Bug 1260756 - The SyntaxTreeVisitor in Parser.jsm fails to process template literals and function default arguments. r=vporof
authorJarda Snajdr <jsnajdr@gmail.com>
Thu, 31 Mar 2016 01:49:00 +0200
changeset 316092 2bc47d801b3204c232615305f679c106de7d449c
parent 316091 e252bff60401d52271611e4493e84c840cc951cd
child 316093 22e771b7f16cda5f45fba39fe9968727168e1586
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvporof
bugs1260756
milestone48.0a1
Bug 1260756 - The SyntaxTreeVisitor in Parser.jsm fails to process template literals and function default arguments. r=vporof
devtools/client/debugger/test/mochitest/browser.ini
devtools/client/debugger/test/mochitest/browser_dbg_parser-function-defaults.js
devtools/client/debugger/test/mochitest/browser_dbg_parser-template-strings.js
devtools/shared/Parser.jsm
--- a/devtools/client/debugger/test/mochitest/browser.ini
+++ b/devtools/client/debugger/test/mochitest/browser.ini
@@ -331,16 +331,18 @@ skip-if = e10s && debug
 skip-if = e10s && debug
 [browser_dbg_parser-08.js]
 skip-if = e10s && debug
 [browser_dbg_parser-09.js]
 skip-if = e10s && debug
 [browser_dbg_parser-10.js]
 skip-if = e10s && debug
 [browser_dbg_parser-11.js]
+[browser_dbg_parser-function-defaults.js]
+[browser_dbg_parser-template-strings.js]
 skip-if = e10s && debug
 [browser_dbg_pause-exceptions-01.js]
 skip-if = e10s && debug
 [browser_dbg_pause-exceptions-02.js]
 skip-if = e10s && debug
 [browser_dbg_pause-no-step.js]
 skip-if = e10s && debug
 [browser_dbg_pause-resume.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_parser-function-defaults.js
@@ -0,0 +1,31 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that function default arguments are correctly processed.
+ */
+
+"use strict";
+
+function test() {
+  let { Parser, ParserHelpers, SyntaxTreeVisitor } =
+    Cu.import("resource://devtools/shared/Parser.jsm", {});
+
+  function verify(source, predicate, string) {
+    let ast = Parser.reflectionAPI.parse(source);
+    let node = SyntaxTreeVisitor.filter(ast, predicate).pop();
+    let info = ParserHelpers.getIdentifierEvalString(node);
+    is(info, string, "The identifier evaluation string is correct.");
+  }
+
+  // FunctionDeclaration
+  verify("function foo(a, b='b') {}", e => e.type == "Literal", "\"b\"");
+  // FunctionExpression
+  verify("let foo=function(a, b='b') {}", e => e.type == "Literal", "\"b\"");
+  // ArrowFunctionExpression
+  verify("let foo=(a, b='b')=> {}", e => e.type == "Literal", "\"b\"");
+
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_parser-template-strings.js
@@ -0,0 +1,29 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that template strings are correctly processed.
+ */
+
+"use strict";
+
+function test() {
+  let { Parser, SyntaxTreeVisitor } =
+    Cu.import("resource://devtools/shared/Parser.jsm", {});
+
+  let ast = Parser.reflectionAPI.parse("`foo${i}bar`");
+  let nodes = SyntaxTreeVisitor.filter(ast, e => e.type == "TemplateLiteral");
+  ok(nodes && nodes.length === 1, "Found the TemplateLiteral node");
+
+  let elements = nodes[0].elements;
+  ok(elements, "The TemplateLiteral node has elements");
+  is(elements.length, 3, "There are 3 elements in the literal");
+
+  ["Literal", "Identifier", "Literal"].forEach((type, i) => {
+    is(elements[i].type, type, `Element at index ${i} is '${type}'`);
+  });
+
+  finish();
+}
--- a/devtools/shared/Parser.jsm
+++ b/devtools/shared/Parser.jsm
@@ -1408,17 +1408,19 @@ var SyntaxTreeVisitor = {
     if (aCallbacks.onFunctionDeclaration) {
       aCallbacks.onFunctionDeclaration(aNode);
     }
     this[aNode.id.type](aNode.id, aNode, aCallbacks);
     for (let param of aNode.params) {
       this[param.type](param, aNode, aCallbacks);
     }
     for (let _default of aNode.defaults) {
-      this[_default.type](_default, aNode, aCallbacks);
+      if (_default) {
+        this[_default.type](_default, aNode, aCallbacks);
+      }
     }
     if (aNode.rest) {
       this[aNode.rest.type](aNode.rest, aNode, aCallbacks);
     }
     this[aNode.body.type](aNode.body, aNode, aCallbacks);
   },
 
   /**
@@ -1617,17 +1619,19 @@ var SyntaxTreeVisitor = {
     }
     if (aNode.id) {
       this[aNode.id.type](aNode.id, aNode, aCallbacks);
     }
     for (let param of aNode.params) {
       this[param.type](param, aNode, aCallbacks);
     }
     for (let _default of aNode.defaults) {
-      this[_default.type](_default, aNode, aCallbacks);
+      if (_default) {
+        this[_default.type](_default, aNode, aCallbacks);
+      }
     }
     if (aNode.rest) {
       this[aNode.rest.type](aNode.rest, aNode, aCallbacks);
     }
     this[aNode.body.type](aNode.body, aNode, aCallbacks);
   },
 
   /**
@@ -1656,17 +1660,19 @@ var SyntaxTreeVisitor = {
     }
     if (aCallbacks.onArrowFunctionExpression) {
       aCallbacks.onArrowFunctionExpression(aNode);
     }
     for (let param of aNode.params) {
       this[param.type](param, aNode, aCallbacks);
     }
     for (let _default of aNode.defaults) {
-      this[_default.type](_default, aNode, aCallbacks);
+      if (_default) {
+        this[_default.type](_default, aNode, aCallbacks);
+      }
     }
     if (aNode.rest) {
       this[aNode.rest.type](aNode.rest, aNode, aCallbacks);
     }
     this[aNode.body.type](aNode.body, aNode, aCallbacks);
   },
 
   /**
@@ -2342,12 +2348,41 @@ var SyntaxTreeVisitor = {
     if (aCallbacks.onNode) {
       if (aCallbacks.onNode(aNode, aParent) === false) {
         return;
       }
     }
     if (aCallbacks.onLiteral) {
       aCallbacks.onLiteral(aNode);
     }
+  },
+
+  /**
+   * A template string literal.
+   *
+   * interface TemplateLiteral <: Node {
+   *   type: "TemplateLiteral";
+   *   elements: [ Expression ];
+   * }
+   */
+  TemplateLiteral: function(aNode, aParent, aCallbacks) {
+    aNode._parent = aParent;
+
+    if (this.break) {
+      return;
+    }
+    if (aCallbacks.onNode) {
+      if (aCallbacks.onNode(aNode, aParent) === false) {
+        return;
+      }
+    }
+    if (aCallbacks.onTemplateLiteral) {
+      aCallbacks.onTemplateLiteral(aNode);
+    }
+    for (let element of aNode.elements) {
+      if (element) {
+        this[element.type](element, aNode, aCallbacks);
+      }
+    }
   }
 };
 
 XPCOMUtils.defineLazyGetter(Parser, "reflectionAPI", () => Reflect);