| Index: third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7802f8d41713a3a9a9dba2fe0baa87fca1084f18
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| @@ -0,0 +1,365 @@
|
| +// Copyright 2016 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.
|
| +
|
| +WebInspector.SourceMapNamesResolver = {};
|
| +
|
| +WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache");
|
| +WebInspector.SourceMapNamesResolver._cachedPromiseSymbol = Symbol("cache");
|
| +
|
| +/**
|
| + * @param {!WebInspector.DebuggerModel.Scope} scope
|
| + * @return {!Promise.<!Map<string, string>>}
|
| + */
|
| +WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
|
| +{
|
| + var cachedMap = scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol];
|
| + if (cachedMap)
|
| + return Promise.resolve(cachedMap);
|
| +
|
| + var cachedPromise = scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol];
|
| + if (cachedPromise)
|
| + return cachedPromise;
|
| +
|
| + var startLocation = scope.startLocation();
|
| + var endLocation = scope.endLocation();
|
| + var script = startLocation.script();
|
| +
|
| + if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !endLocation || !script.sourceMapURL || script !== endLocation.script())
|
| + return Promise.resolve(new Map());
|
| +
|
| + var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(script);
|
| + if (!sourceMap)
|
| + return Promise.resolve(new Map());
|
| +
|
| + var promise = script.requestContent().then(onContent);
|
| + scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise;
|
| + return promise;
|
| +
|
| + /**
|
| + * @param {?string} content
|
| + * @return {!Map<string, string>}
|
| + */
|
| + function onContent(content)
|
| + {
|
| + if (!content)
|
| + return new Map();
|
| +
|
| + var startLocation = scope.startLocation();
|
| + var endLocation = scope.endLocation();
|
| + var textRange = new WebInspector.TextRange(startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber);
|
| +
|
| + var scopeText = textRange.extract(content);
|
| + var scopeStart = textRange.toSourceRange(content).offset;
|
| + var prefix = "function fui";
|
| + var root = acorn.parse(prefix + scopeText, {});
|
| + var declarators = [];
|
| + var functionDeclarationCounter = 0;
|
| + var walker = new WebInspector.ESTreeWalker(beforeVisit, afterVisit);
|
| +
|
| + /**
|
| + * @param {!ESTree.Node} node
|
| + */
|
| + function beforeVisit(node)
|
| + {
|
| + if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression")
|
| + functionDeclarationCounter++;
|
| +
|
| + if (node.type === "VariableDeclarator" && functionDeclarationCounter === 1)
|
| + declarators.push(node);
|
| + }
|
| +
|
| + /**
|
| + * @param {!ESTree.Node} node
|
| + */
|
| + function afterVisit(node)
|
| + {
|
| + if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression")
|
| + functionDeclarationCounter--;
|
| + }
|
| +
|
| + walker.walk(root);
|
| +
|
| + var namesMapping = new Map();
|
| + var lineEndings = content.lineEndings();
|
| +
|
| + for (var i = 0; i < declarators.length; ++i) {
|
| + var id = declarators[i].id;
|
| + var start = scopeStart + id.start - prefix.length;
|
| +
|
| + var lineNumber = lineEndings.lowerBound(start);
|
| + var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[lineNumber - 1] + 1));
|
| + var entry = sourceMap.findEntry(lineNumber, columnNumber);
|
| + if (entry)
|
| + namesMapping.set(id.name, entry.name);
|
| + }
|
| +
|
| + scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMapping;
|
| + delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol];
|
| + return namesMapping;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * @param {!WebInspector.DebuggerModel.Scope} scope
|
| + * @return {!WebInspector.RemoteObject}
|
| + */
|
| +WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope)
|
| +{
|
| + if (!Runtime.experiments.isEnabled("resolveVariableNames"))
|
| + return scope.object();
|
| +
|
| + var startLocation = scope.startLocation();
|
| + var endLocation = scope.endLocation();
|
| +
|
| + if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !endLocation || !startLocation.script().sourceMapURL || startLocation.script() !== endLocation.script())
|
| + return scope.object();
|
| +
|
| + return new WebInspector.SourceMapNamesResolver.RemoteObject(scope);
|
| +}
|
| +
|
| +/**
|
| + * @constructor
|
| + * @extends {WebInspector.RemoteObject}
|
| + * @param {!WebInspector.DebuggerModel.Scope} scope
|
| + */
|
| +WebInspector.SourceMapNamesResolver.RemoteObject = function(scope)
|
| +{
|
| + WebInspector.RemoteObject.call(this);
|
| + this._scope = scope;
|
| + this._object = scope.object();
|
| +};
|
| +
|
| +WebInspector.SourceMapNamesResolver.RemoteObject.prototype = {
|
| + /**
|
| + * @override
|
| + * @return {?RuntimeAgent.CustomPreview}
|
| + */
|
| + customPreview: function()
|
| + {
|
| + return this._object.customPreview();
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {string}
|
| + */
|
| + get type()
|
| + {
|
| + return this._object.type;
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {string|undefined}
|
| + */
|
| + get subtype()
|
| + {
|
| + return this._object.subtype;
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {string|undefined}
|
| + */
|
| + get description()
|
| + {
|
| + return this._object.description;
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + get hasChildren()
|
| + {
|
| + return this._object.hasChildren;
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {number}
|
| + */
|
| + arrayLength: function()
|
| + {
|
| + return this._object.arrayLength();
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebInspector.RemoteObjectProperty>)} callback
|
| + */
|
| + getOwnProperties: function(callback)
|
| + {
|
| + this._object.getOwnProperties(callback);
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {boolean} accessorPropertiesOnly
|
| + * @param {function(?Array<!WebInspector.RemoteObjectProperty>, ?Array<!WebInspector.RemoteObjectProperty>)} callback
|
| + */
|
| + getAllProperties: function(accessorPropertiesOnly, callback)
|
| + {
|
| + /**
|
| + * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties
|
| + * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties
|
| + * @this {WebInspector.SourceMapNamesResolver.RemoteObject}
|
| + */
|
| + function wrappedCallback(properties, internalProperties)
|
| + {
|
| + WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(resolveNames.bind(null, properties, internalProperties))
|
| + }
|
| +
|
| + /**
|
| + * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties
|
| + * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties
|
| + * @param {!Map<string, string>} namesMapping
|
| + */
|
| + function resolveNames(properties, internalProperties, namesMapping)
|
| + {
|
| + var newProperties = [];
|
| + if (properties) {
|
| + for (var i = 0; i < properties.length; ++i) {
|
| + var property = properties[i];
|
| + var name = namesMapping.get(property.name) || properties[i].name;
|
| + newProperties.push(new WebInspector.RemoteObjectProperty(name, property.value, property.enumerable, property.writable, property.isOwn, property.wasThrown, property.symbol, property.synthetic));
|
| + }
|
| + }
|
| +
|
| + callback(newProperties, internalProperties);
|
| + }
|
| +
|
| + this._object.getAllProperties(accessorPropertiesOnly, wrappedCallback.bind(this));
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {string|!RuntimeAgent.CallArgument} argumentName
|
| + * @param {string} value
|
| + * @param {function(string=)} callback
|
| + */
|
| + setPropertyValue: function(argumentName, value, callback)
|
| + {
|
| + WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(resolveName.bind(this));
|
| +
|
| + /**
|
| + * @param {!Map<string, string>} namesMapping
|
| + * @this {WebInspector.SourceMapNamesResolver.RemoteObject}
|
| + */
|
| + function resolveName(namesMapping)
|
| + {
|
| + var name;
|
| + if (typeof argumentName === "string")
|
| + name = argumentName;
|
| + else
|
| + name = /** @type {string} */ (argumentName.value);
|
| +
|
| + var actualName = name;
|
| + for (var compiledName of namesMapping.keys()) {
|
| + if (namesMapping.get(compiledName) === name) {
|
| + actualName = compiledName;
|
| + break;
|
| + }
|
| + }
|
| + this._object.setPropertyValue(actualName, value, callback);
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {!Promise<?Array<!WebInspector.EventListener>>}
|
| + */
|
| + eventListeners: function()
|
| + {
|
| + return this._object.eventListeners();
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!RuntimeAgent.CallArgument} name
|
| + * @param {function(string=)} callback
|
| + */
|
| + deleteProperty: function(name, callback)
|
| + {
|
| + this._object.deleteProperty(name, callback);
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {function(this:Object, ...)} functionDeclaration
|
| + * @param {!Array<!RuntimeAgent.CallArgument>=} args
|
| + * @param {function(?WebInspector.RemoteObject, boolean=)=} callback
|
| + */
|
| + callFunction: function(functionDeclaration, args, callback)
|
| + {
|
| + this._object.callFunction(functionDeclaration, args, callback);
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {function(this:Object, ...)} functionDeclaration
|
| + * @param {!Array<!RuntimeAgent.CallArgument>|undefined} args
|
| + * @param {function(*)} callback
|
| + */
|
| + callFunctionJSON: function(functionDeclaration, args, callback)
|
| + {
|
| + this._object.callFunctionJSON(functionDeclaration, args, callback);
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {!WebInspector.Target}
|
| + */
|
| + target: function()
|
| + {
|
| + return this._object.target();
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {?WebInspector.DebuggerModel}
|
| + */
|
| + debuggerModel: function()
|
| + {
|
| + return this._object.debuggerModel();
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @return {boolean}
|
| + */
|
| + isNode: function()
|
| + {
|
| + return this._object.isNode();
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback
|
| + */
|
| + functionDetails: function(callback)
|
| + {
|
| + this._object.functionDetails(callback);
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback
|
| + */
|
| + generatorObjectDetails: function(callback)
|
| + {
|
| + this._object.generatorObjectDetails(callback);
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback
|
| + */
|
| + collectionEntries: function(callback)
|
| + {
|
| + this._object.collectionEntries(callback);
|
| + },
|
| +
|
| + __proto__: WebInspector.RemoteObject.prototype
|
| +}
|
|
|