Add Websites/browserbench.org
[WebKit-https.git] / Websites / browserbench.org / ARES-6 / Babylon / inspector-blob.js
1 /*
2  * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.ScriptSyntaxTree = class ScriptSyntaxTree extends WebInspector.Object
27 {
28     constructor(sourceText, script)
29     {
30         super();
31
32         console.assert(script && script instanceof WebInspector.Script, script);
33
34         this._script = script;
35
36         try {
37             let sourceType = this._script.sourceType === WebInspector.Script.SourceType.Module ? "module" : "script";
38             let esprimaSyntaxTree = esprima.parse(sourceText, {range: true, sourceType});
39             this._syntaxTree = this._createInternalSyntaxTree(esprimaSyntaxTree);
40             this._parsedSuccessfully = true;
41         } catch (error) {
42             this._parsedSuccessfully = false;
43             this._syntaxTree = null;
44             console.error("Couldn't parse JavaScript File: " + script.url, error);
45         }
46     }
47
48     // Public
49
50     get parsedSuccessfully()
51     {
52         return this._parsedSuccessfully;
53     }
54
55     forEachNode(callback)
56     {
57         console.assert(this._parsedSuccessfully);
58         if (!this._parsedSuccessfully)
59             return;
60
61         this._recurse(this._syntaxTree, callback, this._defaultParserState());
62     }
63
64     filter(predicate, startNode)
65     {
66         console.assert(startNode && this._parsedSuccessfully);
67         if (!this._parsedSuccessfully)
68             return [];
69
70         var nodes = [];
71         function filter(node, state)
72         {
73             if (predicate(node))
74                 nodes.push(node);
75             else
76                 state.skipChildNodes = true;
77         }
78
79         this._recurse(startNode, filter, this._defaultParserState());
80
81         return nodes;
82     }
83
84     containersOfOffset(offset)
85     {
86         console.assert(this._parsedSuccessfully);
87         if (!this._parsedSuccessfully)
88             return [];
89
90         let allNodes = [];
91         const start = 0;
92         const end = 1;
93
94         this.forEachNode((node, state) => {
95             if (node.range[end] < offset)
96                 state.skipChildNodes = true;
97             if (node.range[start] > offset)
98                 state.shouldStopEarly = true;
99             if (node.range[start] <= offset && node.range[end] >= offset)
100                 allNodes.push(node);
101         });
102
103         return allNodes;
104     }
105
106     filterByRange(startOffset, endOffset)
107     {
108         console.assert(this._parsedSuccessfully);
109         if (!this._parsedSuccessfully)
110             return [];
111
112         var allNodes = [];
113         var start = 0;
114         var end = 1;
115         function filterForNodesInRange(node, state)
116         {
117             // program start        range            program end
118             // [                 [         ]               ]
119             //            [ ]  [   [        ] ]  [ ]
120
121             // If a node's range ends before the range we're interested in starts, we don't need to search any of its
122             // enclosing ranges, because, by definition, those enclosing ranges are contained within this node's range.
123             if (node.range[end] < startOffset)
124                 state.skipChildNodes = true;
125
126             // We are only interested in nodes whose start position is within our range.
127             if (startOffset <= node.range[start] && node.range[start] <= endOffset)
128                 allNodes.push(node);
129
130             // Once we see nodes that start beyond our range, we can quit traversing the AST. We can do this safely
131             // because we know the AST is traversed using depth first search, so it will traverse into enclosing ranges
132             // before it traverses into adjacent ranges.
133             if (node.range[start] > endOffset)
134                 state.shouldStopEarly = true;
135         }
136
137         this.forEachNode(filterForNodesInRange);
138
139         return allNodes;
140     }
141
142     containsNonEmptyReturnStatement(startNode)
143     {
144         console.assert(startNode && this._parsedSuccessfully);
145         if (!this._parsedSuccessfully)
146             return false;
147
148         if (startNode.attachments._hasNonEmptyReturnStatement !== undefined)
149             return startNode.attachments._hasNonEmptyReturnStatement;
150
151         function removeFunctionsFilter(node)
152         {
153             return node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression
154                 && node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration
155                 && node.type !== WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression;
156         }
157
158         var nodes = this.filter(removeFunctionsFilter, startNode);
159         var hasNonEmptyReturnStatement = false;
160         var returnStatementType = WebInspector.ScriptSyntaxTree.NodeType.ReturnStatement;
161         for (var node of nodes) {
162             if (node.type === returnStatementType && node.argument) {
163                 hasNonEmptyReturnStatement = true;
164                 break;
165             }
166         }
167
168         startNode.attachments._hasNonEmptyReturnStatement = hasNonEmptyReturnStatement;
169
170         return hasNonEmptyReturnStatement;
171     }
172
173     static functionReturnDivot(node)
174     {
175         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);
176
177         // COMPATIBILITY (iOS 9): Legacy Backends view the return type as being the opening "{" of the function body.
178         // After iOS 9, this is to move to the start of the function statement/expression. See below:
179         // FIXME: Need a better way to determine backend versions. Using DOM.pseudoElement because that was added after iOS 9.
180         if (!DOMAgent.hasEvent("pseudoElementAdded"))
181             return node.body.range[0];
182
183         // "f" in "function". "s" in "set". "g" in "get". First letter in any method name for classes and object literals.
184         // The "[" for computed methods in classes and object literals.
185         return node.typeProfilingReturnDivot;
186     }
187
188     updateTypes(nodesToUpdate, callback)
189     {
190         console.assert(RuntimeAgent.getRuntimeTypesForVariablesAtOffsets);
191         console.assert(Array.isArray(nodesToUpdate) && this._parsedSuccessfully);
192
193         if (!this._parsedSuccessfully)
194             return;
195
196         var allRequests = [];
197         var allRequestNodes = [];
198         var sourceID = this._script.id;
199
200         for (var node of nodesToUpdate) {
201             switch (node.type) {
202             case WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration:
203             case WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression:
204             case WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression:
205                 for (var param of node.params) {
206                     for (var identifier of this._gatherIdentifiersInDeclaration(param)) {
207                         allRequests.push({
208                             typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,
209                             sourceID,
210                             divot: identifier.range[0]
211                         });
212                         allRequestNodes.push(identifier);
213                     }
214                 }
215
216                 allRequests.push({
217                     typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.FunctionReturn,
218                     sourceID,
219                     divot: WebInspector.ScriptSyntaxTree.functionReturnDivot(node)
220                 });
221                 allRequestNodes.push(node);
222                 break;
223             case WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator:
224                 for (var identifier of this._gatherIdentifiersInDeclaration(node.id)) {
225                     allRequests.push({
226                         typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,
227                         sourceID,
228                         divot: identifier.range[0]
229                     });
230                     allRequestNodes.push(identifier);
231                 }
232                 break;
233             }
234         }
235
236         console.assert(allRequests.length === allRequestNodes.length);
237
238         function handleTypes(error, typeInformationArray)
239         {
240             if (error)
241                 return;
242
243             console.assert(typeInformationArray.length === allRequests.length);
244
245             for (var i = 0; i < typeInformationArray.length; i++) {
246                 var node = allRequestNodes[i];
247                 var typeInformation = WebInspector.TypeDescription.fromPayload(typeInformationArray[i]);
248                 if (allRequests[i].typeInformationDescriptor === WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.FunctionReturn)
249                     node.attachments.returnTypes = typeInformation;
250                 else
251                     node.attachments.types = typeInformation;
252             }
253
254             callback(allRequestNodes);
255         }
256
257         this._script.target.RuntimeAgent.getRuntimeTypesForVariablesAtOffsets(allRequests, handleTypes);
258     }
259
260     // Private
261
262     _gatherIdentifiersInDeclaration(node)
263     {
264         function gatherIdentifiers(node)
265         {
266             switch (node.type) {
267                 case WebInspector.ScriptSyntaxTree.NodeType.Identifier:
268                     return [node];
269                 case WebInspector.ScriptSyntaxTree.NodeType.Property:
270                     return gatherIdentifiers(node.value);
271                 case WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern:
272                     var identifiers = [];
273                     for (var property of node.properties) {
274                         for (var identifier of gatherIdentifiers(property))
275                             identifiers.push(identifier);
276                     }
277                     return identifiers;
278                 case WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern:
279                     var identifiers = [];
280                     for (var element of node.elements) {
281                         for (var identifier of gatherIdentifiers(element))
282                             identifiers.push(identifier);
283                     }
284                     return identifiers;
285                 case WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern:
286                     return gatherIdentifiers(node.left);
287                 case WebInspector.ScriptSyntaxTree.NodeType.RestElement:
288                 case WebInspector.ScriptSyntaxTree.NodeType.RestProperty:
289                     return gatherIdentifiers(node.argument);
290                 default:
291                     console.assert(false, "Unexpected node type in variable declarator: " + node.type);
292                     return [];
293             }
294         }
295
296         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);
297
298         return gatherIdentifiers(node);
299     }
300
301     _defaultParserState()
302     {
303         return {
304             shouldStopEarly: false,
305             skipChildNodes: false
306         };
307     }
308
309     _recurse(node, callback, state)
310     {
311         if (!node)
312             return;
313
314         if (state.shouldStopEarly || state.skipChildNodes)
315             return;
316
317         callback(node, state);
318
319         switch (node.type) {
320         case WebInspector.ScriptSyntaxTree.NodeType.AssignmentExpression:
321             this._recurse(node.left, callback, state);
322             this._recurse(node.right, callback, state);
323             break;
324         case WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression:
325         case WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern:
326             this._recurseArray(node.elements, callback, state);
327             break;
328         case WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern:
329             this._recurse(node.left, callback, state);
330             this._recurse(node.right, callback, state);
331             break;
332         case WebInspector.ScriptSyntaxTree.NodeType.AwaitExpression:
333             this._recurse(node.argument, callback, state);
334             break;
335         case WebInspector.ScriptSyntaxTree.NodeType.BlockStatement:
336             this._recurseArray(node.body, callback, state);
337             break;
338         case WebInspector.ScriptSyntaxTree.NodeType.BinaryExpression:
339             this._recurse(node.left, callback, state);
340             this._recurse(node.right, callback, state);
341             break;
342         case WebInspector.ScriptSyntaxTree.NodeType.BreakStatement:
343             this._recurse(node.label, callback, state);
344             break;
345         case WebInspector.ScriptSyntaxTree.NodeType.CatchClause:
346             this._recurse(node.param, callback, state);
347             this._recurse(node.body, callback, state);
348             break;
349         case WebInspector.ScriptSyntaxTree.NodeType.CallExpression:
350             this._recurse(node.callee, callback, state);
351             this._recurseArray(node.arguments, callback, state);
352             break;
353         case WebInspector.ScriptSyntaxTree.NodeType.ClassBody:
354             this._recurseArray(node.body, callback, state);
355             break;
356         case WebInspector.ScriptSyntaxTree.NodeType.ClassDeclaration:
357         case WebInspector.ScriptSyntaxTree.NodeType.ClassExpression:
358             this._recurse(node.id, callback, state);
359             this._recurse(node.superClass, callback, state);
360             this._recurse(node.body, callback, state);
361             break;
362         case WebInspector.ScriptSyntaxTree.NodeType.ContinueStatement:
363             this._recurse(node.label, callback, state);
364             break;
365         case WebInspector.ScriptSyntaxTree.NodeType.DoWhileStatement:
366             this._recurse(node.body, callback, state);
367             this._recurse(node.test, callback, state);
368             break;
369         case WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement:
370             this._recurse(node.expression, callback, state);
371             break;
372         case WebInspector.ScriptSyntaxTree.NodeType.ForStatement:
373             this._recurse(node.init, callback, state);
374             this._recurse(node.test, callback, state);
375             this._recurse(node.update, callback, state);
376             this._recurse(node.body, callback, state);
377             break;
378         case WebInspector.ScriptSyntaxTree.NodeType.ForInStatement:
379         case WebInspector.ScriptSyntaxTree.NodeType.ForOfStatement:
380             this._recurse(node.left, callback, state);
381             this._recurse(node.right, callback, state);
382             this._recurse(node.body, callback, state);
383             break;
384         case WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration:
385         case WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression:
386         case WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression:
387             this._recurse(node.id, callback, state);
388             this._recurseArray(node.params, callback, state);
389             this._recurse(node.body, callback, state);
390             break;
391         case WebInspector.ScriptSyntaxTree.NodeType.IfStatement:
392             this._recurse(node.test, callback, state);
393             this._recurse(node.consequent, callback, state);
394             this._recurse(node.alternate, callback, state);
395             break;
396         case WebInspector.ScriptSyntaxTree.NodeType.LabeledStatement:
397             this._recurse(node.label, callback, state);
398             this._recurse(node.body, callback, state);
399             break;
400         case WebInspector.ScriptSyntaxTree.NodeType.LogicalExpression:
401             this._recurse(node.left, callback, state);
402             this._recurse(node.right, callback, state);
403             break;
404         case WebInspector.ScriptSyntaxTree.NodeType.MemberExpression:
405             this._recurse(node.object, callback, state);
406             this._recurse(node.property, callback, state);
407             break;
408         case WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition:
409             this._recurse(node.key, callback, state);
410             this._recurse(node.value, callback, state);
411             break;
412         case WebInspector.ScriptSyntaxTree.NodeType.NewExpression:
413             this._recurse(node.callee, callback, state);
414             this._recurseArray(node.arguments, callback, state);
415             break;
416         case WebInspector.ScriptSyntaxTree.NodeType.ObjectExpression:
417         case WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern:
418             this._recurseArray(node.properties, callback, state);
419             break;
420         case WebInspector.ScriptSyntaxTree.NodeType.Program:
421             this._recurseArray(node.body, callback, state);
422             break;
423         case WebInspector.ScriptSyntaxTree.NodeType.Property:
424             this._recurse(node.key, callback, state);
425             this._recurse(node.value, callback, state);
426             break;
427         case WebInspector.ScriptSyntaxTree.NodeType.RestElement:
428             this._recurse(node.argument, callback, state);
429             break;
430         case WebInspector.ScriptSyntaxTree.NodeType.RestProperty:
431             this._recurse(node.argument, callback, state);
432             break;
433         case WebInspector.ScriptSyntaxTree.NodeType.ReturnStatement:
434             this._recurse(node.argument, callback, state);
435             break;
436         case WebInspector.ScriptSyntaxTree.NodeType.SequenceExpression:
437             this._recurseArray(node.expressions, callback, state);
438             break;
439         case WebInspector.ScriptSyntaxTree.NodeType.SpreadElement:
440             this._recurse(node.argument, callback, state);
441             break;
442         case WebInspector.ScriptSyntaxTree.NodeType.SpreadProperty:
443             this._recurse(node.argument, callback, state);
444             break;
445         case WebInspector.ScriptSyntaxTree.NodeType.SwitchStatement:
446             this._recurse(node.discriminant, callback, state);
447             this._recurseArray(node.cases, callback, state);
448             break;
449         case WebInspector.ScriptSyntaxTree.NodeType.SwitchCase:
450             this._recurse(node.test, callback, state);
451             this._recurseArray(node.consequent, callback, state);
452             break;
453         case WebInspector.ScriptSyntaxTree.NodeType.ConditionalExpression:
454             this._recurse(node.test, callback, state);
455             this._recurse(node.consequent, callback, state);
456             this._recurse(node.alternate, callback, state);
457             break;
458         case WebInspector.ScriptSyntaxTree.NodeType.TaggedTemplateExpression:
459             this._recurse(node.tag, callback, state);
460             this._recurse(node.quasi, callback, state);
461             break;
462         case WebInspector.ScriptSyntaxTree.NodeType.TemplateLiteral:
463             this._recurseArray(node.quasis, callback, state);
464             this._recurseArray(node.expressions, callback, state);
465             break;
466         case WebInspector.ScriptSyntaxTree.NodeType.ThrowStatement:
467             this._recurse(node.argument, callback, state);
468             break;
469         case WebInspector.ScriptSyntaxTree.NodeType.TryStatement:
470             this._recurse(node.block, callback, state);
471             this._recurse(node.handler, callback, state);
472             this._recurse(node.finalizer, callback, state);
473             break;
474         case WebInspector.ScriptSyntaxTree.NodeType.UnaryExpression:
475             this._recurse(node.argument, callback, state);
476             break;
477         case WebInspector.ScriptSyntaxTree.NodeType.UpdateExpression:
478             this._recurse(node.argument, callback, state);
479             break;
480         case WebInspector.ScriptSyntaxTree.NodeType.VariableDeclaration:
481             this._recurseArray(node.declarations, callback, state);
482             break;
483         case WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator:
484             this._recurse(node.id, callback, state);
485             this._recurse(node.init, callback, state);
486             break;
487         case WebInspector.ScriptSyntaxTree.NodeType.WhileStatement:
488             this._recurse(node.test, callback, state);
489             this._recurse(node.body, callback, state);
490             break;
491         case WebInspector.ScriptSyntaxTree.NodeType.WithStatement:
492             this._recurse(node.object, callback, state);
493             this._recurse(node.body, callback, state);
494             break;
495         case WebInspector.ScriptSyntaxTree.NodeType.YieldExpression:
496             this._recurse(node.argument, callback, state);
497             break;
498
499         // Modules.
500
501         case WebInspector.ScriptSyntaxTree.NodeType.ExportAllDeclaration:
502             this._recurse(node.source, callback, state);
503             break;
504         case WebInspector.ScriptSyntaxTree.NodeType.ExportNamedDeclaration:
505             this._recurse(node.declaration, callback, state);
506             this._recurseArray(node.specifiers, callback, state);
507             this._recurse(node.source, callback, state);
508             break;
509         case WebInspector.ScriptSyntaxTree.NodeType.ExportDefaultDeclaration:
510             this._recurse(node.declaration, callback, state);
511             break;
512         case WebInspector.ScriptSyntaxTree.NodeType.ExportSpecifier:
513             this._recurse(node.local, callback, state);
514             this._recurse(node.exported, callback, state);
515             break;
516         case WebInspector.ScriptSyntaxTree.NodeType.ImportDeclaration:
517             this._recurseArray(node.specifiers, callback, state);
518             this._recurse(node.source, callback, state);
519             break;
520         case WebInspector.ScriptSyntaxTree.NodeType.ImportDefaultSpecifier:
521             this._recurse(node.local, callback, state);
522             break;
523         case WebInspector.ScriptSyntaxTree.NodeType.ImportNamespaceSpecifier:
524             this._recurse(node.local, callback, state);
525             break;
526         case WebInspector.ScriptSyntaxTree.NodeType.ImportSpecifier:
527             this._recurse(node.imported, callback, state);
528             this._recurse(node.local, callback, state);
529             break;
530
531         // All the leaf nodes go here.
532         case WebInspector.ScriptSyntaxTree.NodeType.DebuggerStatement:
533         case WebInspector.ScriptSyntaxTree.NodeType.EmptyStatement:
534         case WebInspector.ScriptSyntaxTree.NodeType.Identifier:
535         case WebInspector.ScriptSyntaxTree.NodeType.Import:
536         case WebInspector.ScriptSyntaxTree.NodeType.Literal:
537         case WebInspector.ScriptSyntaxTree.NodeType.MetaProperty:
538         case WebInspector.ScriptSyntaxTree.NodeType.Super:
539         case WebInspector.ScriptSyntaxTree.NodeType.ThisExpression:
540         case WebInspector.ScriptSyntaxTree.NodeType.TemplateElement:
541             break;
542         }
543
544         state.skipChildNodes = false;
545     }
546
547     _recurseArray(array, callback, state)
548     {
549         for (var node of array)
550             this._recurse(node, callback, state);
551     }
552
553     // This function translates from esprima's Abstract Syntax Tree to ours.
554     // Mostly, this is just the identity function. We've added an extra typeProfilingReturnDivot property for functions/methods.
555     // Our AST complies with the Mozilla parser API:
556     // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API
557     _createInternalSyntaxTree(node)
558     {
559         if (!node)
560             return null;
561
562         var result = null;
563         switch (node.type) {
564         case "ArrayExpression":
565             result = {
566                 type: WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression,
567                 elements: node.elements.map(this._createInternalSyntaxTree, this)
568             };
569             break;
570         case "ArrayPattern":
571             result = {
572                 type: WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern,
573                 elements: node.elements.map(this._createInternalSyntaxTree, this)
574             };
575             break;
576         case "ArrowFunctionExpression":
577             result = {
578                 type: WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression,
579                 id: this._createInternalSyntaxTree(node.id),
580                 params: node.params.map(this._createInternalSyntaxTree, this),
581                 body: this._createInternalSyntaxTree(node.body),
582                 generator: node.generator,
583                 expression: node.expression, // Boolean indicating if the body a single expression or a block statement.
584                 async: node.async,
585                 typeProfilingReturnDivot: node.range[0]
586             };
587             break;
588         case "AssignmentExpression":
589             result = {
590                 type: WebInspector.ScriptSyntaxTree.NodeType.AssignmentExpression,
591                 operator: node.operator,
592                 left: this._createInternalSyntaxTree(node.left),
593                 right: this._createInternalSyntaxTree(node.right)
594             };
595             break;
596         case "AssignmentPattern":
597             result = {
598                 type: WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern,
599                 left: this._createInternalSyntaxTree(node.left),
600                 right: this._createInternalSyntaxTree(node.right),
601             };
602             break;
603         case "AwaitExpression":
604             result = {
605                 type: WebInspector.ScriptSyntaxTree.NodeType.AwaitExpression,
606                 argument: this._createInternalSyntaxTree(node.argument),
607             };
608             break;
609         case "BlockStatement":
610             result = {
611                 type: WebInspector.ScriptSyntaxTree.NodeType.BlockStatement,
612                 body: node.body.map(this._createInternalSyntaxTree, this)
613             };
614             break;
615         case "BinaryExpression":
616             result = {
617                 type: WebInspector.ScriptSyntaxTree.NodeType.BinaryExpression,
618                 operator: node.operator,
619                 left: this._createInternalSyntaxTree(node.left),
620                 right: this._createInternalSyntaxTree(node.right)
621             };
622             break;
623         case "BreakStatement":
624             result = {
625                 type: WebInspector.ScriptSyntaxTree.NodeType.BreakStatement,
626                 label: this._createInternalSyntaxTree(node.label)
627             };
628             break;
629         case "CallExpression":
630             result = {
631                 type: WebInspector.ScriptSyntaxTree.NodeType.CallExpression,
632                 callee: this._createInternalSyntaxTree(node.callee),
633                 arguments: node.arguments.map(this._createInternalSyntaxTree, this)
634             };
635             break;
636         case "CatchClause":
637             result = {
638                 type: WebInspector.ScriptSyntaxTree.NodeType.CatchClause,
639                 param: this._createInternalSyntaxTree(node.param),
640                 body: this._createInternalSyntaxTree(node.body)
641             };
642             break;
643         case "ClassBody":
644             result = {
645                 type: WebInspector.ScriptSyntaxTree.NodeType.ClassBody,
646                 body: node.body.map(this._createInternalSyntaxTree, this)
647             };
648             break;
649         case "ClassDeclaration":
650             result = {
651                 type: WebInspector.ScriptSyntaxTree.NodeType.ClassDeclaration,
652                 id: this._createInternalSyntaxTree(node.id),
653                 superClass: this._createInternalSyntaxTree(node.superClass),
654                 body: this._createInternalSyntaxTree(node.body),
655             };
656             break;
657         case "ClassExpression":
658             result = {
659                 type: WebInspector.ScriptSyntaxTree.NodeType.ClassExpression,
660                 id: this._createInternalSyntaxTree(node.id),
661                 superClass: this._createInternalSyntaxTree(node.superClass),
662                 body: this._createInternalSyntaxTree(node.body),
663             };
664             break;
665         case "ConditionalExpression":
666             result = {
667                 type: WebInspector.ScriptSyntaxTree.NodeType.ConditionalExpression,
668                 test: this._createInternalSyntaxTree(node.test),
669                 consequent: this._createInternalSyntaxTree(node.consequent),
670                 alternate: this._createInternalSyntaxTree(node.alternate)
671             };
672             break;
673         case "ContinueStatement":
674             result = {
675                 type: WebInspector.ScriptSyntaxTree.NodeType.ContinueStatement,
676                 label: this._createInternalSyntaxTree(node.label)
677             };
678             break;
679         case "DoWhileStatement":
680             result = {
681                 type: WebInspector.ScriptSyntaxTree.NodeType.DoWhileStatement,
682                 body: this._createInternalSyntaxTree(node.body),
683                 test: this._createInternalSyntaxTree(node.test)
684             };
685             break;
686         case "DebuggerStatement":
687             result = {
688                 type: WebInspector.ScriptSyntaxTree.NodeType.DebuggerStatement
689             };
690             break;
691         case "EmptyStatement":
692             result = {
693                 type: WebInspector.ScriptSyntaxTree.NodeType.EmptyStatement
694             };
695             break;
696         case "ExpressionStatement":
697             result = {
698                 type: WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement,
699                 expression: this._createInternalSyntaxTree(node.expression)
700             };
701             break;
702         case "ForStatement":
703             result = {
704                 type: WebInspector.ScriptSyntaxTree.NodeType.ForStatement,
705                 init: this._createInternalSyntaxTree(node.init),
706                 test: this._createInternalSyntaxTree(node.test),
707                 update: this._createInternalSyntaxTree(node.update),
708                 body: this._createInternalSyntaxTree(node.body)
709             };
710             break;
711         case "ForInStatement":
712             result = {
713                 type: WebInspector.ScriptSyntaxTree.NodeType.ForInStatement,
714                 left: this._createInternalSyntaxTree(node.left),
715                 right: this._createInternalSyntaxTree(node.right),
716                 body: this._createInternalSyntaxTree(node.body)
717             };
718             break;
719         case "ForOfStatement":
720             result = {
721                 type: WebInspector.ScriptSyntaxTree.NodeType.ForOfStatement,
722                 left: this._createInternalSyntaxTree(node.left),
723                 right: this._createInternalSyntaxTree(node.right),
724                 body: this._createInternalSyntaxTree(node.body)
725             };
726             break;
727         case "FunctionDeclaration":
728             result = {
729                 type: WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration,
730                 id: this._createInternalSyntaxTree(node.id),
731                 params: node.params.map(this._createInternalSyntaxTree, this),
732                 body: this._createInternalSyntaxTree(node.body),
733                 generator: node.generator,
734                 async: node.async,
735                 typeProfilingReturnDivot: node.range[0]
736             };
737             break;
738         case "FunctionExpression":
739             result = {
740                 type: WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression,
741                 id: this._createInternalSyntaxTree(node.id),
742                 params: node.params.map(this._createInternalSyntaxTree, this),
743                 body: this._createInternalSyntaxTree(node.body),
744                 generator: node.generator,
745                 async: node.async,
746                 typeProfilingReturnDivot: node.range[0] // This may be overridden in the Property AST node.
747             };
748             break;
749         case "Identifier":
750             result = {
751                 type: WebInspector.ScriptSyntaxTree.NodeType.Identifier,
752                 name: node.name
753             };
754             break;
755         case "IfStatement":
756             result = {
757                 type: WebInspector.ScriptSyntaxTree.NodeType.IfStatement,
758                 test: this._createInternalSyntaxTree(node.test),
759                 consequent: this._createInternalSyntaxTree(node.consequent),
760                 alternate: this._createInternalSyntaxTree(node.alternate)
761             };
762             break;
763         case "Literal":
764             result = {
765                 type: WebInspector.ScriptSyntaxTree.NodeType.Literal,
766                 value: node.value,
767                 raw: node.raw
768             };
769             break;
770         case "LabeledStatement":
771             result = {
772                 type: WebInspector.ScriptSyntaxTree.NodeType.LabeledStatement,
773                 label: this._createInternalSyntaxTree(node.label),
774                 body: this._createInternalSyntaxTree(node.body)
775             };
776             break;
777         case "LogicalExpression":
778             result = {
779                 type: WebInspector.ScriptSyntaxTree.NodeType.LogicalExpression,
780                 left: this._createInternalSyntaxTree(node.left),
781                 right: this._createInternalSyntaxTree(node.right),
782                 operator: node.operator
783             };
784             break;
785         case "MemberExpression":
786             result = {
787                 type: WebInspector.ScriptSyntaxTree.NodeType.MemberExpression,
788                 object: this._createInternalSyntaxTree(node.object),
789                 property: this._createInternalSyntaxTree(node.property),
790                 computed: node.computed
791             };
792             break;
793         case "MetaProperty":
794             // i.e: new.target produces {meta: "new", property: "target"}
795             result = {
796                 type: WebInspector.ScriptSyntaxTree.NodeType.MetaProperty,
797                 meta: this._createInternalSyntaxTree(node.meta),
798                 property: this._createInternalSyntaxTree(node.property),
799             };
800             break;
801         case "MethodDefinition":
802             result = {
803                 type: WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition,
804                 key: this._createInternalSyntaxTree(node.key),
805                 value: this._createInternalSyntaxTree(node.value),
806                 computed: node.computed,
807                 kind: node.kind,
808                 static: node.static
809             };
810             result.value.typeProfilingReturnDivot = node.range[0]; // "g" in "get" or "s" in "set" or "[" in "['computed']" or "m" in "methodName".
811             break;
812         case "NewExpression":
813             result = {
814                 type: WebInspector.ScriptSyntaxTree.NodeType.NewExpression,
815                 callee: this._createInternalSyntaxTree(node.callee),
816                 arguments: node.arguments.map(this._createInternalSyntaxTree, this)
817             };
818             break;
819         case "ObjectExpression":
820             result = {
821                 type: WebInspector.ScriptSyntaxTree.NodeType.ObjectExpression,
822                 properties: node.properties.map(this._createInternalSyntaxTree, this)
823             };
824             break;
825         case "ObjectPattern":
826             result = {
827                 type: WebInspector.ScriptSyntaxTree.NodeType.ObjectPattern,
828                 properties: node.properties.map(this._createInternalSyntaxTree, this)
829             };
830             break;
831         case "Program":
832             result = {
833                 type: WebInspector.ScriptSyntaxTree.NodeType.Program,
834                 sourceType: node.sourceType,
835                 body: node.body.map(this._createInternalSyntaxTree, this)
836             };
837             break;
838         case "Property":
839             result = {
840                 type: WebInspector.ScriptSyntaxTree.NodeType.Property,
841                 key: this._createInternalSyntaxTree(node.key),
842                 value: this._createInternalSyntaxTree(node.value),
843                 kind: node.kind,
844                 method: node.method,
845                 computed: node.computed
846             };
847             if (result.kind === "get" || result.kind === "set" || result.method)
848                 result.value.typeProfilingReturnDivot = node.range[0];  // "g" in "get" or "s" in "set" or "[" in "['computed']" method or "m" in "methodName".
849             break;
850         case "RestElement":
851             result = {
852                 type: WebInspector.ScriptSyntaxTree.NodeType.RestElement,
853                 argument: this._createInternalSyntaxTree(node.argument)
854             };
855             break;
856         case "RestProperty":
857             result = {
858                 type: WebInspector.ScriptSyntaxTree.NodeType.RestProperty,
859                 argument: this._createInternalSyntaxTree(node.argument),
860             };
861             break;
862         case "ReturnStatement":
863             result = {
864                 type: WebInspector.ScriptSyntaxTree.NodeType.ReturnStatement,
865                 argument: this._createInternalSyntaxTree(node.argument)
866             };
867             break;
868         case "SequenceExpression":
869             result = {
870                 type: WebInspector.ScriptSyntaxTree.NodeType.SequenceExpression,
871                 expressions: node.expressions.map(this._createInternalSyntaxTree, this)
872             };
873             break;
874         case "SpreadElement":
875             result = {
876                 type: WebInspector.ScriptSyntaxTree.NodeType.SpreadElement,
877                 argument: this._createInternalSyntaxTree(node.argument),
878             };
879             break;
880         case "SpreadProperty":
881             result = {
882                 type: WebInspector.ScriptSyntaxTree.NodeType.SpreadProperty,
883                 argument: this._createInternalSyntaxTree(node.argument),
884             };
885             break;
886         case "Super":
887             result = {
888                 type: WebInspector.ScriptSyntaxTree.NodeType.Super
889             };
890             break;
891         case "SwitchStatement":
892             result = {
893                 type: WebInspector.ScriptSyntaxTree.NodeType.SwitchStatement,
894                 discriminant: this._createInternalSyntaxTree(node.discriminant),
895                 cases: node.cases.map(this._createInternalSyntaxTree, this)
896             };
897             break;
898         case "SwitchCase":
899             result = {
900                 type: WebInspector.ScriptSyntaxTree.NodeType.SwitchCase,
901                 test: this._createInternalSyntaxTree(node.test),
902                 consequent: node.consequent.map(this._createInternalSyntaxTree, this)
903             };
904             break;
905         case "TaggedTemplateExpression":
906             result = {
907                 type: WebInspector.ScriptSyntaxTree.NodeType.TaggedTemplateExpression,
908                 tag: this._createInternalSyntaxTree(node.tag),
909                 quasi: this._createInternalSyntaxTree(node.quasi)
910             };
911             break;
912         case "TemplateElement":
913             result = {
914                 type: WebInspector.ScriptSyntaxTree.NodeType.TemplateElement,
915                 value: node.value,
916                 tail: node.tail
917             };
918             break;
919         case "TemplateLiteral":
920             result = {
921                 type: WebInspector.ScriptSyntaxTree.NodeType.TemplateLiteral,
922                 quasis: node.quasis.map(this._createInternalSyntaxTree, this),
923                 expressions: node.expressions.map(this._createInternalSyntaxTree, this)
924             };
925             break;
926         case "ThisExpression":
927             result = {
928                 type: WebInspector.ScriptSyntaxTree.NodeType.ThisExpression
929             };
930             break;
931         case "ThrowStatement":
932             result = {
933                 type: WebInspector.ScriptSyntaxTree.NodeType.ThrowStatement,
934                 argument: this._createInternalSyntaxTree(node.argument)
935             };
936             break;
937         case "TryStatement":
938             result = {
939                 type: WebInspector.ScriptSyntaxTree.NodeType.TryStatement,
940                 block: this._createInternalSyntaxTree(node.block),
941                 handler: this._createInternalSyntaxTree(node.handler),
942                 finalizer: this._createInternalSyntaxTree(node.finalizer)
943             };
944             break;
945         case "UnaryExpression":
946             result = {
947                 type: WebInspector.ScriptSyntaxTree.NodeType.UnaryExpression,
948                 operator: node.operator,
949                 argument: this._createInternalSyntaxTree(node.argument)
950             };
951             break;
952         case "UpdateExpression":
953             result = {
954                 type: WebInspector.ScriptSyntaxTree.NodeType.UpdateExpression,
955                 operator: node.operator,
956                 prefix: node.prefix,
957                 argument: this._createInternalSyntaxTree(node.argument)
958             };
959             break;
960         case "VariableDeclaration":
961             result = {
962                 type: WebInspector.ScriptSyntaxTree.NodeType.VariableDeclaration,
963                 declarations: node.declarations.map(this._createInternalSyntaxTree, this),
964                 kind: node.kind
965             };
966             break;
967         case "VariableDeclarator":
968             result = {
969                 type: WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator,
970                 id: this._createInternalSyntaxTree(node.id),
971                 init: this._createInternalSyntaxTree(node.init)
972             };
973             break;
974         case "WhileStatement":
975             result = {
976                 type: WebInspector.ScriptSyntaxTree.NodeType.WhileStatement,
977                 test: this._createInternalSyntaxTree(node.test),
978                 body: this._createInternalSyntaxTree(node.body)
979             };
980             break;
981         case "WithStatement":
982             result = {
983                 type: WebInspector.ScriptSyntaxTree.NodeType.WithStatement,
984                 object: this._createInternalSyntaxTree(node.object),
985                 body: this._createInternalSyntaxTree(node.body)
986             };
987             break;
988         case "YieldExpression":
989             result = {
990                 type: WebInspector.ScriptSyntaxTree.NodeType.YieldExpression,
991                 argument: this._createInternalSyntaxTree(node.argument),
992                 delegate: node.delegate
993             };
994             break;
995
996         // Modules.
997
998         case "ExportAllDeclaration":
999             result = {
1000                 type: WebInspector.ScriptSyntaxTree.NodeType.ExportAllDeclaration,
1001                 source: this._createInternalSyntaxTree(node.source),
1002             };
1003             break;
1004         case "ExportNamedDeclaration":
1005             result = {
1006                 type: WebInspector.ScriptSyntaxTree.NodeType.ExportNamedDeclaration,
1007                 declaration: this._createInternalSyntaxTree(node.declaration),
1008                 specifiers: node.specifiers.map(this._createInternalSyntaxTree, this),
1009                 source: this._createInternalSyntaxTree(node.source),
1010             };
1011             break;
1012         case "ExportDefaultDeclaration":
1013             result = {
1014                 type: WebInspector.ScriptSyntaxTree.NodeType.ExportDefaultDeclaration,
1015                 declaration: this._createInternalSyntaxTree(node.declaration),
1016             };
1017             break;
1018         case "ExportSpecifier":
1019             result = {
1020                 type: WebInspector.ScriptSyntaxTree.NodeType.ExportSpecifier,
1021                 local: this._createInternalSyntaxTree(node.local),
1022                 exported: this._createInternalSyntaxTree(node.exported),
1023             };
1024             break;
1025         case "Import":
1026             result = {
1027                 type: WebInspector.ScriptSyntaxTree.NodeType.Import,
1028             };
1029             break;
1030         case "ImportDeclaration":
1031             result = {
1032                 type: WebInspector.ScriptSyntaxTree.NodeType.ImportDeclaration,
1033                 specifiers: node.specifiers.map(this._createInternalSyntaxTree, this),
1034                 source: this._createInternalSyntaxTree(node.source),
1035             };
1036             break;
1037         case "ImportDefaultSpecifier":
1038             result = {
1039                 type: WebInspector.ScriptSyntaxTree.NodeType.ImportDefaultSpecifier,
1040                 local: this._createInternalSyntaxTree(node.local),
1041             };
1042             break;
1043         case "ImportNamespaceSpecifier":
1044             result = {
1045                 type: WebInspector.ScriptSyntaxTree.NodeType.ImportNamespaceSpecifier,
1046                 local: this._createInternalSyntaxTree(node.local),
1047             };
1048             break;
1049         case "ImportSpecifier":
1050             result = {
1051                 type: WebInspector.ScriptSyntaxTree.NodeType.ImportSpecifier,
1052                 imported: this._createInternalSyntaxTree(node.imported),
1053                 local: this._createInternalSyntaxTree(node.local),
1054             };
1055             break;
1056
1057         default:
1058             console.error("Unsupported Syntax Tree Node: " + node.type, node);
1059             return null;
1060         }
1061
1062         result.range = node.range;
1063         // 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.
1064         result.attachments = {};
1065
1066         return result;
1067     }
1068 };
1069
1070 // This should be kept in sync with an enum in JavaSciptCore/runtime/TypeProfiler.h
1071 WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor = {
1072     NormalExpression: 1,
1073     FunctionReturn: 2
1074 };
1075
1076 WebInspector.ScriptSyntaxTree.NodeType = {
1077     ArrayExpression: Symbol("array-expression"),
1078     ArrayPattern: Symbol("array-pattern"),
1079     ArrowFunctionExpression: Symbol("arrow-function-expression"),
1080     AssignmentExpression: Symbol("assignment-expression"),
1081     AssignmentPattern: Symbol("assignment-pattern"),
1082     AwaitExpression: Symbol("await-expression"),
1083     BinaryExpression: Symbol("binary-expression"),
1084     BlockStatement: Symbol("block-statement"),
1085     BreakStatement: Symbol("break-statement"),
1086     CallExpression: Symbol("call-expression"),
1087     CatchClause: Symbol("catch-clause"),
1088     ClassBody: Symbol("class-body"),
1089     ClassDeclaration: Symbol("class-declaration"),
1090     ClassExpression: Symbol("class-expression"),
1091     ConditionalExpression: Symbol("conditional-expression"),
1092     ContinueStatement: Symbol("continue-statement"),
1093     DebuggerStatement: Symbol("debugger-statement"),
1094     DoWhileStatement: Symbol("do-while-statement"),
1095     EmptyStatement: Symbol("empty-statement"),
1096     ExportAllDeclaration: Symbol("export-all-declaration"),
1097     ExportDefaultDeclaration: Symbol("export-default-declaration"),
1098     ExportNamedDeclaration: Symbol("export-named-declaration"),
1099     ExportSpecifier: Symbol("export-specifier"),
1100     ExpressionStatement: Symbol("expression-statement"),
1101     ForInStatement: Symbol("for-in-statement"),
1102     ForOfStatement: Symbol("for-of-statement"),
1103     ForStatement: Symbol("for-statement"),
1104     FunctionDeclaration: Symbol("function-declaration"),
1105     FunctionExpression: Symbol("function-expression"),
1106     Identifier: Symbol("identifier"),
1107     IfStatement: Symbol("if-statement"),
1108     Import: Symbol("import"),
1109     ImportDeclaration: Symbol("import-declaration"),
1110     ImportDefaultSpecifier: Symbol("import-default-specifier"),
1111     ImportNamespaceSpecifier: Symbol("import-namespace-specifier"),
1112     ImportSpecifier: Symbol("import-specifier"),
1113     LabeledStatement: Symbol("labeled-statement"),
1114     Literal: Symbol("literal"),
1115     LogicalExpression: Symbol("logical-expression"),
1116     MemberExpression: Symbol("member-expression"),
1117     MetaProperty: Symbol("meta-property"),
1118     MethodDefinition: Symbol("method-definition"),
1119     NewExpression: Symbol("new-expression"),
1120     ObjectExpression: Symbol("object-expression"),
1121     ObjectPattern: Symbol("object-pattern"),
1122     Program: Symbol("program"),
1123     Property: Symbol("property"),
1124     RestElement: Symbol("rest-element"),
1125     RestProperty: Symbol("rest-property"),
1126     ReturnStatement: Symbol("return-statement"),
1127     SequenceExpression: Symbol("sequence-expression"),
1128     SpreadElement: Symbol("spread-element"),
1129     SpreadProperty: Symbol("spread-property"),
1130     Super: Symbol("super"),
1131     SwitchCase: Symbol("switch-case"),
1132     SwitchStatement: Symbol("switch-statement"),
1133     TaggedTemplateExpression: Symbol("tagged-template-expression"),
1134     TemplateElement: Symbol("template-element"),
1135     TemplateLiteral: Symbol("template-literal"),
1136     ThisExpression: Symbol("this-expression"),
1137     ThrowStatement: Symbol("throw-statement"),
1138     TryStatement: Symbol("try-statement"),
1139     UnaryExpression: Symbol("unary-expression"),
1140     UpdateExpression: Symbol("update-expression"),
1141     VariableDeclaration: Symbol("variable-declaration"),
1142     VariableDeclarator: Symbol("variable-declarator"),
1143     WhileStatement: Symbol("while-statement"),
1144     WithStatement: Symbol("with-statement"),
1145     YieldExpression: Symbol("yield-expression"),
1146 };