1147 lines
49 KiB
JavaScript
1147 lines
49 KiB
JavaScript
/*
|
|
* Copyright (C) 2014-2017 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
WebInspector.ScriptSyntaxTree = class ScriptSyntaxTree extends WebInspector.Object
|
|
{
|
|
constructor(sourceText, script)
|
|
{
|
|
super();
|
|
|
|
console.assert(script && script instanceof WebInspector.Script, script);
|
|
|
|
this._script = script;
|
|
|
|
try {
|
|
let sourceType = this._script.sourceType === WebInspector.Script.SourceType.Module ? "module" : "script";
|
|
let esprimaSyntaxTree = esprima.parse(sourceText, {range: true, sourceType});
|
|
this._syntaxTree = this._createInternalSyntaxTree(esprimaSyntaxTree);
|
|
this._parsedSuccessfully = true;
|
|
} catch (error) {
|
|
this._parsedSuccessfully = false;
|
|
this._syntaxTree = null;
|
|
console.error("Couldn't parse JavaScript File: " + script.url, error);
|
|
}
|
|
}
|
|
|
|
// Public
|
|
|
|
get parsedSuccessfully()
|
|
{
|
|
return this._parsedSuccessfully;
|
|
}
|
|
|
|
forEachNode(callback)
|
|
{
|
|
console.assert(this._parsedSuccessfully);
|
|
if (!this._parsedSuccessfully)
|
|
return;
|
|
|
|
this._recurse(this._syntaxTree, callback, this._defaultParserState());
|
|
}
|
|
|
|
filter(predicate, startNode)
|
|
{
|
|
console.assert(startNode && this._parsedSuccessfully);
|
|
if (!this._parsedSuccessfully)
|
|
return [];
|
|
|
|
var nodes = [];
|
|
function filter(node, state)
|
|
{
|
|
if (predicate(node))
|
|
nodes.push(node);
|
|
else
|
|
state.skipChildNodes = true;
|
|
}
|
|
|
|
this._recurse(startNode, filter, this._defaultParserState());
|
|
|
|
return nodes;
|
|
}
|
|
|
|
containersOfOffset(offset)
|
|
{
|
|
console.assert(this._parsedSuccessfully);
|
|
if (!this._parsedSuccessfully)
|
|
return [];
|
|
|
|
let allNodes = [];
|
|
const start = 0;
|
|
const end = 1;
|
|
|
|
this.forEachNode((node, state) => {
|
|
if (node.range[end] < offset)
|
|
state.skipChildNodes = true;
|
|
if (node.range[start] > offset)
|
|
state.shouldStopEarly = true;
|
|
if (node.range[start] <= offset && node.range[end] >= offset)
|
|
allNodes.push(node);
|
|
});
|
|
|
|
return allNodes;
|
|
}
|
|
|
|
filterByRange(startOffset, endOffset)
|
|
{
|
|
console.assert(this._parsedSuccessfully);
|
|
if (!this._parsedSuccessfully)
|
|
return [];
|
|
|
|
var allNodes = [];
|
|
var start = 0;
|
|
var end = 1;
|
|
function filterForNodesInRange(node, state)
|
|
{
|
|
// program start range program end
|
|
// [ [ ] ]
|
|
// [ ] [ [ ] ] [ ]
|
|
|
|
// If a node's range ends before the range we're interested in starts, we don't need to search any of its
|
|
// enclosing ranges, because, by definition, those enclosing ranges are contained within this node's range.
|
|
if (node.range[end] < startOffset)
|
|
state.skipChildNodes = true;
|
|
|
|
// We are only interested in nodes whose start position is within our range.
|
|
if (startOffset <= node.range[start] && node.range[start] <= endOffset)
|
|
allNodes.push(node);
|
|
|
|
// Once we see nodes that start beyond our range, we can quit traversing the AST. We can do this safely
|
|
// because we know the AST is traversed using depth first search, so it will traverse into enclosing ranges
|
|
// before it traverses into adjacent ranges.
|
|
if (node.range[start] > endOffset)
|
|
state.shouldStopEarly = true;
|
|
}
|
|
|
|
this.forEachNode(filterForNodesInRange);
|
|
|
|
return allNodes;
|
|
}
|
|
|
|
containsNonEmptyReturnStatement(startNode)
|
|
{
|
|
console.assert(startNode && this._parsedSuccessfully);
|
|
if (!this._parsedSuccessfully)
|
|
return false;
|
|
|
|
if (startNode.attachments._hasNonEmptyReturnStatement !== undefined)
|
|
return startNode.attachments._hasNonEmptyReturnStatement;
|
|
|
|
function removeFunctionsFilter(node)
|
|
{
|
|
return node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression
|
|
&& node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration
|
|
&& node.type !== WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression;
|
|
}
|
|
|
|
var nodes = this.filter(removeFunctionsFilter, startNode);
|
|
var hasNonEmptyReturnStatement = false;
|
|
var returnStatementType = WebInspector.ScriptSyntaxTree.NodeType.ReturnStatement;
|
|
for (var node of nodes) {
|
|
if (node.type === returnStatementType && node.argument) {
|
|
hasNonEmptyReturnStatement = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
startNode.attachments._hasNonEmptyReturnStatement = hasNonEmptyReturnStatement;
|
|
|
|
return hasNonEmptyReturnStatement;
|
|
}
|
|
|
|
static functionReturnDivot(node)
|
|
{
|
|
console.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration || node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression || node.type === WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition || node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression);
|
|
|
|
// COMPATIBILITY (iOS 9): Legacy Backends view the return type as being the opening "{" of the function body.
|
|
// After iOS 9, this is to move to the start of the function statement/expression. See below:
|
|
// FIXME: Need a better way to determine backend versions. Using DOM.pseudoElement because that was added after iOS 9.
|
|
if (!DOMAgent.hasEvent("pseudoElementAdded"))
|
|
return node.body.range[0];
|
|
|
|
// "f" in "function". "s" in "set". "g" in "get". First letter in any method name for classes and object literals.
|
|
// The "[" for computed methods in classes and object literals.
|
|
return node.typeProfilingReturnDivot;
|
|
}
|
|
|
|
updateTypes(nodesToUpdate, callback)
|
|
{
|
|
console.assert(RuntimeAgent.getRuntimeTypesForVariablesAtOffsets);
|
|
console.assert(Array.isArray(nodesToUpdate) && this._parsedSuccessfully);
|
|
|
|
if (!this._parsedSuccessfully)
|
|
return;
|
|
|
|
var allRequests = [];
|
|
var allRequestNodes = [];
|
|
var sourceID = this._script.id;
|
|
|
|
for (var node of nodesToUpdate) {
|
|
switch (node.type) {
|
|
case WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression:
|
|
for (var param of node.params) {
|
|
for (var identifier of this._gatherIdentifiersInDeclaration(param)) {
|
|
allRequests.push({
|
|
typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,
|
|
sourceID,
|
|
divot: identifier.range[0]
|
|
});
|
|
allRequestNodes.push(identifier);
|
|
}
|
|
}
|
|
|
|
allRequests.push({
|
|
typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.FunctionReturn,
|
|
sourceID,
|
|
divot: WebInspector.ScriptSyntaxTree.functionReturnDivot(node)
|
|
});
|
|
allRequestNodes.push(node);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator:
|
|
for (var identifier of this._gatherIdentifiersInDeclaration(node.id)) {
|
|
allRequests.push({
|
|
typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,
|
|
sourceID,
|
|
divot: identifier.range[0]
|
|
});
|
|
allRequestNodes.push(identifier);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
console.assert(allRequests.length === allRequestNodes.length);
|
|
|
|
function handleTypes(error, typeInformationArray)
|
|
{
|
|
if (error)
|
|
return;
|
|
|
|
console.assert(typeInformationArray.length === allRequests.length);
|
|
|
|
for (var i = 0; i < typeInformationArray.length; i++) {
|
|
var node = allRequestNodes[i];
|
|
var typeInformation = WebInspector.TypeDescription.fromPayload(typeInformationArray[i]);
|
|
if (allRequests[i].typeInformationDescriptor === WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.FunctionReturn)
|
|
node.attachments.returnTypes = typeInformation;
|
|
else
|
|
node.attachments.types = typeInformation;
|
|
}
|
|
|
|
callback(allRequestNodes);
|
|
}
|
|
|
|
this._script.target.RuntimeAgent.getRuntimeTypesForVariablesAtOffsets(allRequests, handleTypes);
|
|
}
|
|
|
|
// Private
|
|
|
|
_gatherIdentifiersInDeclaration(node)
|
|
{
|
|
function gatherIdentifiers(node)
|
|
{
|
|
switch (node.type) {
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Identifier:
|
|
return [node];
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Property:
|
|
return gatherIdentifiers(node.value);
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern:
|
|
var identifiers = [];
|
|
for (var property of node.properties) {
|
|
for (var identifier of gatherIdentifiers(property))
|
|
identifiers.push(identifier);
|
|
}
|
|
return identifiers;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern:
|
|
var identifiers = [];
|
|
for (var element of node.elements) {
|
|
for (var identifier of gatherIdentifiers(element))
|
|
identifiers.push(identifier);
|
|
}
|
|
return identifiers;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern:
|
|
return gatherIdentifiers(node.left);
|
|
case WebInspector.ScriptSyntaxTree.NodeType.RestElement:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.RestProperty:
|
|
return gatherIdentifiers(node.argument);
|
|
default:
|
|
console.assert(false, "Unexpected node type in variable declarator: " + node.type);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
console.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.Identifier || node.type === WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern || node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern || node.type === WebInspector.ScriptSyntaxTree.NodeType.RestElement || node.type === WebInspector.ScriptSyntaxTree.NodeType.RestProperty);
|
|
|
|
return gatherIdentifiers(node);
|
|
}
|
|
|
|
_defaultParserState()
|
|
{
|
|
return {
|
|
shouldStopEarly: false,
|
|
skipChildNodes: false
|
|
};
|
|
}
|
|
|
|
_recurse(node, callback, state)
|
|
{
|
|
if (!node)
|
|
return;
|
|
|
|
if (state.shouldStopEarly || state.skipChildNodes)
|
|
return;
|
|
|
|
callback(node, state);
|
|
|
|
switch (node.type) {
|
|
case WebInspector.ScriptSyntaxTree.NodeType.AssignmentExpression:
|
|
this._recurse(node.left, callback, state);
|
|
this._recurse(node.right, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern:
|
|
this._recurseArray(node.elements, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern:
|
|
this._recurse(node.left, callback, state);
|
|
this._recurse(node.right, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.AwaitExpression:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.BlockStatement:
|
|
this._recurseArray(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.BinaryExpression:
|
|
this._recurse(node.left, callback, state);
|
|
this._recurse(node.right, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.BreakStatement:
|
|
this._recurse(node.label, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.CatchClause:
|
|
this._recurse(node.param, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.CallExpression:
|
|
this._recurse(node.callee, callback, state);
|
|
this._recurseArray(node.arguments, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ClassBody:
|
|
this._recurseArray(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ClassDeclaration:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ClassExpression:
|
|
this._recurse(node.id, callback, state);
|
|
this._recurse(node.superClass, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ContinueStatement:
|
|
this._recurse(node.label, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.DoWhileStatement:
|
|
this._recurse(node.body, callback, state);
|
|
this._recurse(node.test, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement:
|
|
this._recurse(node.expression, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ForStatement:
|
|
this._recurse(node.init, callback, state);
|
|
this._recurse(node.test, callback, state);
|
|
this._recurse(node.update, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ForInStatement:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ForOfStatement:
|
|
this._recurse(node.left, callback, state);
|
|
this._recurse(node.right, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression:
|
|
this._recurse(node.id, callback, state);
|
|
this._recurseArray(node.params, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.IfStatement:
|
|
this._recurse(node.test, callback, state);
|
|
this._recurse(node.consequent, callback, state);
|
|
this._recurse(node.alternate, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.LabeledStatement:
|
|
this._recurse(node.label, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.LogicalExpression:
|
|
this._recurse(node.left, callback, state);
|
|
this._recurse(node.right, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.MemberExpression:
|
|
this._recurse(node.object, callback, state);
|
|
this._recurse(node.property, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition:
|
|
this._recurse(node.key, callback, state);
|
|
this._recurse(node.value, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.NewExpression:
|
|
this._recurse(node.callee, callback, state);
|
|
this._recurseArray(node.arguments, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ObjectExpression:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern:
|
|
this._recurseArray(node.properties, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Program:
|
|
this._recurseArray(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Property:
|
|
this._recurse(node.key, callback, state);
|
|
this._recurse(node.value, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.RestElement:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.RestProperty:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ReturnStatement:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.SequenceExpression:
|
|
this._recurseArray(node.expressions, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.SpreadElement:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.SpreadProperty:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.SwitchStatement:
|
|
this._recurse(node.discriminant, callback, state);
|
|
this._recurseArray(node.cases, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.SwitchCase:
|
|
this._recurse(node.test, callback, state);
|
|
this._recurseArray(node.consequent, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ConditionalExpression:
|
|
this._recurse(node.test, callback, state);
|
|
this._recurse(node.consequent, callback, state);
|
|
this._recurse(node.alternate, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.TaggedTemplateExpression:
|
|
this._recurse(node.tag, callback, state);
|
|
this._recurse(node.quasi, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.TemplateLiteral:
|
|
this._recurseArray(node.quasis, callback, state);
|
|
this._recurseArray(node.expressions, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ThrowStatement:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.TryStatement:
|
|
this._recurse(node.block, callback, state);
|
|
this._recurse(node.handler, callback, state);
|
|
this._recurse(node.finalizer, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.UnaryExpression:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.UpdateExpression:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.VariableDeclaration:
|
|
this._recurseArray(node.declarations, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator:
|
|
this._recurse(node.id, callback, state);
|
|
this._recurse(node.init, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.WhileStatement:
|
|
this._recurse(node.test, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.WithStatement:
|
|
this._recurse(node.object, callback, state);
|
|
this._recurse(node.body, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.YieldExpression:
|
|
this._recurse(node.argument, callback, state);
|
|
break;
|
|
|
|
// Modules.
|
|
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ExportAllDeclaration:
|
|
this._recurse(node.source, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ExportNamedDeclaration:
|
|
this._recurse(node.declaration, callback, state);
|
|
this._recurseArray(node.specifiers, callback, state);
|
|
this._recurse(node.source, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ExportDefaultDeclaration:
|
|
this._recurse(node.declaration, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ExportSpecifier:
|
|
this._recurse(node.local, callback, state);
|
|
this._recurse(node.exported, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ImportDeclaration:
|
|
this._recurseArray(node.specifiers, callback, state);
|
|
this._recurse(node.source, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ImportDefaultSpecifier:
|
|
this._recurse(node.local, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ImportNamespaceSpecifier:
|
|
this._recurse(node.local, callback, state);
|
|
break;
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ImportSpecifier:
|
|
this._recurse(node.imported, callback, state);
|
|
this._recurse(node.local, callback, state);
|
|
break;
|
|
|
|
// All the leaf nodes go here.
|
|
case WebInspector.ScriptSyntaxTree.NodeType.DebuggerStatement:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.EmptyStatement:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Identifier:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Import:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Literal:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.MetaProperty:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.Super:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.ThisExpression:
|
|
case WebInspector.ScriptSyntaxTree.NodeType.TemplateElement:
|
|
break;
|
|
}
|
|
|
|
state.skipChildNodes = false;
|
|
}
|
|
|
|
_recurseArray(array, callback, state)
|
|
{
|
|
for (var node of array)
|
|
this._recurse(node, callback, state);
|
|
}
|
|
|
|
// This function translates from esprima's Abstract Syntax Tree to ours.
|
|
// Mostly, this is just the identity function. We've added an extra typeProfilingReturnDivot property for functions/methods.
|
|
// Our AST complies with the Mozilla parser API:
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API
|
|
_createInternalSyntaxTree(node)
|
|
{
|
|
if (!node)
|
|
return null;
|
|
|
|
var result = null;
|
|
switch (node.type) {
|
|
case "ArrayExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression,
|
|
elements: node.elements.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "ArrayPattern":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern,
|
|
elements: node.elements.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "ArrowFunctionExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression,
|
|
id: this._createInternalSyntaxTree(node.id),
|
|
params: node.params.map(this._createInternalSyntaxTree, this),
|
|
body: this._createInternalSyntaxTree(node.body),
|
|
generator: node.generator,
|
|
expression: node.expression, // Boolean indicating if the body a single expression or a block statement.
|
|
async: node.async,
|
|
typeProfilingReturnDivot: node.range[0]
|
|
};
|
|
break;
|
|
case "AssignmentExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.AssignmentExpression,
|
|
operator: node.operator,
|
|
left: this._createInternalSyntaxTree(node.left),
|
|
right: this._createInternalSyntaxTree(node.right)
|
|
};
|
|
break;
|
|
case "AssignmentPattern":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern,
|
|
left: this._createInternalSyntaxTree(node.left),
|
|
right: this._createInternalSyntaxTree(node.right),
|
|
};
|
|
break;
|
|
case "AwaitExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.AwaitExpression,
|
|
argument: this._createInternalSyntaxTree(node.argument),
|
|
};
|
|
break;
|
|
case "BlockStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.BlockStatement,
|
|
body: node.body.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "BinaryExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.BinaryExpression,
|
|
operator: node.operator,
|
|
left: this._createInternalSyntaxTree(node.left),
|
|
right: this._createInternalSyntaxTree(node.right)
|
|
};
|
|
break;
|
|
case "BreakStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.BreakStatement,
|
|
label: this._createInternalSyntaxTree(node.label)
|
|
};
|
|
break;
|
|
case "CallExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.CallExpression,
|
|
callee: this._createInternalSyntaxTree(node.callee),
|
|
arguments: node.arguments.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "CatchClause":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.CatchClause,
|
|
param: this._createInternalSyntaxTree(node.param),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "ClassBody":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ClassBody,
|
|
body: node.body.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "ClassDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ClassDeclaration,
|
|
id: this._createInternalSyntaxTree(node.id),
|
|
superClass: this._createInternalSyntaxTree(node.superClass),
|
|
body: this._createInternalSyntaxTree(node.body),
|
|
};
|
|
break;
|
|
case "ClassExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ClassExpression,
|
|
id: this._createInternalSyntaxTree(node.id),
|
|
superClass: this._createInternalSyntaxTree(node.superClass),
|
|
body: this._createInternalSyntaxTree(node.body),
|
|
};
|
|
break;
|
|
case "ConditionalExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ConditionalExpression,
|
|
test: this._createInternalSyntaxTree(node.test),
|
|
consequent: this._createInternalSyntaxTree(node.consequent),
|
|
alternate: this._createInternalSyntaxTree(node.alternate)
|
|
};
|
|
break;
|
|
case "ContinueStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ContinueStatement,
|
|
label: this._createInternalSyntaxTree(node.label)
|
|
};
|
|
break;
|
|
case "DoWhileStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.DoWhileStatement,
|
|
body: this._createInternalSyntaxTree(node.body),
|
|
test: this._createInternalSyntaxTree(node.test)
|
|
};
|
|
break;
|
|
case "DebuggerStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.DebuggerStatement
|
|
};
|
|
break;
|
|
case "EmptyStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.EmptyStatement
|
|
};
|
|
break;
|
|
case "ExpressionStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement,
|
|
expression: this._createInternalSyntaxTree(node.expression)
|
|
};
|
|
break;
|
|
case "ForStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ForStatement,
|
|
init: this._createInternalSyntaxTree(node.init),
|
|
test: this._createInternalSyntaxTree(node.test),
|
|
update: this._createInternalSyntaxTree(node.update),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "ForInStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ForInStatement,
|
|
left: this._createInternalSyntaxTree(node.left),
|
|
right: this._createInternalSyntaxTree(node.right),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "ForOfStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ForOfStatement,
|
|
left: this._createInternalSyntaxTree(node.left),
|
|
right: this._createInternalSyntaxTree(node.right),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "FunctionDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration,
|
|
id: this._createInternalSyntaxTree(node.id),
|
|
params: node.params.map(this._createInternalSyntaxTree, this),
|
|
body: this._createInternalSyntaxTree(node.body),
|
|
generator: node.generator,
|
|
async: node.async,
|
|
typeProfilingReturnDivot: node.range[0]
|
|
};
|
|
break;
|
|
case "FunctionExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression,
|
|
id: this._createInternalSyntaxTree(node.id),
|
|
params: node.params.map(this._createInternalSyntaxTree, this),
|
|
body: this._createInternalSyntaxTree(node.body),
|
|
generator: node.generator,
|
|
async: node.async,
|
|
typeProfilingReturnDivot: node.range[0] // This may be overridden in the Property AST node.
|
|
};
|
|
break;
|
|
case "Identifier":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.Identifier,
|
|
name: node.name
|
|
};
|
|
break;
|
|
case "IfStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.IfStatement,
|
|
test: this._createInternalSyntaxTree(node.test),
|
|
consequent: this._createInternalSyntaxTree(node.consequent),
|
|
alternate: this._createInternalSyntaxTree(node.alternate)
|
|
};
|
|
break;
|
|
case "Literal":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.Literal,
|
|
value: node.value,
|
|
raw: node.raw
|
|
};
|
|
break;
|
|
case "LabeledStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.LabeledStatement,
|
|
label: this._createInternalSyntaxTree(node.label),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "LogicalExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.LogicalExpression,
|
|
left: this._createInternalSyntaxTree(node.left),
|
|
right: this._createInternalSyntaxTree(node.right),
|
|
operator: node.operator
|
|
};
|
|
break;
|
|
case "MemberExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.MemberExpression,
|
|
object: this._createInternalSyntaxTree(node.object),
|
|
property: this._createInternalSyntaxTree(node.property),
|
|
computed: node.computed
|
|
};
|
|
break;
|
|
case "MetaProperty":
|
|
// i.e: new.target produces {meta: "new", property: "target"}
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.MetaProperty,
|
|
meta: this._createInternalSyntaxTree(node.meta),
|
|
property: this._createInternalSyntaxTree(node.property),
|
|
};
|
|
break;
|
|
case "MethodDefinition":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition,
|
|
key: this._createInternalSyntaxTree(node.key),
|
|
value: this._createInternalSyntaxTree(node.value),
|
|
computed: node.computed,
|
|
kind: node.kind,
|
|
static: node.static
|
|
};
|
|
result.value.typeProfilingReturnDivot = node.range[0]; // "g" in "get" or "s" in "set" or "[" in "['computed']" or "m" in "methodName".
|
|
break;
|
|
case "NewExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.NewExpression,
|
|
callee: this._createInternalSyntaxTree(node.callee),
|
|
arguments: node.arguments.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "ObjectExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ObjectExpression,
|
|
properties: node.properties.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "ObjectPattern":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern,
|
|
properties: node.properties.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "Program":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.Program,
|
|
sourceType: node.sourceType,
|
|
body: node.body.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "Property":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.Property,
|
|
key: this._createInternalSyntaxTree(node.key),
|
|
value: this._createInternalSyntaxTree(node.value),
|
|
kind: node.kind,
|
|
method: node.method,
|
|
computed: node.computed
|
|
};
|
|
if (result.kind === "get" || result.kind === "set" || result.method)
|
|
result.value.typeProfilingReturnDivot = node.range[0]; // "g" in "get" or "s" in "set" or "[" in "['computed']" method or "m" in "methodName".
|
|
break;
|
|
case "RestElement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.RestElement,
|
|
argument: this._createInternalSyntaxTree(node.argument)
|
|
};
|
|
break;
|
|
case "RestProperty":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.RestProperty,
|
|
argument: this._createInternalSyntaxTree(node.argument),
|
|
};
|
|
break;
|
|
case "ReturnStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ReturnStatement,
|
|
argument: this._createInternalSyntaxTree(node.argument)
|
|
};
|
|
break;
|
|
case "SequenceExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.SequenceExpression,
|
|
expressions: node.expressions.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "SpreadElement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.SpreadElement,
|
|
argument: this._createInternalSyntaxTree(node.argument),
|
|
};
|
|
break;
|
|
case "SpreadProperty":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.SpreadProperty,
|
|
argument: this._createInternalSyntaxTree(node.argument),
|
|
};
|
|
break;
|
|
case "Super":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.Super
|
|
};
|
|
break;
|
|
case "SwitchStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.SwitchStatement,
|
|
discriminant: this._createInternalSyntaxTree(node.discriminant),
|
|
cases: node.cases.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "SwitchCase":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.SwitchCase,
|
|
test: this._createInternalSyntaxTree(node.test),
|
|
consequent: node.consequent.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "TaggedTemplateExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.TaggedTemplateExpression,
|
|
tag: this._createInternalSyntaxTree(node.tag),
|
|
quasi: this._createInternalSyntaxTree(node.quasi)
|
|
};
|
|
break;
|
|
case "TemplateElement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.TemplateElement,
|
|
value: node.value,
|
|
tail: node.tail
|
|
};
|
|
break;
|
|
case "TemplateLiteral":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.TemplateLiteral,
|
|
quasis: node.quasis.map(this._createInternalSyntaxTree, this),
|
|
expressions: node.expressions.map(this._createInternalSyntaxTree, this)
|
|
};
|
|
break;
|
|
case "ThisExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ThisExpression
|
|
};
|
|
break;
|
|
case "ThrowStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ThrowStatement,
|
|
argument: this._createInternalSyntaxTree(node.argument)
|
|
};
|
|
break;
|
|
case "TryStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.TryStatement,
|
|
block: this._createInternalSyntaxTree(node.block),
|
|
handler: this._createInternalSyntaxTree(node.handler),
|
|
finalizer: this._createInternalSyntaxTree(node.finalizer)
|
|
};
|
|
break;
|
|
case "UnaryExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.UnaryExpression,
|
|
operator: node.operator,
|
|
argument: this._createInternalSyntaxTree(node.argument)
|
|
};
|
|
break;
|
|
case "UpdateExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.UpdateExpression,
|
|
operator: node.operator,
|
|
prefix: node.prefix,
|
|
argument: this._createInternalSyntaxTree(node.argument)
|
|
};
|
|
break;
|
|
case "VariableDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.VariableDeclaration,
|
|
declarations: node.declarations.map(this._createInternalSyntaxTree, this),
|
|
kind: node.kind
|
|
};
|
|
break;
|
|
case "VariableDeclarator":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator,
|
|
id: this._createInternalSyntaxTree(node.id),
|
|
init: this._createInternalSyntaxTree(node.init)
|
|
};
|
|
break;
|
|
case "WhileStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.WhileStatement,
|
|
test: this._createInternalSyntaxTree(node.test),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "WithStatement":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.WithStatement,
|
|
object: this._createInternalSyntaxTree(node.object),
|
|
body: this._createInternalSyntaxTree(node.body)
|
|
};
|
|
break;
|
|
case "YieldExpression":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.YieldExpression,
|
|
argument: this._createInternalSyntaxTree(node.argument),
|
|
delegate: node.delegate
|
|
};
|
|
break;
|
|
|
|
// Modules.
|
|
|
|
case "ExportAllDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ExportAllDeclaration,
|
|
source: this._createInternalSyntaxTree(node.source),
|
|
};
|
|
break;
|
|
case "ExportNamedDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ExportNamedDeclaration,
|
|
declaration: this._createInternalSyntaxTree(node.declaration),
|
|
specifiers: node.specifiers.map(this._createInternalSyntaxTree, this),
|
|
source: this._createInternalSyntaxTree(node.source),
|
|
};
|
|
break;
|
|
case "ExportDefaultDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ExportDefaultDeclaration,
|
|
declaration: this._createInternalSyntaxTree(node.declaration),
|
|
};
|
|
break;
|
|
case "ExportSpecifier":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ExportSpecifier,
|
|
local: this._createInternalSyntaxTree(node.local),
|
|
exported: this._createInternalSyntaxTree(node.exported),
|
|
};
|
|
break;
|
|
case "Import":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.Import,
|
|
};
|
|
break;
|
|
case "ImportDeclaration":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ImportDeclaration,
|
|
specifiers: node.specifiers.map(this._createInternalSyntaxTree, this),
|
|
source: this._createInternalSyntaxTree(node.source),
|
|
};
|
|
break;
|
|
case "ImportDefaultSpecifier":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ImportDefaultSpecifier,
|
|
local: this._createInternalSyntaxTree(node.local),
|
|
};
|
|
break;
|
|
case "ImportNamespaceSpecifier":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ImportNamespaceSpecifier,
|
|
local: this._createInternalSyntaxTree(node.local),
|
|
};
|
|
break;
|
|
case "ImportSpecifier":
|
|
result = {
|
|
type: WebInspector.ScriptSyntaxTree.NodeType.ImportSpecifier,
|
|
imported: this._createInternalSyntaxTree(node.imported),
|
|
local: this._createInternalSyntaxTree(node.local),
|
|
};
|
|
break;
|
|
|
|
default:
|
|
console.error("Unsupported Syntax Tree Node: " + node.type, node);
|
|
return null;
|
|
}
|
|
|
|
result.range = node.range;
|
|
// This is an object for which you can add fields to an AST node without worrying about polluting the syntax-related fields of the node.
|
|
result.attachments = {};
|
|
|
|
return result;
|
|
}
|
|
};
|
|
|
|
// This should be kept in sync with an enum in JavaSciptCore/runtime/TypeProfiler.h
|
|
WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor = {
|
|
NormalExpression: 1,
|
|
FunctionReturn: 2
|
|
};
|
|
|
|
WebInspector.ScriptSyntaxTree.NodeType = {
|
|
ArrayExpression: Symbol("array-expression"),
|
|
ArrayPattern: Symbol("array-pattern"),
|
|
ArrowFunctionExpression: Symbol("arrow-function-expression"),
|
|
AssignmentExpression: Symbol("assignment-expression"),
|
|
AssignmentPattern: Symbol("assignment-pattern"),
|
|
AwaitExpression: Symbol("await-expression"),
|
|
BinaryExpression: Symbol("binary-expression"),
|
|
BlockStatement: Symbol("block-statement"),
|
|
BreakStatement: Symbol("break-statement"),
|
|
CallExpression: Symbol("call-expression"),
|
|
CatchClause: Symbol("catch-clause"),
|
|
ClassBody: Symbol("class-body"),
|
|
ClassDeclaration: Symbol("class-declaration"),
|
|
ClassExpression: Symbol("class-expression"),
|
|
ConditionalExpression: Symbol("conditional-expression"),
|
|
ContinueStatement: Symbol("continue-statement"),
|
|
DebuggerStatement: Symbol("debugger-statement"),
|
|
DoWhileStatement: Symbol("do-while-statement"),
|
|
EmptyStatement: Symbol("empty-statement"),
|
|
ExportAllDeclaration: Symbol("export-all-declaration"),
|
|
ExportDefaultDeclaration: Symbol("export-default-declaration"),
|
|
ExportNamedDeclaration: Symbol("export-named-declaration"),
|
|
ExportSpecifier: Symbol("export-specifier"),
|
|
ExpressionStatement: Symbol("expression-statement"),
|
|
ForInStatement: Symbol("for-in-statement"),
|
|
ForOfStatement: Symbol("for-of-statement"),
|
|
ForStatement: Symbol("for-statement"),
|
|
FunctionDeclaration: Symbol("function-declaration"),
|
|
FunctionExpression: Symbol("function-expression"),
|
|
Identifier: Symbol("identifier"),
|
|
IfStatement: Symbol("if-statement"),
|
|
Import: Symbol("import"),
|
|
ImportDeclaration: Symbol("import-declaration"),
|
|
ImportDefaultSpecifier: Symbol("import-default-specifier"),
|
|
ImportNamespaceSpecifier: Symbol("import-namespace-specifier"),
|
|
ImportSpecifier: Symbol("import-specifier"),
|
|
LabeledStatement: Symbol("labeled-statement"),
|
|
Literal: Symbol("literal"),
|
|
LogicalExpression: Symbol("logical-expression"),
|
|
MemberExpression: Symbol("member-expression"),
|
|
MetaProperty: Symbol("meta-property"),
|
|
MethodDefinition: Symbol("method-definition"),
|
|
NewExpression: Symbol("new-expression"),
|
|
ObjectExpression: Symbol("object-expression"),
|
|
ObjectPattern: Symbol("object-pattern"),
|
|
Program: Symbol("program"),
|
|
Property: Symbol("property"),
|
|
RestElement: Symbol("rest-element"),
|
|
RestProperty: Symbol("rest-property"),
|
|
ReturnStatement: Symbol("return-statement"),
|
|
SequenceExpression: Symbol("sequence-expression"),
|
|
SpreadElement: Symbol("spread-element"),
|
|
SpreadProperty: Symbol("spread-property"),
|
|
Super: Symbol("super"),
|
|
SwitchCase: Symbol("switch-case"),
|
|
SwitchStatement: Symbol("switch-statement"),
|
|
TaggedTemplateExpression: Symbol("tagged-template-expression"),
|
|
TemplateElement: Symbol("template-element"),
|
|
TemplateLiteral: Symbol("template-literal"),
|
|
ThisExpression: Symbol("this-expression"),
|
|
ThrowStatement: Symbol("throw-statement"),
|
|
TryStatement: Symbol("try-statement"),
|
|
UnaryExpression: Symbol("unary-expression"),
|
|
UpdateExpression: Symbol("update-expression"),
|
|
VariableDeclaration: Symbol("variable-declaration"),
|
|
VariableDeclarator: Symbol("variable-declarator"),
|
|
WhileStatement: Symbol("while-statement"),
|
|
WithStatement: Symbol("with-statement"),
|
|
YieldExpression: Symbol("yield-expression"),
|
|
};
|