From bc4e7ec82c3d21ba81b8a2ec994632e0b21423ff Mon Sep 17 00:00:00 2001 From: Antonin Hildebrand Date: Sun, 1 Nov 2020 16:45:56 +0100 Subject: [PATCH] revert code changes introduced to fix issue 53 It has been causing me headaches when merging official changes. I defer to devtools devs to fix this on their side. https://github.com/binaryage/dirac/issues/53 --- front_end/sources/DebuggerPlugin.js | 76 +++---- front_end/sources/SourceMapNamesResolver.js | 209 +++++++------------- 2 files changed, 92 insertions(+), 193 deletions(-) diff --git a/front_end/sources/DebuggerPlugin.js b/front_end/sources/DebuggerPlugin.js index d3391a67540..42c05f8d365 100644 --- a/front_end/sources/DebuggerPlugin.js +++ b/front_end/sources/DebuggerPlugin.js @@ -1134,29 +1134,13 @@ export class DebuggerPlugin extends Plugin { return; } - /** - * @param {string} name - * @param {number|string=} line - * @param {number|string=} column - * @return {string} - */ - function getLocationId(name, line, column) { - line = line || '?'; - column = column || '?'; - return `${name}@${line}:${column}`; - } - - const infoMap = new Map(); + const valuesMap = new Map(); for (const property of properties) { - const locationId = getLocationId(property.name, property.originalNameLineNumber, property.originalNameColumnNumber); - infoMap.set(locationId, { - name: property.name, - value: property.value - }); + valuesMap.set(property.name, property.value); } /** @type {!Map.>} */ - const infoIdsPerLine = new Map(); + const namesPerLine = new Map(); let skipObjectProperty = false; const tokenizer = new TextEditor.CodeMirrorUtils.TokenizerFactory().createTokenizer('text/javascript'); tokenizer(this._textEditor.line(fromLine).substring(fromColumn), processToken.bind(this, fromLine)); @@ -1173,41 +1157,31 @@ export class DebuggerPlugin extends Plugin { * @this {DebuggerPlugin} */ function processToken(editorLineNumber, tokenValue, tokenType, column, newColumn) { - if (!skipObjectProperty && tokenType && this._isIdentifier(tokenType)) { - let exists = true; - let tokenLocationId = getLocationId(tokenValue, editorLineNumber, column); - if (!infoMap.has(tokenLocationId)) { - tokenLocationId = getLocationId(tokenValue); // a case without source-maps - if (!infoMap.has(tokenLocationId)) { - exists = false; - } - } - if (exists) { - let ids = infoIdsPerLine.get(editorLineNumber); - if (!ids) { - ids = new Set(); - infoIdsPerLine.set(editorLineNumber, ids); - } - ids.add(tokenLocationId); + if (!skipObjectProperty && tokenType && this._isIdentifier(tokenType) && valuesMap.get(tokenValue)) { + let names = namesPerLine.get(editorLineNumber); + if (!names) { + names = new Set(); + namesPerLine.set(editorLineNumber, names); } + names.add(tokenValue); } skipObjectProperty = tokenValue === '.'; } - this._textEditor.operation(this._renderDecorations.bind(this, infoMap, infoIdsPerLine, fromLine, toLine)); + this._textEditor.operation(this._renderDecorations.bind(this, valuesMap, namesPerLine, fromLine, toLine)); } /** - * @param {!Map.} infoMap - * @param {!Map.>} infoIdsPerLine + * @param {!Map.} valuesMap + * @param {!Map.>} namesPerLine * @param {number} fromLine * @param {number} toLine */ - _renderDecorations(infoMap, infoIdsPerLine, fromLine, toLine) { + _renderDecorations(valuesMap, namesPerLine, fromLine, toLine) { const formatter = new ObjectUI.RemoteObjectPreviewFormatter.RemoteObjectPreviewFormatter(); for (let i = fromLine; i < toLine; ++i) { - const infoIds = infoIdsPerLine.get(i); + const names = namesPerLine.get(i); const oldWidget = this._valueWidgets.get(i); - if (!infoIds) { + if (!names) { if (oldWidget) { this._valueWidgets.delete(i); this._textEditor.removeDecoration(oldWidget, i); @@ -1231,21 +1205,21 @@ export class DebuggerPlugin extends Plugin { widget.__nameToToken = new Map(); let renderedNameCount = 0; - for (const infoId of infoIds) { + for (const name of names) { if (renderedNameCount > 10) { break; } - if (infoIdsPerLine.get(i - 1) && infoIdsPerLine.get(i - 1).has(infoId)) { - continue; // Only render name once in the given continuous block. - } + const names = namesPerLine.get(i - 1); + if (names && names.has(name)) { + continue; + } // Only render name once in the given continuous block. if (renderedNameCount) { UI.UIUtils.createTextChild(widget, ', '); } const nameValuePair = /** @type {!HTMLElement} */ (widget.createChild('span')); - widget.__nameToToken.set(infoId, nameValuePair); - const info = infoMap.get(infoId); - UI.UIUtils.createTextChild(nameValuePair, info.name + ' = '); - const value = info.value; + widget.__nameToToken.set(name, nameValuePair); + UI.UIUtils.createTextChild(nameValuePair, name + ' = '); + const value = valuesMap.get(name); if (!value) { throw new Error('value is expected to be null'); } @@ -1258,7 +1232,7 @@ export class DebuggerPlugin extends Plugin { formatter.appendObjectPreview(nameValuePair, value.preview, false /* isEntry */); } else { const propertyValue = ObjectUI.ObjectPropertiesSection.ObjectPropertiesSection.createPropertyValue( - value, /* wasThrown */ false, /* showPreview */ false); + value, /* wasThrown */ false, /* showPreview */ false); nameValuePair.appendChild(propertyValue.element); } ++renderedNameCount; @@ -1276,7 +1250,7 @@ export class DebuggerPlugin extends Plugin { widgetChanged = true; // value has changed, update it. UI.UIUtils.runCSSAnimationOnce( - /** @type {!Element} */ (widget.__nameToToken.get(name)), 'source-frame-value-update-highlight'); + /** @type {!Element} */ (widget.__nameToToken.get(name)), 'source-frame-value-update-highlight'); } } if (widgetChanged) { diff --git a/front_end/sources/SourceMapNamesResolver.js b/front_end/sources/SourceMapNamesResolver.js index 31774933566..c96b64f8d7f 100644 --- a/front_end/sources/SourceMapNamesResolver.js +++ b/front_end/sources/SourceMapNamesResolver.js @@ -30,34 +30,6 @@ export class Identifier { } } -export class NameDescriptor { - /** - * @param {string} name - * @param {number|undefined} lineNumber - * @param {number|undefined} columnNumber - */ - constructor(name, lineNumber, columnNumber) { - this.name = name; - this.lineNumber = lineNumber; - this.columnNumber = columnNumber; - } -} - - -export class MappingRecord { - /** - * @param {!NameDescriptor} compiledNameDescriptor - * @param {!NameDescriptor} originalNameDescriptor - */ - constructor(compiledNameDescriptor, originalNameDescriptor) { - this.compiledNameDescriptor = compiledNameDescriptor; - this.originalNameDescriptor = originalNameDescriptor; - } -} - -export class Mapping extends Array { -} - /** * @param {!SDK.DebuggerModel.ScopeChainEntry} scope * @return {!Promise>} @@ -119,7 +91,7 @@ export const scopeIdentifiers = function(scope) { /** * @param {!SDK.DebuggerModel.ScopeChainEntry} scope - * @return {!Promise} + * @return {!Promise.>} */ export const resolveScope = function(scope) { let identifiersPromise = scopeToCachedIdentifiersMap.get(scope); @@ -130,7 +102,7 @@ export const resolveScope = function(scope) { const script = scope.callFrame().script; const sourceMap = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().sourceMapForScript(script); if (!sourceMap) { - return Promise.resolve(/** @type {!Mapping} */([])); + return Promise.resolve(new Map()); } /** @type {!Map} */ @@ -141,11 +113,10 @@ export const resolveScope = function(scope) { /** * @param {!Array} identifiers - * @return {!Promise} + * @return {!Promise>} */ function onIdentifiers(identifiers) { - const namesMapping = /** @type {!Mapping} */([]); - const missingIdentifiers = []; + const namesMapping = new Map(); // Extract as much as possible from SourceMap. for (let i = 0; i < identifiers.length; ++i) { const id = identifiers[i]; @@ -154,39 +125,38 @@ export const resolveScope = function(scope) { } const entry = sourceMap.findEntry(id.lineNumber, id.columnNumber); if (entry && entry.name) { - const compiled = new NameDescriptor(id.name, id.lineNumber, id.columnNumber); - const original = new NameDescriptor(entry.name, entry.sourceLineNumber, entry.sourceColumnNumber); - namesMapping.push(new MappingRecord(compiled, original)); - } else { - missingIdentifiers.push(id); + namesMapping.set(id.name, entry.name); } } // Resolve missing identifier names from sourcemap ranges. - const promises = missingIdentifiers.map(id => { - return resolveSourceName(id).then( - (originalNameDescriptor) => onSourceNameResolved(namesMapping, id, originalNameDescriptor)) - }); - return Promise.all(promises) - .then(() => namesMapping); + const promises = []; + for (let i = 0; i < identifiers.length; ++i) { + const id = identifiers[i]; + if (namesMapping.has(id.name)) { + continue; + } + const promise = resolveSourceName(id).then(onSourceNameResolved.bind(null, namesMapping, id)); + promises.push(promise); + } + return Promise.all(promises).then(getScopeResolvedForTest()).then(() => namesMapping); } /** - * @param {!Mapping} namesMapping + * @param {!Map} namesMapping * @param {!Identifier} id - * @param {?NameDescriptor} originalNameDescriptor + * @param {?string} sourceName */ - function onSourceNameResolved(namesMapping, id, originalNameDescriptor) { - if (!originalNameDescriptor) { + function onSourceNameResolved(namesMapping, id, sourceName) { + if (!sourceName) { return; } - const compiled = new NameDescriptor(id.name, id.lineNumber, id.columnNumber); - namesMapping.push(new MappingRecord(compiled, originalNameDescriptor)); + namesMapping.set(id.name, sourceName); } /** * @param {!Identifier} id - * @return {!Promise} + * @return {!Promise} */ function resolveSourceName(id) { const startEntry = sourceMap ? sourceMap.findEntry(id.lineNumber, id.columnNumber) : null; @@ -194,7 +164,7 @@ export const resolveScope = function(scope) { if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sourceURL !== endEntry.sourceURL || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber) { - return Promise.resolve(null); + return Promise.resolve(/** @type {?string} */ (null)); } const sourceTextRange = new TextUtils.TextRange.TextRange( startEntry.sourceLineNumber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber, @@ -203,23 +173,21 @@ export const resolveScope = function(scope) { Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().uiSourceCodeForSourceMapSourceURL( script.debuggerModel, startEntry.sourceURL, script.isContentScript()); if (!uiSourceCode) { - return Promise.resolve(null); + return Promise.resolve(/** @type {?string} */ (null)); } return uiSourceCode.requestContent().then(deferredContent => { const content = deferredContent.content; - return onSourceContent(sourceTextRange, startEntry.sourceLineNumber || 1, startEntry.sourceColumnNumber || 1, content); + return onSourceContent(sourceTextRange, content); }); } /** * @param {!TextUtils.TextRange.TextRange} sourceTextRange - * @param {number} line - * @param {number} column * @param {?string} content - * @return {?NameDescriptor} + * @return {?string} */ - function onSourceContent(sourceTextRange, line, column, content) { + function onSourceContent(sourceTextRange, content) { if (!content) { return null; } @@ -229,16 +197,13 @@ export const resolveScope = function(scope) { textCache.set(content, text); } const originalIdentifier = text.extract(sourceTextRange).trim(); - if (!/[a-zA-Z0-9_$]+/.test(originalIdentifier)) { - return null; - } - return new NameDescriptor(originalIdentifier, line, column); + return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier : null; } }; /** * @param {!SDK.DebuggerModel.CallFrame} callFrame - * @return {!Promise} + * @return {!Promise.>} */ export const allVariablesInCallFrame = function(callFrame) { const cached = cachedMapBycallFrame.get(callFrame); @@ -255,56 +220,23 @@ export const allVariablesInCallFrame = function(callFrame) { return Promise.all(promises).then(mergeVariables); /** - * @param {!Array} nameMappings - * @return {!Mapping} + * @param {!Array>} nameMappings + * @return {!Map} */ function mergeVariables(nameMappings) { - const mapping = /** @type {!Mapping} */(Array.prototype.concat.apply([], nameMappings)); - callFrame[cachedMapSymbol] = mapping; - return mapping; - } -}; - -/** - * @param {!Mapping} mapping - * @param {string} name - * @param {number} line - * @param {number} column - * @return {?MappingRecord} - */ -const lookupMappingRecordForOriginalName = function(mapping, name, line, column) { - const res = mapping.filter(value => { - const desc = value.originalNameDescriptor; - return desc.name === name && desc.lineNumber === line && desc.columnNumber === column; - }); - if (res.length !== 1) { - return null; + /** @type {!Map} */ + const reverseMapping = new Map(); + for (const map of nameMappings) { + for (const compiledName of map.keys()) { + const originalName = map.get(compiledName); + if (originalName && !reverseMapping.has(originalName)) { + reverseMapping.set(originalName, compiledName); + } + } + } + cachedMapBycallFrame.set(callFrame, reverseMapping); + return reverseMapping; } - return res[0]; -}; - -/** - * @param {!Mapping} mapping - * @param {string} name - * @return {!Array} - */ -const collectMappingRecordsForOriginalName = function(mapping, name) { - return mapping.filter(value => { - const desc = value.originalNameDescriptor; - return desc.name === name; - }); -}; - -/** - * @param {!Mapping} mapping - * @param {string} name - * @return {!Array} - */ -const collectMappingRecordsForCompiledName = function(mapping, name) { - return mapping.filter(value => { - const desc = value.compiledNameDescriptor; - return desc.name === name; - }); }; /** @@ -333,14 +265,12 @@ export const resolveExpression = function( /** * @param {!SDK.DebuggerModel.DebuggerModel} debuggerModel - * @param {!Mapping} mapping + * @param {!Map} reverseMapping * @return {!Promise} */ - function findCompiledName(debuggerModel, mapping) { - const record = lookupMappingRecordForOriginalName(mapping, - originalText, lineNumber, startColumnNumber); - if (record) { - return Promise.resolve(record.compiledNameDescriptor.name); + function findCompiledName(debuggerModel, reverseMapping) { + if (reverseMapping.has(originalText)) { + return Promise.resolve(reverseMapping.get(originalText) || ''); } return resolveExpressionAsync(debuggerModel, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber); @@ -409,7 +339,7 @@ export const resolveExpressionAsync = */ export const resolveThisObject = function(callFrame) { if (!callFrame) { - return Promise.resolve(null); + return Promise.resolve(/** @type {?SDK.RemoteObject.RemoteObject} */ (null)); } if (!callFrame.scopeChain().length) { return Promise.resolve(callFrame.thisObject()); @@ -418,19 +348,23 @@ export const resolveThisObject = function(callFrame) { return resolveScope(callFrame.scopeChain()[0]).then(onScopeResolved); /** - * @param {!Mapping} namesMapping + * @param {!Map} namesMapping * @return {!Promise} */ function onScopeResolved(namesMapping) { - const thisRecords = collectMappingRecordsForOriginalName(namesMapping, 'this'); - if (thisRecords.size !== 1) { + const thisMappings = Platform.MapUtilities.inverse(namesMapping).get('this'); + if (!callFrame) { + return Promise.resolve(null); + } + + if (!thisMappings || thisMappings.size !== 1) { return Promise.resolve(callFrame.thisObject()); } - const compiledName = thisRecords[0].compiledNameDescriptor.name; + const thisMapping = thisMappings.values().next().value; return callFrame .evaluate(/** @type {!SDK.RuntimeModel.EvaluationOptions} */ ({ - expression: compiledName, + expression: thisMapping, objectGroup: 'backtrace', includeCommandLineAPI: false, silent: true, @@ -578,23 +512,13 @@ export class RemoteObject extends SDK.RemoteObject.RemoteObject { if (properties) { for (let i = 0; i < properties.length; ++i) { const property = properties[i]; - let name = property.name; - const propertyMapping = collectMappingRecordsForCompiledName(namesMapping, name); - if (propertyMapping.length > 0) { - // TODO: how to resolve the case when compiled name matches multiple original names? - // currently we don't have any information in property which would help us decide which one to take - name = propertyMapping[0].originalNameDescriptor.name; - } - const newProperty = new SDK.RemoteObject.RemoteObjectProperty( - name, property.value, property.enumerable, property.writable, property.isOwn, property.wasThrown, - property.symbol, property.synthetic); - if (propertyMapping.length > 0) { - // this is for _prepareScopeVariables, TODO: figure out a better way how to pass this info - newProperty.originalNameLineNumber = propertyMapping[0].originalNameDescriptor.lineNumber; - newProperty.originalNameColumnNumber = propertyMapping[0].originalNameDescriptor.columnNumber; + const name = namesMapping.get(property.name) || properties[i].name; + if (!property.value) { + continue; } - newProperties.push(newProperty); - newProperties[newProperties.length - 1].resolutionSourceProperty = property; + newProperties.push(new SDK.RemoteObject.RemoteObjectProperty( + name, property.value, property.enumerable, property.writable, property.isOwn, property.wasThrown, + property.symbol, property.synthetic)); } } return {properties: newProperties, internalProperties: internalProperties}; @@ -617,10 +541,11 @@ export class RemoteObject extends SDK.RemoteObject.RemoteObject { } let actualName = name; - const matchingRecords = collectMappingRecordsForOriginalName(namesMapping, name); - if (matchingRecords.length > 0) { - // TODO: how to resolve the case when original name matches multiple compiled names? - actualName = matchingRecords[0].compiledNameDescriptor.name; + for (const compiledName of namesMapping.keys()) { + if (namesMapping.get(compiledName) === name) { + actualName = compiledName; + break; + } } return this._object.setPropertyValue(actualName, value); }