Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(784)

Unified Diff: third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js

Issue 1653053002: Devtools: parse variables scopes and sourcemap them (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
+}

Powered by Google App Engine
This is Rietveld 408576698