All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
META-INF.dirigible.dev-tools.object_ui.RemoteObjectPreviewFormatter.js Maven / Gradle / Ivy
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as Common from '../common/common.js';
import * as SDK from '../sdk/sdk.js';
/**
* @unrestricted
*/
export class RemoteObjectPreviewFormatter {
/**
* @param {!Protocol.Runtime.PropertyPreview} a
* @param {!Protocol.Runtime.PropertyPreview} b
* @return {number}
*/
static _objectPropertyComparator(a, b) {
return sortValue(a) - sortValue(b);
/**
* @param {!Protocol.Runtime.PropertyPreview} property
* @return {number}
*/
function sortValue(property) {
// TODO(einbinder) expose whether preview properties are actually internal.
const internalName = _internalName;
if (property.name === internalName.PromiseStatus) {
return 1;
}
if (property.name === internalName.PromiseValue) {
return 2;
}
if (property.name === internalName.GeneratorStatus || property.name === internalName.PrimitiveValue) {
return 3;
}
// TODO(einbinder) expose whether preview properties are actually private.
if (property.type !== 'function' && !property.name.startsWith('#')) {
return 4;
}
return 5;
}
}
/**
* @param {!DocumentFragment|!Element} parentElement
* @param {!Protocol.Runtime.ObjectPreview} preview
* @param {boolean} isEntry
*/
appendObjectPreview(parentElement, preview, isEntry) {
const description = preview.description;
const subTypesWithoutValuePreview = new Set(['null', 'regexp', 'error', 'internal#entry']);
if (preview.type !== 'object' || subTypesWithoutValuePreview.has(preview.subtype) || isEntry) {
parentElement.appendChild(this.renderPropertyPreview(preview.type, preview.subtype, description));
return;
}
const isArrayOrTypedArray = preview.subtype === 'array' || preview.subtype === 'typedarray';
if (description) {
let text;
if (isArrayOrTypedArray) {
const arrayLength = SDK.RemoteObject.RemoteObject.arrayLength(preview);
const arrayLengthText = arrayLength > 1 ? ('(' + arrayLength + ')') : '';
const arrayName = SDK.RemoteObject.RemoteObject.arrayNameFromDescription(description);
text = arrayName === 'Array' ? arrayLengthText : (arrayName + arrayLengthText);
} else {
const hideDescription = description === 'Object';
text = hideDescription ? '' : description;
}
if (text.length > 0) {
parentElement.createChild('span', 'object-description').textContent = text + '\xA0';
}
}
const propertiesElement = parentElement.createChild('span', 'object-properties-preview');
propertiesElement.createTextChild(isArrayOrTypedArray ? '[' : '{');
if (preview.entries) {
this._appendEntriesPreview(propertiesElement, preview);
} else if (isArrayOrTypedArray) {
this._appendArrayPropertiesPreview(propertiesElement, preview);
} else {
this._appendObjectPropertiesPreview(propertiesElement, preview);
}
if (preview.overflow) {
const ellipsisText = propertiesElement.textContent.length > 1 ? ',\xA0…' : '…';
propertiesElement.createChild('span').textContent = ellipsisText;
}
propertiesElement.createTextChild(isArrayOrTypedArray ? ']' : '}');
}
/**
* @param {string} description
* @return {string}
*/
_abbreviateFullQualifiedClassName(description) {
const abbreviatedDescription = description.split('.');
for (let i = 0; i < abbreviatedDescription.length - 1; ++i) {
abbreviatedDescription[i] = abbreviatedDescription[i].trimMiddle(3);
}
return abbreviatedDescription.join('.');
}
/**
* @param {!Element} parentElement
* @param {!Protocol.Runtime.ObjectPreview} preview
*/
_appendObjectPropertiesPreview(parentElement, preview) {
const internalName = _internalName;
const properties = preview.properties.filter(p => p.type !== 'accessor')
.sort(RemoteObjectPreviewFormatter._objectPropertyComparator);
for (let i = 0; i < properties.length; ++i) {
if (i > 0) {
parentElement.createTextChild(', ');
}
const property = properties[i];
const name = property.name;
// Internal properties are given special formatting, e.g. Promises `: 123`.
if (preview.subtype === 'promise' && name === internalName.PromiseStatus) {
parentElement.appendChild(this._renderDisplayName('<' + property.value + '>'));
const nextProperty = i + 1 < properties.length ? properties[i + 1] : null;
if (nextProperty && nextProperty.name === internalName.PromiseValue) {
if (property.value !== 'pending') {
parentElement.createTextChild(': ');
parentElement.appendChild(this._renderPropertyPreviewOrAccessor([nextProperty]));
}
i++;
}
} else if (preview.subtype === 'generator' && name === internalName.GeneratorStatus) {
parentElement.appendChild(this._renderDisplayName('<' + property.value + '>'));
} else if (name === internalName.PrimitiveValue) {
parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));
} else {
parentElement.appendChild(this._renderDisplayName(name));
parentElement.createTextChild(': ');
parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));
}
}
}
/**
* @param {!Element} parentElement
* @param {!Protocol.Runtime.ObjectPreview} preview
*/
_appendArrayPropertiesPreview(parentElement, preview) {
const arrayLength = SDK.RemoteObject.RemoteObject.arrayLength(preview);
const indexProperties = preview.properties.filter(p => toArrayIndex(p.name) !== -1).sort(arrayEntryComparator);
const otherProperties = preview.properties.filter(p => toArrayIndex(p.name) === -1)
.sort(RemoteObjectPreviewFormatter._objectPropertyComparator);
/**
* @param {!Protocol.Runtime.PropertyPreview} a
* @param {!Protocol.Runtime.PropertyPreview} b
* @return {number}
*/
function arrayEntryComparator(a, b) {
return toArrayIndex(a.name) - toArrayIndex(b.name);
}
/**
* @param {string} name
* @return {number}
*/
function toArrayIndex(name) {
const index = name >>> 0;
if (String(index) === name && index < arrayLength) {
return index;
}
return -1;
}
// Gaps can be shown when all properties are guaranteed to be in the preview.
const canShowGaps = !preview.overflow;
let lastNonEmptyArrayIndex = -1;
let elementsAdded = false;
for (let i = 0; i < indexProperties.length; ++i) {
if (elementsAdded) {
parentElement.createTextChild(', ');
}
const property = indexProperties[i];
const index = toArrayIndex(property.name);
if (canShowGaps && index - lastNonEmptyArrayIndex > 1) {
appendUndefined(index);
parentElement.createTextChild(', ');
}
if (!canShowGaps && i !== index) {
parentElement.appendChild(this._renderDisplayName(property.name));
parentElement.createTextChild(': ');
}
parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));
lastNonEmptyArrayIndex = index;
elementsAdded = true;
}
if (canShowGaps && arrayLength - lastNonEmptyArrayIndex > 1) {
if (elementsAdded) {
parentElement.createTextChild(', ');
}
appendUndefined(arrayLength);
}
for (let i = 0; i < otherProperties.length; ++i) {
if (elementsAdded) {
parentElement.createTextChild(', ');
}
const property = otherProperties[i];
parentElement.appendChild(this._renderDisplayName(property.name));
parentElement.createTextChild(': ');
parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));
elementsAdded = true;
}
/**
* @param {number} index
*/
function appendUndefined(index) {
const span = parentElement.createChild('span', 'object-value-undefined');
const count = index - lastNonEmptyArrayIndex - 1;
span.textContent =
count !== 1 ? Common.UIString.UIString('empty × %d', count) : Common.UIString.UIString('empty');
elementsAdded = true;
}
}
/**
* @param {!Element} parentElement
* @param {!Protocol.Runtime.ObjectPreview} preview
*/
_appendEntriesPreview(parentElement, preview) {
for (let i = 0; i < preview.entries.length; ++i) {
if (i > 0) {
parentElement.createTextChild(', ');
}
const entry = preview.entries[i];
if (entry.key) {
this.appendObjectPreview(parentElement, entry.key, true /* isEntry */);
parentElement.createTextChild(' => ');
}
this.appendObjectPreview(parentElement, entry.value, true /* isEntry */);
}
}
/**
* @param {string} name
* @return {!Element}
*/
_renderDisplayName(name) {
const result = createElementWithClass('span', 'name');
const needsQuotes = /^\s|\s$|^$|\n/.test(name);
result.textContent = needsQuotes ? '"' + name.replace(/\n/g, '\u21B5') + '"' : name;
return result;
}
/**
* @param {!Array.} propertyPath
* @return {!Element}
*/
_renderPropertyPreviewOrAccessor(propertyPath) {
const property = propertyPath.peekLast();
return this.renderPropertyPreview(property.type, /** @type {string} */ (property.subtype), property.value);
}
/**
* @param {string} type
* @param {string=} subtype
* @param {string=} description
* @return {!Element}
*/
renderPropertyPreview(type, subtype, description) {
const span = createElementWithClass('span', 'object-value-' + (subtype || type));
description = description || '';
if (type === 'accessor') {
span.textContent = '(...)';
span.title = Common.UIString.UIString('The property is computed with a getter');
return span;
}
if (type === 'function') {
span.textContent = '\u0192';
return span;
}
if (type === 'object' && subtype === 'node' && description) {
createSpansForNodeTitle(span, description);
return span;
}
if (type === 'string') {
span.createTextChildren('"', description.replace(/\n/g, '\u21B5'), '"');
return span;
}
if (type === 'object' && !subtype) {
let preview = this._abbreviateFullQualifiedClassName(description);
if (preview === 'Object') {
preview = '{…}';
}
span.textContent = preview;
span.title = description;
return span;
}
span.textContent = description;
return span;
}
}
/** @enum {string} */
const _internalName = {
GeneratorStatus: '[[GeneratorStatus]]',
PrimitiveValue: '[[PrimitiveValue]]',
PromiseStatus: '[[PromiseStatus]]',
PromiseValue: '[[PromiseValue]]'
};
/**
* @param {!Element} container
* @param {string} nodeTitle
*/
export const createSpansForNodeTitle = function(container, nodeTitle) {
const match = nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/);
container.createChild('span', 'webkit-html-tag-name').textContent = match[1];
if (match[2]) {
container.createChild('span', 'webkit-html-attribute-value').textContent = match[2];
}
if (match[3]) {
container.createChild('span', 'webkit-html-attribute-name').textContent = match[3];
}
};