summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/reflect-parse
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/reflect-parse')
-rw-r--r--js/src/tests/non262/reflect-parse/Match.js242
-rw-r--r--js/src/tests/non262/reflect-parse/PatternAsserts.js95
-rw-r--r--js/src/tests/non262/reflect-parse/PatternBuilders.js290
-rw-r--r--js/src/tests/non262/reflect-parse/async.js25
-rw-r--r--js/src/tests/non262/reflect-parse/browser.js0
-rw-r--r--js/src/tests/non262/reflect-parse/class-fields.js23
-rw-r--r--js/src/tests/non262/reflect-parse/class-static.js8
-rw-r--r--js/src/tests/non262/reflect-parse/classes.js551
-rw-r--r--js/src/tests/non262/reflect-parse/computedPropNames.js45
-rw-r--r--js/src/tests/non262/reflect-parse/declarations.js97
-rw-r--r--js/src/tests/non262/reflect-parse/destructuring-array-holes-reflect-as-null.js9
-rw-r--r--js/src/tests/non262/reflect-parse/destructuring-assignment.js32
-rw-r--r--js/src/tests/non262/reflect-parse/destructuring-function-parameters.js45
-rw-r--r--js/src/tests/non262/reflect-parse/destructuring-variable-declarations.js58
-rw-r--r--js/src/tests/non262/reflect-parse/destructuring__proto__.js16
-rw-r--r--js/src/tests/non262/reflect-parse/expression-short-circuit-compound-assignment.js11
-rw-r--r--js/src/tests/non262/reflect-parse/expression.js193
-rw-r--r--js/src/tests/non262/reflect-parse/for-loop-destructuring.js47
-rw-r--r--js/src/tests/non262/reflect-parse/generators.js12
-rw-r--r--js/src/tests/non262/reflect-parse/lexicals.js19
-rw-r--r--js/src/tests/non262/reflect-parse/location.js33
-rw-r--r--js/src/tests/non262/reflect-parse/methodDefn.js51
-rw-r--r--js/src/tests/non262/reflect-parse/module-export-name.js121
-rw-r--r--js/src/tests/non262/reflect-parse/newTarget.js42
-rw-r--r--js/src/tests/non262/reflect-parse/object-rest.js41
-rw-r--r--js/src/tests/non262/reflect-parse/object-spread.js29
-rw-r--r--js/src/tests/non262/reflect-parse/proxyArgs.js13
-rw-r--r--js/src/tests/non262/reflect-parse/shell.js66
-rw-r--r--js/src/tests/non262/reflect-parse/stackOverflow.js8
-rw-r--r--js/src/tests/non262/reflect-parse/statements.js88
-rw-r--r--js/src/tests/non262/reflect-parse/templateStrings.js42
31 files changed, 2352 insertions, 0 deletions
diff --git a/js/src/tests/non262/reflect-parse/Match.js b/js/src/tests/non262/reflect-parse/Match.js
new file mode 100644
index 0000000000..2a14d8a315
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/Match.js
@@ -0,0 +1,242 @@
+// |reftest| skip
+
+// A little pattern-matching library.
+var Match =
+
+(function() {
+
+ function Pattern(template) {
+ // act like a constructor even as a function
+ if (!(this instanceof Pattern))
+ return new Pattern(template);
+
+ this.template = template;
+ }
+
+ Pattern.prototype = {
+ match: function(act) {
+ return match(act, this.template);
+ },
+
+ matches: function(act) {
+ try {
+ return this.match(act);
+ }
+ catch (e) {
+ if (!(e instanceof MatchError))
+ throw e;
+ return false;
+ }
+ },
+
+ assert: function(act, message) {
+ try {
+ return this.match(act);
+ }
+ catch (e) {
+ if (!(e instanceof MatchError))
+ throw e;
+ throw new Error((message || "failed match") + ": " + e.message);
+ }
+ },
+
+ toString: () => "[object Pattern]"
+ };
+
+ Pattern.ANY = new Pattern;
+ Pattern.ANY.template = Pattern.ANY;
+
+ Pattern.NUMBER = new Pattern;
+ Pattern.NUMBER.match = function (act) {
+ if (typeof act !== 'number') {
+ throw new MatchError("Expected number, got: " + quote(act));
+ }
+ }
+
+ Pattern.NATURAL = new Pattern
+ Pattern.NATURAL.match = function (act) {
+ if (typeof act !== 'number' || act !== Math.floor(act) || act < 0) {
+ throw new MatchError("Expected natural number, got: " + quote(act));
+ }
+ }
+
+ class ObjectWithExactly extends Pattern {
+ constructor(template) {
+ super(template);
+ }
+
+ match(actual) {
+ return matchObjectWithExactly(actual, this.template)
+ }
+ }
+
+ Pattern.OBJECT_WITH_EXACTLY = function (template) {
+ return new ObjectWithExactly(template);
+ }
+
+ var quote = JSON.stringify;
+
+ class MatchError extends Error {
+ toString() {
+ return "match error: " + this.message;
+ }
+ };
+
+ Pattern.MatchError = MatchError;
+
+ function isAtom(x) {
+ return (typeof x === "number") ||
+ (typeof x === "string") ||
+ (typeof x === "boolean") ||
+ (x === null) ||
+ (x === undefined) ||
+ (typeof x === "object" && x instanceof RegExp) ||
+ (typeof x === "bigint");
+ }
+
+ function isObject(x) {
+ return (x !== null) && (typeof x === "object");
+ }
+
+ function isFunction(x) {
+ return typeof x === "function";
+ }
+
+ function isArrayLike(x) {
+ return isObject(x) && ("length" in x);
+ }
+
+ function matchAtom(act, exp) {
+ if ((typeof exp) === "number" && isNaN(exp)) {
+ if ((typeof act) !== "number" || !isNaN(act))
+ throw new MatchError("expected NaN, got: " + quote(act));
+ return true;
+ }
+
+ if (exp === null) {
+ if (act !== null)
+ throw new MatchError("expected null, got: " + quote(act));
+ return true;
+ }
+
+ if (exp instanceof RegExp) {
+ if (!(act instanceof RegExp) || exp.source !== act.source)
+ throw new MatchError("expected " + quote(exp) + ", got: " + quote(act));
+ return true;
+ }
+
+ switch (typeof exp) {
+ case "string":
+ case "undefined":
+ if (act !== exp)
+ throw new MatchError("expected " + quote(exp) + ", got " + quote(act));
+ return true;
+ case "boolean":
+ case "number":
+ case "bigint":
+ if (exp !== act)
+ throw new MatchError("expected " + exp + ", got " + quote(act));
+ return true;
+ }
+
+ throw new Error("bad pattern: " + JSON.stringify(exp));
+ }
+
+ // Match an object having at least the expected properties.
+ function matchObjectWithAtLeast(act, exp) {
+ if (!isObject(act))
+ throw new MatchError("expected object, got " + quote(act));
+
+ for (var key in exp) {
+ if (!(key in act))
+ throw new MatchError("expected property " + quote(key) + " not found in " + quote(act));
+ try {
+ match(act[key], exp[key]);
+ } catch (inner) {
+ if (!(inner instanceof MatchError)) {
+ throw inner;
+ }
+ inner.message = `matching property "${String(key)}":\n${inner.message}`;
+ throw inner;
+ }
+ }
+
+ return true;
+ }
+
+ // Match an object having all the expected properties and no more.
+ function matchObjectWithExactly(act, exp) {
+ matchObjectWithAtLeast(act, exp);
+
+ for (var key in act) {
+ if (!(key in exp)) {
+ throw new MatchError("unexpected property " + quote(key));
+ }
+ }
+
+ return true;
+ }
+
+ function matchFunction(act, exp) {
+ if (!isFunction(act))
+ throw new MatchError("expected function, got " + quote(act));
+
+ if (act !== exp)
+ throw new MatchError("expected function: " + exp +
+ "\nbut got different function: " + act);
+ }
+
+ function matchArray(act, exp) {
+ if (!isObject(act) || !("length" in act))
+ throw new MatchError("expected array-like object, got " + quote(act));
+
+ var length = exp.length;
+ if (act.length !== exp.length)
+ throw new MatchError("expected array-like object of length " + length + ", got " + quote(act));
+
+ for (var i = 0; i < length; i++) {
+ if (i in exp) {
+ if (!(i in act))
+ throw new MatchError("expected array property " + i + " not found in " + quote(act));
+ try {
+ match(act[i], exp[i]);
+ } catch (inner) {
+ if (!(inner instanceof MatchError)) {
+ throw inner;
+ }
+ inner.message = `matching array element [${i}]:\n${inner.message}`;
+ throw inner;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ function match(act, exp) {
+ if (exp === Pattern.ANY)
+ return true;
+
+ if (exp instanceof Pattern)
+ return exp.match(act);
+
+ if (isAtom(exp))
+ return matchAtom(act, exp);
+
+ if (isArrayLike(exp))
+ return matchArray(act, exp);
+
+ if (isFunction(exp))
+ return matchFunction(act, exp);
+
+ if (isObject(exp))
+ return matchObjectWithAtLeast(act, exp);
+
+ throw new Error("bad pattern: " + JSON.stringify(exp));
+ }
+
+ return { Pattern: Pattern,
+ MatchError: MatchError };
+
+})();
+
diff --git a/js/src/tests/non262/reflect-parse/PatternAsserts.js b/js/src/tests/non262/reflect-parse/PatternAsserts.js
new file mode 100644
index 0000000000..1be20d2812
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/PatternAsserts.js
@@ -0,0 +1,95 @@
+// |reftest| skip
+
+loadRelativeToScript('PatternBuilders.js');
+
+function localSrc(src) {
+ return "(function(){ " + src + " })";
+}
+function localPatt(patt) {
+ return program([exprStmt(funExpr(null, [], blockStmt([patt])))]);
+}
+function blockSrc(src) {
+ return "(function(){ { " + src + " } })";
+}
+function blockPatt(patt) {
+ return program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))]);
+}
+
+function assertBlockStmt(src, patt) {
+ blockPatt(patt).assert(Reflect.parse(blockSrc(src)));
+}
+
+function assertBlockExpr(src, patt) {
+ assertBlockStmt(src, exprStmt(patt));
+}
+
+function assertBlockDecl(src, patt, builder) {
+ blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder}));
+}
+
+function assertLocalStmt(src, patt) {
+ localPatt(patt).assert(Reflect.parse(localSrc(src)));
+}
+
+function assertLocalExpr(src, patt) {
+ assertLocalStmt(src, exprStmt(patt));
+}
+
+function assertLocalDecl(src, patt) {
+ localPatt(patt).assert(Reflect.parse(localSrc(src)));
+}
+
+function assertGlobalStmt(src, patt, builder) {
+ program([patt]).assert(Reflect.parse(src, {builder: builder}));
+}
+
+function assertStringExpr(src, patt) {
+ program([exprStmt(patt)]).assert(Reflect.parse(src));
+}
+
+function assertGlobalExpr(src, patt, builder) {
+ program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder}));
+ //assertStmt(src, exprStmt(patt));
+}
+
+function assertGlobalDecl(src, patt) {
+ program([patt]).assert(Reflect.parse(src));
+}
+
+function assertProg(src, patt) {
+ program(patt).assert(Reflect.parse(src));
+}
+
+function assertStmt(src, patt) {
+ assertLocalStmt(src, patt);
+ assertGlobalStmt(src, patt);
+ assertBlockStmt(src, patt);
+}
+
+function assertInFunctionExpr(src, patt) {
+ assertLocalExpr(src, patt);
+ assertBlockExpr(src, patt);
+}
+
+function assertExpr(src, patt) {
+ assertLocalExpr(src, patt);
+ assertGlobalExpr(src, patt);
+ assertBlockExpr(src, patt);
+}
+
+function assertDecl(src, patt) {
+ assertLocalDecl(src, patt);
+ assertGlobalDecl(src, patt);
+ assertBlockDecl(src, patt);
+}
+
+function assertError(src, errorType) {
+ try {
+ Reflect.parse(src);
+ } catch (expected) {
+ if (!(expected instanceof errorType))
+ throw expected;
+ return;
+ }
+ throw new Error("expected " + errorType.name + " for " + JSON.stringify(src));
+}
diff --git a/js/src/tests/non262/reflect-parse/PatternBuilders.js b/js/src/tests/non262/reflect-parse/PatternBuilders.js
new file mode 100644
index 0000000000..6415e405fb
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/PatternBuilders.js
@@ -0,0 +1,290 @@
+// |reftest| skip
+
+loadRelativeToScript('Match.js');
+
+var { Pattern, MatchError } = Match;
+
+function program(elts) {
+ return Pattern({ type: "Program", body: elts });
+}
+function exprStmt(expr) {
+ return Pattern({ type: "ExpressionStatement", expression: expr });
+}
+function throwStmt(expr) {
+ return Pattern({ type: "ThrowStatement", argument: expr });
+}
+function returnStmt(expr) {
+ return Pattern({ type: "ReturnStatement", argument: expr });
+}
+function yieldExpr(expr) {
+ return Pattern({ type: "YieldExpression", argument: expr });
+}
+function lit(val) {
+ return Pattern({ type: "Literal", value: val });
+}
+function comp(name) {
+ return Pattern({ type: "ComputedName", name: name });
+}
+function spread(val) {
+ return Pattern({ type: "SpreadExpression", expression: val});
+}
+function optExpr(val) {
+ return Pattern({ type: "OptionalExpression", expression: val});
+}
+function delOptExpr(val) {
+ return Pattern({ type: "DeleteOptionalExpression", expression: val});
+}
+var thisExpr = Pattern({ type: "ThisExpression" });
+function funDecl(id, params, body, defaults=[], rest=null) {
+ return Pattern({ type: "FunctionDeclaration",
+ id: id,
+ params: params,
+ defaults: defaults,
+ body: body,
+ rest: rest,
+ generator: false });
+}
+function genFunDecl(style, id, params, body) {
+ return Pattern({ type: "FunctionDeclaration",
+ id: id,
+ params: params,
+ defaults: [],
+ body: body,
+ generator: true,
+ style: style });
+}
+function asyncFunDecl(id, params, body) {
+ return Pattern({ type: "FunctionDeclaration",
+ id: id,
+ params: params,
+ defaults: [],
+ body: body,
+ generator: false,
+ async: true });
+}
+function varDecl(decls) {
+ return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" });
+}
+function letDecl(decls) {
+ return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" });
+}
+function constDecl(decls) {
+ return Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" });
+}
+function ident(name) {
+ return Pattern({ type: "Identifier", name: name });
+}
+function dotExpr(obj, id) {
+ return Pattern({ type: "MemberExpression", computed: false, object: obj, property: id });
+}
+function memExpr(obj, id) {
+ return Pattern({ type: "MemberExpression", computed: true, object: obj, property: id });
+}
+function optDotExpr(obj, id) {
+ return Pattern({ type: "OptionalMemberExpression", computed: false, object: obj, property: id });
+}
+function optMemExpr(obj, id) {
+ return Pattern({ type: "OptionalMemberExpression", computed: true, object: obj, property: id });
+}
+function forStmt(init, test, update, body) {
+ return Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body });
+}
+function forOfStmt(lhs, rhs, body) {
+ return Pattern({ type: "ForOfStatement", left: lhs, right: rhs, body: body });
+}
+function forInStmt(lhs, rhs, body) {
+ return Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body });
+}
+function breakStmt(lab) {
+ return Pattern({ type: "BreakStatement", label: lab });
+}
+function continueStmt(lab) {
+ return Pattern({ type: "ContinueStatement", label: lab });
+}
+function blockStmt(body) {
+ return Pattern({ type: "BlockStatement", body: body });
+}
+function literal(val) {
+ return Pattern({ type: "Literal", value: val });
+}
+var emptyStmt = Pattern({ type: "EmptyStatement" });
+function ifStmt(test, cons, alt) {
+ return Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons });
+}
+function labStmt(lab, stmt) {
+ return Pattern({ type: "LabeledStatement", label: lab, body: stmt });
+}
+function withStmt(obj, stmt) {
+ return Pattern({ type: "WithStatement", object: obj, body: stmt });
+}
+function whileStmt(test, stmt) {
+ return Pattern({ type: "WhileStatement", test: test, body: stmt });
+}
+function doStmt(stmt, test) {
+ return Pattern({ type: "DoWhileStatement", test: test, body: stmt });
+}
+function switchStmt(disc, cases) {
+ return Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases });
+}
+function caseClause(test, stmts) {
+ return Pattern({ type: "SwitchCase", test: test, consequent: stmts });
+}
+function defaultClause(stmts) {
+ return Pattern({ type: "SwitchCase", test: null, consequent: stmts });
+}
+function catchClause(id, body) {
+ return Pattern({ type: "CatchClause", param: id, body: body });
+}
+function tryStmt(body, handler, fin) {
+ return Pattern({ type: "TryStatement", block: body, handler: handler, finalizer: fin });
+}
+
+function superProp(id) {
+ return dotExpr(Pattern({ type: "Super" }), id);
+}
+function superElem(id) {
+ return memExpr(Pattern({ type: "Super" }), id);
+}
+
+function classStmt(id, heritage, body) {
+ return Pattern({ type: "ClassStatement",
+ id: id,
+ superClass: heritage,
+ body: body});
+}
+function classExpr(id, heritage, body) {
+ return Pattern({ type: "ClassExpression",
+ id: id,
+ superClass: heritage,
+ body: body});
+}
+function classMethod(id, body, kind, static) {
+ return Pattern({ type: "ClassMethod",
+ name: id,
+ body: body,
+ kind: kind,
+ static: static });
+}
+function classField(id, init) {
+ return Pattern({ type: "ClassField",
+ name: id,
+ init: init });
+}
+function staticClassBlock(body) {
+ return Pattern({ type: "StaticClassBlock", body: body });
+}
+
+function funExpr(id, args, body, gen) {
+ return Pattern({ type: "FunctionExpression",
+ id: id,
+ params: args,
+ body: body,
+ generator: false });
+}
+function genFunExpr(style, id, args, body) {
+ return Pattern({ type: "FunctionExpression",
+ id: id,
+ params: args,
+ body: body,
+ generator: true,
+ style: style });
+}
+function asyncFunExpr(id, args, body) {
+ return Pattern({ type: "FunctionExpression",
+ id: id,
+ params: args,
+ body: body,
+ generator: false,
+ async: true });
+}
+function arrowExpr(args, body) {
+ return Pattern({ type: "ArrowFunctionExpression",
+ params: args,
+ body: body });
+}
+function asyncArrowExpr(isExpression, args, body) {
+ return Pattern({ type: "ArrowFunctionExpression",
+ params: args,
+ body: body,
+ generator: false,
+ async: true,
+ expression: isExpression });
+}
+
+function metaProperty(meta, property) {
+ return Pattern({ type: "MetaProperty",
+ meta: meta,
+ property: property });
+}
+function newTarget() {
+ return metaProperty(ident("new"), ident("target"));
+}
+
+function unExpr(op, arg) {
+ return Pattern({ type: "UnaryExpression", operator: op, argument: arg });
+}
+function binExpr(op, left, right) {
+ return Pattern({ type: "BinaryExpression", operator: op, left: left, right: right });
+}
+function aExpr(op, left, right) {
+ return Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right });
+}
+function updExpr(op, arg, prefix) {
+ return Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix });
+}
+function logExpr(op, left, right) {
+ return Pattern({ type: "LogicalExpression", operator: op, left: left, right: right });
+}
+
+function condExpr(test, cons, alt) {
+ return Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt });
+}
+function seqExpr(exprs) {
+ return Pattern({ type: "SequenceExpression", expressions: exprs });
+}
+function newExpr(callee, args) {
+ return Pattern({ type: "NewExpression", callee: callee, arguments: args });
+}
+function callExpr(callee, args) {
+ return Pattern({ type: "CallExpression", callee: callee, arguments: args });
+}
+function optCallExpr(callee, args) {
+ return Pattern({ type: "OptionalCallExpression", callee: callee, arguments: args });
+}
+function superCallExpr(args) {
+ return callExpr({ type: "Super" }, args);
+}
+function arrExpr(elts) {
+ return Pattern({ type: "ArrayExpression", elements: elts });
+}
+function objExpr(elts) {
+ return Pattern({ type: "ObjectExpression", properties: elts });
+}
+function computedName(elts) {
+ return Pattern({ type: "ComputedName", name: elts });
+}
+function templateLit(elts) {
+ return Pattern({ type: "TemplateLiteral", elements: elts });
+}
+function taggedTemplate(tagPart, templatePart) {
+ return Pattern({ type: "TaggedTemplate", callee: tagPart, arguments : templatePart });
+}
+function template(raw, cooked, ...args) {
+ return Pattern([{ type: "CallSiteObject", raw: raw, cooked: cooked}, ...args]);
+}
+
+function arrPatt(elts) {
+ return Pattern({ type: "ArrayPattern", elements: elts });
+}
+function objPatt(elts) {
+ return Pattern({ type: "ObjectPattern", properties: elts });
+}
+
+function assignElem(target, defaultExpr = null, targetIdent = typeof target == 'string' ? ident(target) : target) {
+ return defaultExpr ? aExpr('=', targetIdent, defaultExpr) : targetIdent;
+}
+function assignProp(property, target, defaultExpr = null, shorthand = !target, targetProp = target || ident(property)) {
+ return Pattern({
+ type: "Property", key: ident(property), shorthand,
+ value: defaultExpr ? aExpr('=', targetProp, defaultExpr) : targetProp });
+}
diff --git a/js/src/tests/non262/reflect-parse/async.js b/js/src/tests/non262/reflect-parse/async.js
new file mode 100644
index 0000000000..355f0356c5
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/async.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+// async function declaration.
+assertDecl("async function foo() {}", asyncFunDecl(ident("foo"), [], blockStmt([])));
+
+// async function expression.
+assertExpr("(async function() {})", asyncFunExpr(null, [], blockStmt([])));
+assertExpr("(async function foo() {})", asyncFunExpr(ident("foo"), [], blockStmt([])));
+
+// async arrow.
+assertExpr("async a => 1", asyncArrowExpr(true, [ident("a")], literal(1)));
+assertExpr("async a => { 1 }", asyncArrowExpr(false, [ident("a")], blockStmt([exprStmt(literal(1))])));
+assertExpr("async a => { return 1 }", asyncArrowExpr(false, [ident("a")], blockStmt([returnStmt(literal(1))])));
+
+// async method.
+assertExpr("({ async foo() {} })", objExpr([{ key: ident("foo"), value: asyncFunExpr(ident("foo"), [], blockStmt([]))}]));
+
+assertStmt("class C { async foo() {} }", classStmt(ident("C"), null, [classMethod(ident("foo"), asyncFunExpr(ident("foo"), [], blockStmt([])), "method", false)]));
+assertStmt("class C { static async foo() {} }", classStmt(ident("C"), null, [classMethod(ident("foo"), asyncFunExpr(ident("foo"), [], blockStmt([])), "method", true)]));
+
+// await expression.
+assertDecl("async function foo() { await bar }", asyncFunDecl(ident("foo"), [], blockStmt([exprStmt(unExpr("await", ident("bar")))])));
+
+if (typeof reportCompare === 'function')
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/reflect-parse/browser.js b/js/src/tests/non262/reflect-parse/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/browser.js
diff --git a/js/src/tests/non262/reflect-parse/class-fields.js b/js/src/tests/non262/reflect-parse/class-fields.js
new file mode 100644
index 0000000000..c1ace34b42
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/class-fields.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// Classes
+function testClassFields() {
+ function constructor_(name) {
+ let body = blockStmt([]);
+ let method = funExpr(ident(name), [], body);
+ return classMethod(ident("constructor"), method, "method", false);
+ }
+
+ assertExpr("(class C { x = 2; })", classExpr(ident("C"), null, [classField(ident("x"), lit(2))]));
+ assertExpr("(class C { x = x; })", classExpr(ident("C"), null, [classField(ident("x"), ident("x"))]))
+ assertExpr("(class C { x; })", classExpr(ident("C"), null, [classField(ident("x"), null)]))
+ assertExpr("(class C { x; y = 2; })", classExpr(ident("C"), null, [classField(ident("x"), null), classField(ident("y"), lit(2))]))
+ assertExpr("(class C { x = 2; constructor(){} })", classExpr(ident("C"), null, [classField(ident("x"), lit(2)), constructor_("C")]))
+
+
+ assertExpr("(class C { #x = 2; })", classExpr(ident("C"), null, [classField(ident("#x"), lit(2))]));
+ assertExpr("(class C { #x; })", classExpr(ident("C"), null, [classField(ident("#x"), null)]))
+ assertExpr("(class C { #x; #y = 2; })", classExpr(ident("C"), null, [classField(ident("#x"), null), classField(ident("#y"), lit(2))]))
+
+}
+
+runtest(testClassFields);
diff --git a/js/src/tests/non262/reflect-parse/class-static.js b/js/src/tests/non262/reflect-parse/class-static.js
new file mode 100644
index 0000000000..e770b2dfc6
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/class-static.js
@@ -0,0 +1,8 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// Classes
+function testClassStaticBlock() {
+
+ assertExpr("(class C { static { 2; } })", classExpr(ident("C"), null, [staticClassBlock(blockStmt([exprStmt(lit(2))]))]));
+}
+
+runtest(testClassStaticBlock); \ No newline at end of file
diff --git a/js/src/tests/non262/reflect-parse/classes.js b/js/src/tests/non262/reflect-parse/classes.js
new file mode 100644
index 0000000000..b855c5d741
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/classes.js
@@ -0,0 +1,551 @@
+// |reftest| slow skip-if(!xulRuntime.shell)
+// Classes
+function testClasses() {
+ function methodFun(id, kind, generator, args, body = []) {
+ assertEq(generator && kind === "method", generator);
+ assertEq(typeof id === 'string' || id === null, true);
+ let methodName;
+ switch (kind) {
+ case "method":
+ methodName = typeof id === 'string' ? ident(id) : null;
+ break;
+ case "get":
+ case "set":
+ methodName = ident(`${kind} ${typeof id === 'string' ? id : ""}`);
+ break;
+ default:
+ methodName = null;
+ break;
+ }
+ return generator
+ ? genFunExpr("es6", methodName, args.map(ident), blockStmt(body))
+ : funExpr(methodName, args.map(ident), blockStmt(body));
+ }
+
+ function simpleMethod(id, kind, generator, args = [], isStatic = false) {
+ return classMethod(ident(id),
+ methodFun(id, kind, generator, args),
+ kind, isStatic);
+ }
+ function ctorWithName(id, body = []) {
+ return classMethod(ident("constructor"),
+ methodFun(id, "method", false, [], body),
+ "method", false);
+ }
+ function emptyCPNMethod(id, isStatic) {
+ return classMethod(computedName(lit(id)),
+ funExpr(null, [], blockStmt([])),
+ "method", isStatic);
+ }
+
+ function assertClassExpr(str, methods, heritage = null, name = null) {
+ let template = classExpr(name, heritage, methods);
+ assertExpr("(" + str + ")", template);
+ }
+
+ // FunctionExpression of constructor has class name as its id.
+ // FIXME: Implement ES6 function "name" property semantics (bug 883377).
+ let ctorPlaceholder = {};
+ function assertClass(str, methods, heritage = null, constructorBody = []) {
+ let namelessStr = str.replace("NAME", "");
+ let namedStr = str.replace("NAME", "Foo");
+ let namedCtor = ctorWithName("Foo", constructorBody);
+ let namelessCtor = ctorWithName(null, constructorBody);
+ let namelessMethods = methods.map(x => x == ctorPlaceholder ? namelessCtor : x);
+ let namedMethods = methods.map(x => x == ctorPlaceholder ? namedCtor : x);
+ assertClassExpr(namelessStr, namelessMethods, heritage);
+ assertClassExpr(namedStr, namedMethods, heritage, ident("Foo"));
+
+ let template = classStmt(ident("Foo"), heritage, namedMethods);
+ assertStmt(namedStr, template);
+ }
+ function assertNamedClassError(str, error) {
+ assertError(str, error);
+ assertError("(" + str + ")", error);
+ }
+ function assertClassError(str, error) {
+ assertNamedClassError(str, error);
+ assertError("(" + str.replace("NAME", "") + ")", error);
+ }
+
+ /* Trivial classes */
+ // Unnamed class statements are forbidden, but unnamed class expressions are
+ // just fine.
+ assertError("class { constructor() { } }", SyntaxError);
+ assertClass("class NAME { constructor() { } }", [ctorPlaceholder]);
+
+ // A class name must actually be a name
+ assertNamedClassError("class x.y { constructor() {} }", SyntaxError);
+ assertNamedClassError("class [] { constructor() {} }", SyntaxError);
+ assertNamedClassError("class {x} { constructor() {} }", SyntaxError);
+ assertNamedClassError("class for { constructor() {} }", SyntaxError);
+
+ // Allow methods and accessors
+ assertClass("class NAME { constructor() { } method() { } }",
+ [ctorPlaceholder, simpleMethod("method", "method", false)]);
+
+ assertClass("class NAME { constructor() { } get method() { } }",
+ [ctorPlaceholder, simpleMethod("method", "get", false)]);
+
+ assertClass("class NAME { constructor() { } set method(x) { } }",
+ [ctorPlaceholder, simpleMethod("method", "set", false, ["x"])]);
+
+ /* Static */
+ assertClass(`class NAME {
+ constructor() { };
+ static method() { };
+ static *methodGen() { };
+ static get getter() { };
+ static set setter(x) { }
+ }`,
+ [ctorPlaceholder,
+ simpleMethod("method", "method", false, [], true),
+ simpleMethod("methodGen", "method", true, [], true),
+ simpleMethod("getter", "get", false, [], true),
+ simpleMethod("setter", "set", false, ["x"], true)]);
+
+ // It's not an error to have a method named static, static, or not.
+ assertClass("class NAME { constructor() { } static() { } }",
+ [ctorPlaceholder, simpleMethod("static", "method", false)]);
+ assertClass("class NAME { static static() { }; constructor() { } }",
+ [simpleMethod("static", "method", false, [], true), ctorPlaceholder]);
+ assertClass("class NAME { static get static() { }; constructor() { } }",
+ [simpleMethod("static", "get", false, [], true), ctorPlaceholder]);
+ assertClass("class NAME { constructor() { }; static set static(x) { } }",
+ [ctorPlaceholder, simpleMethod("static", "set", false, ["x"], true)]);
+
+ // You do, however, have to put static in the right spot
+ assertClassError("class NAME { constructor() { }; get static foo() { } }", SyntaxError);
+
+ // Spec disallows "prototype" as a static member in a class, since that
+ // one's important to make the desugaring work
+ assertClassError("class NAME { constructor() { } static prototype() { } }", SyntaxError);
+ assertClassError("class NAME { constructor() { } static *prototype() { } }", SyntaxError);
+ assertClassError("class NAME { static get prototype() { }; constructor() { } }", SyntaxError);
+ assertClassError("class NAME { static set prototype(x) { }; constructor() { } }", SyntaxError);
+
+ // You are, however, allowed to have a CPN called prototype as a static
+ assertClass("class NAME { constructor() { }; static [\"prototype\"]() { } }",
+ [ctorPlaceholder, emptyCPNMethod("prototype", true)]);
+
+ /* Constructor */
+ // Allow default constructors
+ assertClass("class NAME { }", []);
+ assertClass("class NAME extends null { }", [], lit(null));
+
+ // Derived class constructor must have curly brackets
+ assertClassError("class NAME extends null { constructor() 1 }", SyntaxError);
+
+ // It is an error to have two methods named constructor, but not other
+ // names, regardless if one is an accessor or a generator or static.
+ assertClassError("class NAME { constructor() { } constructor(a) { } }", SyntaxError);
+ let methods = [["method() { }", simpleMethod("method", "method", false)],
+ ["*method() { }", simpleMethod("method", "method", true)],
+ ["get method() { }", simpleMethod("method", "get", false)],
+ ["set method(x) { }", simpleMethod("method", "set", false, ["x"])],
+ ["static method() { }", simpleMethod("method", "method", false, [], true)],
+ ["static *method() { }", simpleMethod("method", "method", true, [], true)],
+ ["static get method() { }", simpleMethod("method", "get", false, [], true)],
+ ["static set method(x) { }", simpleMethod("method", "set", false, ["x"], true)]];
+ let i, j;
+ for (i = 0; i < methods.length; i++) {
+ for (j = 0; j < methods.length; j++) {
+ let str = "class NAME { constructor() { } " +
+ methods[i][0] + " " + methods[j][0] +
+ " }";
+ assertClass(str, [ctorPlaceholder, methods[i][1], methods[j][1]]);
+ }
+ }
+
+ // It is, however, not an error to have a constructor, and a method with a
+ // computed property name 'constructor'
+ assertClass("class NAME { constructor () { } [\"constructor\"] () { } }",
+ [ctorPlaceholder, emptyCPNMethod("constructor", false)]);
+
+ // It is an error to have a generator or accessor named constructor
+ assertClassError("class NAME { *constructor() { } }", SyntaxError);
+ assertClassError("class NAME { get constructor() { } }", SyntaxError);
+ assertClassError("class NAME { set constructor() { } }", SyntaxError);
+
+ /* Semicolons */
+ // Allow Semicolons in Class Definitions
+ assertClass("class NAME { constructor() { }; }", [ctorPlaceholder]);
+
+ // Allow more than one semicolon, even in otherwise trivial classses
+ assertClass("class NAME { ;;; constructor() { } }", [ctorPlaceholder]);
+
+ // Semicolons are optional, even if the methods share a line
+ assertClass("class NAME { method() { } constructor() { } }",
+ [simpleMethod("method", "method", false), ctorPlaceholder]);
+
+ /* Generators */
+ // No yield as a class name inside a generator
+ assertError(`function *foo() {
+ class yield {
+ constructor() { }
+ }
+ }`, SyntaxError);
+ assertError(`function *foo() {
+ (class yield {
+ constructor() { }
+ })
+ }`, SyntaxError);
+
+ // No legacy generators for methods.
+ assertClassError(`class NAME {
+ constructor() { yield 2; }
+ }`, SyntaxError);
+ assertClassError(`class NAME {
+ method() { yield 2; }
+ }`, SyntaxError);
+ assertClassError(`class NAME {
+ get method() { yield 2; }
+ }`, SyntaxError);
+ assertClassError(`class NAME {
+ set method() { yield 2; }
+ }`, SyntaxError);
+
+ // Methods may be generators, but not accessors
+ assertClassError("class NAME { constructor() { } *get foo() { } }", SyntaxError);
+ assertClassError("class NAME { constructor() { } *set foo() { } }", SyntaxError);
+
+ assertClass("class NAME { *method() { } constructor() { } }",
+ [simpleMethod("method", "method", true), ctorPlaceholder]);
+
+ /* Strictness */
+ // yield is a strict-mode keyword, and class definitions are always strict.
+ assertClassError("class NAME { constructor() { var yield; } }", SyntaxError);
+
+ // Beware of the strictness of computed property names. Here use bareword
+ // deletion (a deprecated action) to check.
+ assertClassError("class NAME { constructor() { } [delete bar]() { }}", SyntaxError);
+
+ /* Bindings */
+ // Class statements bind lexically, so they should collide with other
+ // in-block lexical bindings, but class expressions don't.
+ let FooCtor = ctorWithName("Foo");
+ assertError("{ let Foo; class Foo { constructor() { } } }", SyntaxError);
+ assertStmt("{ let Foo; (class Foo { constructor() { } }) }",
+ blockStmt([letDecl([{ id: ident("Foo"), init: null }]),
+ exprStmt(classExpr(ident("Foo"), null, [FooCtor]))]));
+ assertError("{ const Foo = 0; class Foo { constructor() { } } }", SyntaxError);
+ assertStmt("{ const Foo = 0; (class Foo { constructor() { } }) }",
+ blockStmt([constDecl([{ id: ident("Foo"), init: lit(0) }]),
+ exprStmt(classExpr(ident("Foo"), null, [FooCtor]))]));
+ assertError("{ class Foo { constructor() { } } class Foo { constructor() { } } }", SyntaxError);
+ assertStmt(`{
+ (class Foo {
+ constructor() { }
+ },
+ class Foo {
+ constructor() { }
+ });
+ }`,
+ blockStmt([exprStmt(seqExpr([classExpr(ident("Foo"), null, [FooCtor]),
+ classExpr(ident("Foo"), null, [FooCtor])]))]));
+ assertStmt(`{
+ var x = class Foo { constructor() { } };
+ class Foo { constructor() { } }
+ }`,
+ blockStmt([varDecl([{
+ id: ident("x"),
+ init: classExpr(ident("Foo"), null, [FooCtor])
+ }]),
+ classStmt(ident("Foo"), null, [FooCtor])]));
+
+
+ // Can't make a lexical binding without a block.
+ assertError("if (1) class Foo { constructor() { } }", SyntaxError);
+
+ /* Heritage Expressions */
+ // It's illegal to have things that look like "multiple inheritance":
+ // non-parenthesized comma expressions.
+ assertClassError("class NAME extends null, undefined { constructor() { } }", SyntaxError);
+
+ // Again check for strict-mode in heritage expressions
+ assertClassError("class NAME extends (delete x) { constructor() { } }", SyntaxError);
+
+ // You must specify an inheritance if you say "extends"
+ assertClassError("class NAME extends { constructor() { } }", SyntaxError);
+
+ // "extends" is still a valid name for a method
+ assertClass("class NAME { constructor() { }; extends() { } }",
+ [ctorPlaceholder, simpleMethod("extends", "method", false)]);
+
+ // Immediate expression
+ assertClass("class NAME extends null { constructor() { } }",
+ [ctorPlaceholder], lit(null));
+
+ // Sequence expresson
+ assertClass("class NAME extends (undefined, undefined) { constructor() { } }",
+ [ctorPlaceholder], seqExpr([ident("undefined"), ident("undefined")]));
+
+ // Function expression
+ let emptyFunction = funExpr(null, [], blockStmt([]));
+ assertClass("class NAME extends function(){ } { constructor() { } }",
+ [ctorPlaceholder], emptyFunction);
+
+ // New expression
+ assertClass("class NAME extends new function(){ }() { constructor() { } }",
+ [ctorPlaceholder], newExpr(emptyFunction, []));
+
+ // Call expression
+ assertClass("class NAME extends function(){ }() { constructor() { } }",
+ [ctorPlaceholder], callExpr(emptyFunction, []));
+
+ // Dot expression
+ assertClass("class NAME extends {}.foo { constructor() { } }",
+ [ctorPlaceholder], dotExpr(objExpr([]), ident("foo")));
+
+ // Member expression
+ assertClass("class NAME extends {}[foo] { constructor() { } }",
+ [ctorPlaceholder], memExpr(objExpr([]), ident("foo")));
+
+ // #constructor is an invalid private method name.
+ assertClassError("class NAME { #constructor() { } }", SyntaxError);
+
+ const method = ["#method() { }", simpleMethod("#method", "method", false)];
+ const generator = ["*#method() { }", simpleMethod("#method", "method", true)];
+ const getter = ["get #method() { }", simpleMethod("#method", "get", false)];
+ const setter = ["set #method(x) { }", simpleMethod("#method", "set", false, ["x"])];
+ for (const [source, parsed] of [method, generator, getter, setter]) {
+ assertClass(`class NAME { constructor() { } ${source} }`, [ctorPlaceholder, parsed]);
+ }
+
+ // Private getters and setters of the same name are allowed.
+ assertClass(`class NAME { constructor() { } ${getter[0]} ${setter[0]} }`,
+ [ctorPlaceholder, getter[1], setter[1]]);
+ assertClass(`class NAME { constructor() { } ${setter[0]} ${getter[0]} }`,
+ [ctorPlaceholder, setter[1], getter[1]]);
+
+ // Private method names can't be used multiple times, other than for a getter/setter pair.
+ for (const [source1, _] of [method, generator, getter, setter]) {
+ for (const [source2, _] of [method, generator]) {
+ assertClassError(`class NAME { constructor() { } ${source1} ${source2} }`, SyntaxError);
+ }
+ }
+
+ assertClassError(`class NAME { constructor() { } ${setter[0]} ${setter[0]} }`, SyntaxError);
+ assertClassError(`class NAME { constructor() { } ${getter[0]} ${getter[0]} }`, SyntaxError);
+
+
+ /* SuperProperty */
+ // NOTE: Some of these tests involve object literals, as SuperProperty is a
+ // valid production in any method definition, including in objectl
+ // litterals. These tests still fall here, as |super| is not implemented in
+ // any form without classes.
+
+ function assertValidSuperProps(assertion, makeStr, makeExpr, type, generator, args, static,
+ extending) {
+ let superProperty = superProp(ident("prop"));
+ let superMember = superElem(lit("prop"));
+
+ let situations = [
+ ["super.prop", superProperty],
+ ["super['prop']", superMember],
+ ["super.prop()", callExpr(superProperty, [])],
+ ["super['prop']()", callExpr(superMember, [])],
+ ["new super.prop()", newExpr(superProperty, [])],
+ ["new super['prop']()", newExpr(superMember, [])],
+ ["delete super.prop", unExpr("delete", superProperty)],
+ ["delete super['prop']", unExpr("delete", superMember)],
+ ["++super.prop", updExpr("++", superProperty, true)],
+ ["super['prop']--", updExpr("--", superMember, false)],
+ ["super.prop = 4", aExpr("=", superProperty, lit(4))],
+ ["super['prop'] = 4", aExpr("=", superMember, lit(4))],
+ ["super.prop += 4", aExpr("+=", superProperty, lit(4))],
+ ["super['prop'] += 4", aExpr("+=", superMember, lit(4))],
+ ["super.prop -= 4", aExpr("-=", superProperty, lit(4))],
+ ["super['prop'] -= 4", aExpr("-=", superMember, lit(4))],
+ ["super.prop *= 4", aExpr("*=", superProperty, lit(4))],
+ ["super['prop'] *= 4", aExpr("*=", superMember, lit(4))],
+ ["super.prop /= 4", aExpr("/=", superProperty, lit(4))],
+ ["super['prop'] /= 4", aExpr("/=", superMember, lit(4))],
+ ["super.prop %= 4", aExpr("%=", superProperty, lit(4))],
+ ["super['prop'] %= 4", aExpr("%=", superMember, lit(4))],
+ ["super.prop <<= 4", aExpr("<<=", superProperty, lit(4))],
+ ["super['prop'] <<= 4", aExpr("<<=", superMember, lit(4))],
+ ["super.prop >>= 4", aExpr(">>=", superProperty, lit(4))],
+ ["super['prop'] >>= 4", aExpr(">>=", superMember, lit(4))],
+ ["super.prop >>>= 4", aExpr(">>>=", superProperty, lit(4))],
+ ["super['prop'] >>>= 4", aExpr(">>>=", superMember, lit(4))],
+ ["super.prop |= 4", aExpr("|=", superProperty, lit(4))],
+ ["super['prop'] |= 4", aExpr("|=", superMember, lit(4))],
+ ["super.prop ^= 4", aExpr("^=", superProperty, lit(4))],
+ ["super['prop'] ^= 4", aExpr("^=", superMember, lit(4))],
+ ["super.prop &= 4", aExpr("&=", superProperty, lit(4))],
+ ["super['prop'] &= 4", aExpr("&=", superMember, lit(4))],
+
+ // We can also use super from inside arrow functions in method
+ // definitions
+ ["()=>super.prop", arrowExpr([], superProperty)],
+ ["()=>super['prop']", arrowExpr([], superMember)]];
+
+ for (let situation of situations) {
+ let sitStr = situation[0];
+ let sitExpr = situation[1];
+
+ let fun = methodFun("method", type, generator, args, [exprStmt(sitExpr)]);
+ let str = makeStr(sitStr, type, generator, args, static, extending);
+ assertion(str, makeExpr(fun, type, static), extending);
+ }
+ }
+
+ function assertValidSuperPropTypes(assertion, makeStr, makeExpr, static, extending) {
+ for (let type of ["method", "get", "set"]) {
+ if (type === "method") {
+ // methods can also be generators
+ assertValidSuperProps(assertion, makeStr, makeExpr, type, true, [], static, extending);
+ assertValidSuperProps(assertion, makeStr, makeExpr, type, false, [], static, extending);
+ continue;
+ }
+
+ // Setters require 1 argument, and getters require 0
+ assertValidSuperProps(assertion, makeStr, makeExpr, type, false,
+ type === "set" ? ["x"] : [], static, extending);
+ }
+ }
+
+ function makeSuperPropMethodStr(propStr, type, generator, args) {
+ return `${type === "method" ? "" : type} ${generator ? "*" : ""} method(${args.join(",")})
+ {
+ ${propStr};
+ }`;
+ }
+
+ function makeClassSuperPropStr(propStr, type, generator, args, static, extending) {
+ return `class NAME ${extending ? "extends null" : ""} {
+ constructor() { };
+ ${static ? "static" : ""} ${makeSuperPropMethodStr(propStr, type, generator, args)}
+ }`;
+ }
+ function makeClassSuperPropExpr(fun, type, static) {
+ // We are going right into assertClass, so we don't have to build the
+ // entire statement.
+ return [ctorPlaceholder,
+ classMethod(ident("method"), fun, type, static)];
+ }
+ function doClassSuperPropAssert(str, expr, extending) {
+ assertClass(str, expr, extending ? lit(null) : null);
+ }
+ function assertValidClassSuperPropExtends(extending) {
+ // super.prop and super[prop] are valid, regardless of whether the
+ // method is static or not
+ assertValidSuperPropTypes(doClassSuperPropAssert, makeClassSuperPropStr, makeClassSuperPropExpr,
+ false, extending);
+ assertValidSuperPropTypes(doClassSuperPropAssert, makeClassSuperPropStr, makeClassSuperPropExpr,
+ true, extending);
+ }
+ function assertValidClassSuperProps() {
+ // super.prop and super[prop] are valid, regardless of class heritage
+ assertValidClassSuperPropExtends(false);
+ assertValidClassSuperPropExtends(true);
+ }
+
+ function makeOLSuperPropStr(propStr, type, generator, args) {
+ let str = `({ ${makeSuperPropMethodStr(propStr, type, generator, args)} })`;
+ return str;
+ }
+ function makeOLSuperPropExpr(fun) {
+ return objExpr([{ type: "Property", key: ident("method"), value: fun }]);
+ }
+ function assertValidOLSuperProps() {
+ assertValidSuperPropTypes(assertExpr, makeOLSuperPropStr, makeOLSuperPropExpr);
+ }
+
+
+ // Check all valid uses of SuperProperty
+ assertValidClassSuperProps();
+ assertValidOLSuperProps();
+
+ // SuperProperty is forbidden outside of method definitions.
+ assertError("function foo () { super.prop; }", SyntaxError);
+ assertError("(function () { super.prop; }", SyntaxError);
+ assertError("(()=>super.prop)", SyntaxError);
+ assertError("function *foo() { super.prop; }", SyntaxError);
+ assertError("super.prop", SyntaxError);
+ assertError("function foo () { super['prop']; }", SyntaxError);
+ assertError("(function () { super['prop']; }", SyntaxError);
+ assertError("(()=>super['prop'])", SyntaxError);
+ assertError("function *foo() { super['prop']; }", SyntaxError);
+ assertError("super['prop']", SyntaxError);
+
+ // Or inside functions inside method definitions...
+ assertClassError("class NAME { constructor() { function nested() { super.prop; }}}", SyntaxError);
+
+ // Bare super is forbidden
+ assertError("super", SyntaxError);
+
+ // Even where super is otherwise allowed
+ assertError("{ foo() { super } }", SyntaxError);
+ assertClassError("class NAME { constructor() { super; } }", SyntaxError);
+
+ /* SuperCall */
+
+ // SuperCall is invalid outside derived class constructors.
+ assertError("super()", SyntaxError);
+ assertError("(function() { super(); })", SyntaxError);
+
+
+ // Even in class constructors
+ assertClassError("class NAME { constructor() { super(); } }", SyntaxError);
+
+ function superConstructor(args) {
+ return classMethod(ident("constructor"),
+ methodFun("NAME", "method", false,
+ [], [exprStmt(superCallExpr(args))]),
+ "method", false);
+ }
+
+ function superCallBody(args) {
+ return [exprStmt(superCallExpr(args))];
+ }
+
+ // SuperCall works with various argument configurations.
+ assertClass("class NAME extends null { constructor() { super() } }",
+ [ctorPlaceholder], lit(null), superCallBody([]));
+ assertClass("class NAME extends null { constructor() { super(1) } }",
+ [ctorPlaceholder], lit(null), superCallBody([lit(1)]));
+ assertClass("class NAME extends null { constructor() { super(1, a) } }",
+ [ctorPlaceholder], lit(null), superCallBody([lit(1), ident("a")]));
+ assertClass("class NAME extends null { constructor() { super(...[]) } }",
+ [ctorPlaceholder], lit(null), superCallBody([spread(arrExpr([]))]));
+
+ /* EOF */
+ // Clipped classes should throw a syntax error
+ assertClassError("class NAME {", SyntaxError);
+ assertClassError("class NAME {;", SyntaxError);
+ assertClassError("class NAME { constructor", SyntaxError);
+ assertClassError("class NAME { constructor(", SyntaxError);
+ assertClassError("class NAME { constructor()", SyntaxError);
+ assertClassError("class NAME { constructor()", SyntaxError);
+ assertClassError("class NAME { constructor() {", SyntaxError);
+ assertClassError("class NAME { constructor() { }", SyntaxError);
+ assertClassError("class NAME { static", SyntaxError);
+ assertClassError("class NAME { static y", SyntaxError);
+ assertClassError("class NAME { static *", SyntaxError);
+ assertClassError("class NAME { static *y", SyntaxError);
+ assertClassError("class NAME { static get", SyntaxError);
+ assertClassError("class NAME { static get y", SyntaxError);
+ assertClassError("class NAME { static ;", SyntaxError);
+ assertClassError("class NAME extends", SyntaxError);
+ assertClassError("class NAME { constructor() { super", SyntaxError);
+ assertClassError("class NAME { constructor() { super.", SyntaxError);
+ assertClassError("class NAME { constructor() { super.x", SyntaxError);
+ assertClassError("class NAME { constructor() { super.m(", SyntaxError);
+ assertClassError("class NAME { constructor() { super[", SyntaxError);
+ assertClassError("class NAME { constructor() { super(", SyntaxError);
+
+ // Can not omit curly brackets
+ assertClassError("class NAME { constructor() ({}) }", SyntaxError);
+ assertClassError("class NAME { constructor() void 0 }", SyntaxError);
+ assertClassError("class NAME { constructor() 1 }", SyntaxError);
+ assertClassError("class NAME { constructor() false }", SyntaxError);
+ assertClassError("class NAME { constructor() {} a() ({}) }", SyntaxError);
+ assertClassError("class NAME { constructor() {} a() void 0 }", SyntaxError);
+ assertClassError("class NAME { constructor() {} a() 1 }", SyntaxError);
+ assertClassError("class NAME { constructor() {} a() false }", SyntaxError);
+
+}
+
+runtest(testClasses);
diff --git a/js/src/tests/non262/reflect-parse/computedPropNames.js b/js/src/tests/non262/reflect-parse/computedPropNames.js
new file mode 100644
index 0000000000..c8cf8bc0f0
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/computedPropNames.js
@@ -0,0 +1,45 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// Bug 924688: computed property names
+assertExpr('a= {[field1]: "a", [field2=1]: "b"}',
+ aExpr("=", ident("a"),
+ objExpr([{ key: computedName(ident("field1")), value: lit("a")},
+ { key: computedName(aExpr("=", ident("field2"), lit(1))),
+ value: lit("b")}])));
+
+assertExpr('a= {["field1"]: "a", field2 : "b"}',
+ aExpr("=", ident("a"),
+ objExpr([{ key: computedName(lit("field1")), value: lit("a") },
+ { key: ident("field2"), value: lit("b") }])));
+
+assertExpr('a= {[1]: 1, 2 : 2}',
+ aExpr("=", ident("a"),
+ objExpr([{ key: computedName(lit(1)), value: lit(1) },
+ { key: lit(2), value: lit(2) }])));
+
+// Bug 924688: computed property names - location information
+var node = Reflect.parse("a = {[field1]: 5}");
+Pattern({ body: [ { expression: { right: { properties: [ {key: { loc:
+ { start: { line: 1, column: 6 }, end: { line: 1, column: 14 }}}}]}}}]}).match(node);
+
+// Bug 1048384 - Getter/setter syntax with computed names
+assertExpr("b = { get [meth]() { } }", aExpr("=", ident("b"),
+ objExpr([{ key: computedName(ident("meth")), value: funExpr(null, [], blockStmt([])),
+ method: false, kind: "get"}])));
+assertExpr("b = { set [meth](a) { } }", aExpr("=", ident("b"),
+ objExpr([{ key: computedName(ident("meth")), value: funExpr(null, [ident("a")],
+ blockStmt([])), method: false, kind: "set"}])));
+
+// Bug 1220702 - If it's not written as a method, `.method` should be false.
+assertExpr("({[x]: function () {}})",
+ objExpr([{
+ key: computedName(ident("x")),
+ value: funExpr(null, [], blockStmt([])),
+ method: false,
+ kind: "init"
+ }]));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/declarations.js b/js/src/tests/non262/reflect-parse/declarations.js
new file mode 100644
index 0000000000..4962f4cee9
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/declarations.js
@@ -0,0 +1,97 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// Bug 632056: constant-folding
+program([exprStmt(ident("f")),
+ ifStmt(lit(1),
+ blockStmt([funDecl(ident("f"), [], blockStmt([]))]),
+ null)]).assert(Reflect.parse("f; if (1) function f(){}"));
+// declarations
+
+assertDecl("var x = 1, y = 2, z = 3",
+ varDecl([{ id: ident("x"), init: lit(1) },
+ { id: ident("y"), init: lit(2) },
+ { id: ident("z"), init: lit(3) }]));
+assertDecl("var x, y, z",
+ varDecl([{ id: ident("x"), init: null },
+ { id: ident("y"), init: null },
+ { id: ident("z"), init: null }]));
+assertDecl("function foo() { }",
+ funDecl(ident("foo"), [], blockStmt([])));
+assertDecl("function foo() { return 42 }",
+ funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))])));
+
+assertDecl("function foo(...rest) { }",
+ funDecl(ident("foo"), [], blockStmt([]), [], ident("rest")));
+
+assertDecl("function foo(a=4) { }", funDecl(ident("foo"), [ident("a")], blockStmt([]), [lit(4)]));
+assertDecl("function foo(a, b=4) { }", funDecl(ident("foo"), [ident("a"), ident("b")], blockStmt([]), [null, lit(4)]));
+assertDecl("function foo(a, b=4, ...rest) { }",
+ funDecl(ident("foo"), [ident("a"), ident("b")], blockStmt([]), [null, lit(4), null], ident("rest")));
+assertDecl("function foo(a=(function () {})) { function a() {} }",
+ funDecl(ident("foo"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))]),
+ [funExpr(null, [], blockStmt([]))]));
+
+// Bug 1018628: default paremeter for destructuring
+assertDecl("function f(a=1, [x,y]=[2,3]) { }",
+ funDecl(ident("f"),
+ [ident("a"), arrPatt([ident("x"), ident("y")])],
+ blockStmt([]),
+ [lit(1), arrExpr([lit(2), lit(3)])]));
+
+// Bug 591437: rebound args have their defs turned into uses
+assertDecl("function f(a) { function a() { } }",
+ funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
+assertDecl("function f(a,b,c) { function b() { } }",
+ funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
+assertDecl("function f(a,[x,y]) { function a() { } }",
+ funDecl(ident("f"),
+ [ident("a"), arrPatt([assignElem("x"), assignElem("y")])],
+ blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
+
+// Bug 591450: this test currently crashes because of a bug in jsparse
+// assertDecl("function f(a,[x,y],b,[w,z],c) { function b() { } }",
+// funDecl(ident("f"),
+// [ident("a"), arrPatt([ident("x"), ident("y")]), ident("b"), arrPatt([ident("w"), ident("z")]), ident("c")],
+// blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
+
+// redeclarations (TOK_NAME nodes with lexdef)
+
+assertStmt("function f() { function g() { } function g() { } }",
+ funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
+ funDecl(ident("g"), [], blockStmt([]))])));
+
+// Fails due to parser quirks (bug 638577)
+//assertStmt("function f() { function g() { } function g() { return 42 } }",
+// funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
+// funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))])));
+
+assertStmt("function f() { var x = 42; var x = 43; }",
+ funDecl(ident("f"), [], blockStmt([varDecl([{ id: ident("x"), init: lit(42) }]),
+ varDecl([{ id: ident("x"), init: lit(43) }])])));
+
+
+assertDecl("var {x:y} = foo;", varDecl([{ id: objPatt([assignProp("x", ident("y"))]),
+ init: ident("foo") }]));
+assertDecl("var {x} = foo;", varDecl([{ id: objPatt([assignProp("x")]),
+ init: ident("foo") }]));
+
+// Bug 632030: redeclarations between var and funargs, var and function
+assertStmt("function g(x) { var x }",
+ funDecl(ident("g"), [ident("x")], blockStmt([varDecl([{ id: ident("x"), init: null }])])));
+assertProg("f.p = 1; var f; f.p; function f(){}",
+ [exprStmt(aExpr("=", dotExpr(ident("f"), ident("p")), lit(1))),
+ varDecl([{ id: ident("f"), init: null }]),
+ exprStmt(dotExpr(ident("f"), ident("p"))),
+ funDecl(ident("f"), [], blockStmt([]))]);
+}
+
+assertBlockStmt("{ function f(x) {} }",
+ blockStmt([funDecl(ident("f"), [ident("x")], blockStmt([]))]));
+
+// Annex B semantics should not change parse tree.
+assertBlockStmt("{ let f; { function f(x) {} } }",
+ blockStmt([letDecl([{ id: ident("f"), init: null }]),
+ blockStmt([funDecl(ident("f"), [ident("x")], blockStmt([]))])]));
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/destructuring-array-holes-reflect-as-null.js b/js/src/tests/non262/reflect-parse/destructuring-array-holes-reflect-as-null.js
new file mode 100644
index 0000000000..8005ecc5cd
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/destructuring-array-holes-reflect-as-null.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// Bug 632027: array holes should reflect as null
+assertExpr("[,]=[,]", aExpr("=", arrPatt([null]), arrExpr([null])));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/destructuring-assignment.js b/js/src/tests/non262/reflect-parse/destructuring-assignment.js
new file mode 100644
index 0000000000..cba4197ee9
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/destructuring-assignment.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// destructuring assignment
+
+function testAssignmentCombinations(makePattSrc, makePattPatt) {
+ var pattSrcs = makePatternCombinations(n => ("x" + n + " = 0"), makePattSrc);
+ var pattPatts = makePatternCombinations(n => (aExpr("=", ident("x" + n), lit(0))), makePattPatt);
+
+ for (var i = 0; i < pattSrcs.length; i++) {
+ var src = pattSrcs[i].join(",");
+ var patt = pattPatts[i].length === 1 ? pattPatts[i][0] : seqExpr(pattPatts[i]);
+
+ // assignment expression statement
+ assertExpr("(" + src + ")", patt);
+
+ // for-loop head assignment
+ assertStmt("for (" + src + "; foo; bar);",
+ forStmt(patt, ident("foo"), ident("bar"), emptyStmt));
+ }
+}
+
+testAssignmentCombinations(n => ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
+ n => (aExpr("=",
+ objPatt([assignProp("a" + n, ident("x" + n)),
+ assignProp("b" + n, ident("y" + n)),
+ assignProp("c" + n, ident("z" + n))]),
+ lit(0))));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/destructuring-function-parameters.js b/js/src/tests/non262/reflect-parse/destructuring-function-parameters.js
new file mode 100644
index 0000000000..6b3a777379
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/destructuring-function-parameters.js
@@ -0,0 +1,45 @@
+// |reftest| slow skip-if(!xulRuntime.shell)
+function test() {
+
+function testParamPatternCombinations(makePattSrc, makePattPatt) {
+ var pattSrcs = makePatternCombinations(n => ("x" + n), makePattSrc);
+ var pattPatts = makePatternCombinations(n => (ident("x" + n)), makePattPatt);
+
+ for (var i = 0; i < pattSrcs.length; i++) {
+ function makeSrc(body) {
+ return "(function(" + pattSrcs[i].join(",") + ") " + body + ")";
+ }
+ function makePatt(body) {
+ return funExpr(null, pattPatts[i], body);
+ }
+
+ // no upvars, block body
+ assertExpr(makeSrc("{ }"), makePatt(blockStmt([])));
+ // upvars, block body
+ assertExpr(makeSrc("{ return [x1,x2,x3,x4,x5]; }"),
+ makePatt(blockStmt([returnStmt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")]))])));
+ }
+}
+
+testParamPatternCombinations(n => ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "}"),
+ n => (objPatt([assignProp("a" + n, ident("x" + n)),
+ assignProp("b" + n, ident("y" + n)),
+ assignProp("c" + n, ident("z" + n))])));
+
+testParamPatternCombinations(n => ("{a" + n + ":x" + n + " = 10," + "b" + n + ":y" + n + " = 10," + "c" + n + ":z" + n + " = 10}"),
+ n => (objPatt([assignProp("a" + n, ident("x" + n), lit(10)),
+ assignProp("b" + n, ident("y" + n), lit(10)),
+ assignProp("c" + n, ident("z" + n), lit(10))])));
+
+testParamPatternCombinations(n => ("[x" + n + "," + "y" + n + "," + "z" + n + "]"),
+ n => (arrPatt([assignElem("x" + n), assignElem("y" + n), assignElem("z" + n)])));
+
+testParamPatternCombinations(n => ("[a" + n + ", ..." + "b" + n + "]"),
+ n => (arrPatt([assignElem("a" + n), spread(ident("b" + n))])));
+
+testParamPatternCombinations(n => ("[a" + n + ", " + "b" + n + " = 10]"),
+ n => (arrPatt([assignElem("a" + n), assignElem("b" + n, lit(10))])));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/destructuring-variable-declarations.js b/js/src/tests/non262/reflect-parse/destructuring-variable-declarations.js
new file mode 100644
index 0000000000..6a455668af
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/destructuring-variable-declarations.js
@@ -0,0 +1,58 @@
+// |reftest| slow skip-if(!xulRuntime.shell)
+function test() {
+
+function testVarPatternCombinations(makePattSrc, makePattPatt) {
+ var pattSrcs = makePatternCombinations(n => ("x" + n), makePattSrc);
+ var pattPatts = makePatternCombinations(n => ({ id: ident("x" + n), init: null }), makePattPatt);
+ // It's illegal to have uninitialized const declarations, so we need a
+ // separate set of patterns and sources.
+ var constSrcs = makePatternCombinations(n => ("x" + n + " = undefined"), makePattSrc);
+ var constPatts = makePatternCombinations(n => ({ id: ident("x" + n), init: ident("undefined") }), makePattPatt);
+
+ for (var i = 0; i < pattSrcs.length; i++) {
+ // variable declarations in blocks
+ assertDecl("var " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
+
+ assertGlobalDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
+ assertLocalDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
+ assertBlockDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
+
+ assertDecl("const " + constSrcs[i].join(",") + ";", constDecl(constPatts[i]));
+
+ // variable declarations in for-loop heads
+ assertStmt("for (var " + pattSrcs[i].join(",") + "; foo; bar);",
+ forStmt(varDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
+ assertStmt("for (let " + pattSrcs[i].join(",") + "; foo; bar);",
+ forStmt(letDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
+ assertStmt("for (const " + constSrcs[i].join(",") + "; foo; bar);",
+ forStmt(constDecl(constPatts[i]), ident("foo"), ident("bar"), emptyStmt));
+ }
+}
+
+testVarPatternCombinations(n => ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
+ n => ({ id: objPatt([assignProp("a" + n, ident("x" + n)),
+ assignProp("b" + n, ident("y" + n)),
+ assignProp("c" + n, ident("z" + n))]),
+ init: lit(0) }));
+
+testVarPatternCombinations(n => ("{a" + n + ":x" + n + " = 10," + "b" + n + ":y" + n + " = 10," + "c" + n + ":z" + n + " = 10} = 0"),
+ n => ({ id: objPatt([assignProp("a" + n, ident("x" + n), lit(10)),
+ assignProp("b" + n, ident("y" + n), lit(10)),
+ assignProp("c" + n, ident("z" + n), lit(10))]),
+ init: lit(0) }));
+
+testVarPatternCombinations(n => ("[x" + n + "," + "y" + n + "," + "z" + n + "] = 0"),
+ n => ({ id: arrPatt([assignElem("x" + n), assignElem("y" + n), assignElem("z" + n)]),
+ init: lit(0) }));
+
+testVarPatternCombinations(n => ("[a" + n + ", ..." + "b" + n + "] = 0"),
+ n => ({ id: arrPatt([assignElem("a" + n), spread(ident("b" + n))]),
+ init: lit(0) }));
+
+testVarPatternCombinations(n => ("[a" + n + ", " + "b" + n + " = 10] = 0"),
+ n => ({ id: arrPatt([assignElem("a" + n), assignElem("b" + n, lit(10))]),
+ init: lit(0) }));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/destructuring__proto__.js b/js/src/tests/non262/reflect-parse/destructuring__proto__.js
new file mode 100644
index 0000000000..3238904086
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/destructuring__proto__.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// |reftest| skip-if(!xulRuntime.shell)
+// bug 963641
+
+Reflect.parse("({ __proto__: null });");
+Reflect.parse("var { __proto__: x } = obj;");
+Reflect.parse("var [{ __proto__: y }] = obj;");
+Reflect.parse("[{ __proto__: y }] = arr;");
+Reflect.parse("({ __proto__: y } = obj);");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+
+
+print("Tests complete");
diff --git a/js/src/tests/non262/reflect-parse/expression-short-circuit-compound-assignment.js b/js/src/tests/non262/reflect-parse/expression-short-circuit-compound-assignment.js
new file mode 100644
index 0000000000..abec4a18af
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/expression-short-circuit-compound-assignment.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+function test() {
+
+assertExpr("(x ??= y)", aExpr("??=", ident("x"), ident("y")));
+assertExpr("(x ||= y)", aExpr("||=", ident("x"), ident("y")));
+assertExpr("(x &&= y)", aExpr("&&=", ident("x"), ident("y")));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/expression.js b/js/src/tests/non262/reflect-parse/expression.js
new file mode 100644
index 0000000000..c91525aa98
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/expression.js
@@ -0,0 +1,193 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// primary expressions
+assertExpr("true", lit(true));
+assertExpr("false", lit(false));
+assertExpr("42", lit(42));
+assertExpr("(/asdf/)", lit(/asdf/));
+assertExpr("this", thisExpr);
+assertExpr("foo", ident("foo"));
+if ("BigInt" in this) {
+ assertExpr("1234n", lit(BigInt(1234)));
+}
+
+// member expressions
+assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar")));
+assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar")));
+assertExpr("foo['bar']", memExpr(ident("foo"), lit("bar")));
+assertExpr("foo[42]", memExpr(ident("foo"), lit(42)));
+
+// optional member expressions
+assertExpr("foo?.bar", optExpr(optDotExpr(ident("foo"), ident("bar"))));
+assertExpr("foo?.bar.baz", optExpr(dotExpr(optDotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo.bar?.baz", optExpr(optDotExpr(dotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo?.bar?.baz", optExpr(optDotExpr(optDotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo?.[bar].baz", optExpr(dotExpr(optMemExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo.bar?.[baz]", optExpr(optMemExpr(dotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo[bar]?.[baz]", optExpr(optMemExpr(memExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo?.[bar][baz]", optExpr(memExpr(optMemExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("foo?.['bar']?.['baz']", optExpr(optMemExpr(optMemExpr(ident("foo"), lit("bar")), lit("baz"))));
+assertExpr("foo?.[bar]?.baz", optExpr(optDotExpr(optMemExpr(ident("foo"), ident("bar")), ident("baz"))));
+
+// delete optional expressions
+assertExpr("\ndelete [] ?. [1]", delOptExpr(optMemExpr(arrExpr([]), lit(1))));
+assertExpr("delete foo?.bar", delOptExpr(optDotExpr(ident("foo"), ident("bar"))));
+assertExpr("delete foo?.bar.baz", delOptExpr(dotExpr(optDotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo.bar?.baz", delOptExpr(optDotExpr(dotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo?.bar?.baz", delOptExpr(optDotExpr(optDotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo?.[bar].baz", delOptExpr(dotExpr(optMemExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo.bar?.[baz]", delOptExpr(optMemExpr(dotExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo[bar]?.[baz]", delOptExpr(optMemExpr(memExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo?.[bar][baz]", delOptExpr(memExpr(optMemExpr(ident("foo"), ident("bar")), ident("baz"))));
+assertExpr("delete foo?.['bar']?.['baz']", delOptExpr(optMemExpr(optMemExpr(ident("foo"), lit("bar")), lit("baz"))));
+assertExpr("delete foo?.[bar]?.baz", delOptExpr(optDotExpr(optMemExpr(ident("foo"), ident("bar")), ident("baz"))));
+
+// function expressions
+assertExpr("(function(){})", funExpr(null, [], blockStmt([])));
+assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([])));
+assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([])));
+assertExpr("a => a", arrowExpr([ident("a")], ident("a")));
+assertExpr("(a) => a", arrowExpr([ident("a")], ident("a")));
+assertExpr("a => b => a", arrowExpr([ident("a")], arrowExpr([ident("b")], ident("a"))));
+assertExpr("a => {}", arrowExpr([ident("a")], blockStmt([])));
+assertExpr("a => ({})", arrowExpr([ident("a")], objExpr([])));
+assertExpr("(a, b, c) => {}", arrowExpr([ident("a"), ident("b"), ident("c")], blockStmt([])));
+assertExpr("([a, b]) => {}", arrowExpr([arrPatt([assignElem("a"), assignElem("b")])], blockStmt([])));
+
+// Unary expressions
+assertExpr("(++x)", updExpr("++", ident("x"), true));
+assertExpr("(x++)", updExpr("++", ident("x"), false));
+assertExpr("(+x)", unExpr("+", ident("x")));
+assertExpr("(-x)", unExpr("-", ident("x")));
+assertExpr("(!x)", unExpr("!", ident("x")));
+assertExpr("(~x)", unExpr("~", ident("x")));
+assertExpr("(delete x)", unExpr("delete", ident("x")));
+assertExpr("(typeof x)", unExpr("typeof", ident("x")));
+assertExpr("(void x)", unExpr("void", ident("x")));
+
+// Bug 632026: constant-folding
+assertExpr("typeof(0?0:a)", unExpr("typeof", condExpr(lit(0), lit(0), ident("a"))));
+
+// Binary exporessions
+assertExpr("(x == y)", binExpr("==", ident("x"), ident("y")));
+assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y")));
+assertExpr("(x === y)", binExpr("===", ident("x"), ident("y")));
+assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y")));
+assertExpr("(x < y)", binExpr("<", ident("x"), ident("y")));
+assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y")));
+assertExpr("(x > y)", binExpr(">", ident("x"), ident("y")));
+assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y")));
+assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y")));
+assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y")));
+assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y")));
+assertExpr("(x + y)", binExpr("+", ident("x"), ident("y")));
+assertExpr("(w + x + y + z)", binExpr("+", binExpr("+", binExpr("+", ident("w"), ident("x")), ident("y")), ident("z")));
+assertExpr("(x - y)", binExpr("-", ident("x"), ident("y")));
+assertExpr("(w - x - y - z)", binExpr("-", binExpr("-", binExpr("-", ident("w"), ident("x")), ident("y")), ident("z")));
+assertExpr("(x * y)", binExpr("*", ident("x"), ident("y")));
+assertExpr("(x / y)", binExpr("/", ident("x"), ident("y")));
+assertExpr("(x % y)", binExpr("%", ident("x"), ident("y")));
+assertExpr("(x | y)", binExpr("|", ident("x"), ident("y")));
+assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y")));
+assertExpr("(x & y)", binExpr("&", ident("x"), ident("y")));
+assertExpr("(x in y)", binExpr("in", ident("x"), ident("y")));
+assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y")));
+
+// Bug 571617: eliminate constant-folding
+assertExpr("2 + 3", binExpr("+", lit(2), lit(3)));
+
+// Assignment expressions
+assertExpr("(x = y)", aExpr("=", ident("x"), ident("y")));
+assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y")));
+assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y")));
+assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y")));
+assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y")));
+assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y")));
+assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y")));
+assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y")));
+assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
+assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
+assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
+assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
+
+// Conditional expressions
+assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
+assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
+assertExpr("(x ?? y)", logExpr("??", ident("x"), ident("y")));
+assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z")))
+assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
+
+// Sequence expressions
+assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
+assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
+assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));
+
+// Call expressions
+assertExpr("(new Object)", newExpr(ident("Object"), []));
+assertExpr("(new Object())", newExpr(ident("Object"), []));
+assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)]));
+assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)]));
+assertExpr("(String())", callExpr(ident("String"), []));
+assertExpr("(String(42))", callExpr(ident("String"), [lit(42)]));
+assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)]));
+
+// Optional Call expressions
+assertExpr("(String?.())", optExpr(optCallExpr(ident("String"), [])));
+assertExpr("(String?.(42))", optExpr(optCallExpr(ident("String"), [lit(42)])));
+assertExpr("(String?.(1,2,3))", optExpr(optCallExpr(ident("String"), [lit(1),lit(2),lit(3)])));
+assertExpr("(String?.foo?.())", optExpr(optCallExpr(optDotExpr(ident("String"), ident("foo")), [])));
+assertExpr("(String.foo?.())", optExpr(optCallExpr(dotExpr(ident("String"), ident("foo")), [])));
+assertExpr("(String?.foo)()", callExpr(optExpr(optDotExpr(ident("String"), ident("foo"))), []));
+assertExpr("(String?.foo)?.()", optExpr(optCallExpr(optExpr(optDotExpr(ident("String"), ident("foo"))), [])));
+
+// Array expressions
+assertExpr("[]", arrExpr([]));
+assertExpr("[1]", arrExpr([lit(1)]));
+assertExpr("[1,2]", arrExpr([lit(1),lit(2)]));
+assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)]));
+assertExpr("[1,,2,3]", arrExpr([lit(1),null,lit(2),lit(3)]));
+assertExpr("[1,,,2,3]", arrExpr([lit(1),null,null,lit(2),lit(3)]));
+assertExpr("[1,,,2,,3]", arrExpr([lit(1),null,null,lit(2),null,lit(3)]));
+assertExpr("[1,,,2,,,3]", arrExpr([lit(1),null,null,lit(2),null,null,lit(3)]));
+assertExpr("[,1,2,3]", arrExpr([null,lit(1),lit(2),lit(3)]));
+assertExpr("[,,1,2,3]", arrExpr([null,null,lit(1),lit(2),lit(3)]));
+assertExpr("[,,,1,2,3]", arrExpr([null,null,null,lit(1),lit(2),lit(3)]));
+assertExpr("[,,,1,2,3,]", arrExpr([null,null,null,lit(1),lit(2),lit(3)]));
+assertExpr("[,,,1,2,3,,]", arrExpr([null,null,null,lit(1),lit(2),lit(3),null]));
+assertExpr("[,,,1,2,3,,,]", arrExpr([null,null,null,lit(1),lit(2),lit(3),null,null]));
+assertExpr("[,,,,,]", arrExpr([null,null,null,null,null]));
+assertExpr("[1, ...a, 2]", arrExpr([lit(1), spread(ident("a")), lit(2)]));
+assertExpr("[,, ...a,, ...b, 42]", arrExpr([null,null, spread(ident("a")),, spread(ident("b")), lit(42)]));
+assertExpr("[1,(2,3)]", arrExpr([lit(1),seqExpr([lit(2),lit(3)])]));
+assertExpr("[,(2,3)]", arrExpr([null,seqExpr([lit(2),lit(3)])]));
+
+// Object expressions
+assertExpr("({})", objExpr([]));
+assertExpr("({x:1})", objExpr([{ key: ident("x"), value: lit(1) }]));
+assertExpr("({x:x, y})", objExpr([{ key: ident("x"), value: ident("x"), shorthand: false },
+ { key: ident("y"), value: ident("y"), shorthand: true }]));
+assertExpr("({x:1, y:2})", objExpr([{ key: ident("x"), value: lit(1) },
+ { key: ident("y"), value: lit(2) } ]));
+assertExpr("({x:1, y:2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
+ { key: ident("y"), value: lit(2) },
+ { key: ident("z"), value: lit(3) } ]));
+assertExpr("({x:1, 'y':2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
+ { key: lit("y"), value: lit(2) },
+ { key: ident("z"), value: lit(3) } ]));
+assertExpr("({'x':1, 'y':2, z:3})", objExpr([{ key: lit("x"), value: lit(1) },
+ { key: lit("y"), value: lit(2) },
+ { key: ident("z"), value: lit(3) } ]));
+assertExpr("({'x':1, 'y':2, 3:3})", objExpr([{ key: lit("x"), value: lit(1) },
+ { key: lit("y"), value: lit(2) },
+ { key: lit(3), value: lit(3) } ]));
+assertExpr("({__proto__:x})", objExpr([{ type: "PrototypeMutation", value: ident("x") }]));
+assertExpr("({'__proto__':x})", objExpr([{ type: "PrototypeMutation", value: ident("x") }]));
+assertExpr("({['__proto__']:x})", objExpr([{ type: "Property", key: comp(lit("__proto__")), value: ident("x") }]));
+assertExpr("({['__proto__']:q, __proto__() {}, __proto__: null })",
+ objExpr([{ type: "Property", key: comp(lit("__proto__")), value: ident("q") },
+ { type: "Property", key: ident("__proto__"), method: true },
+ { type: "PrototypeMutation", value: lit(null) }]));
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/for-loop-destructuring.js b/js/src/tests/non262/reflect-parse/for-loop-destructuring.js
new file mode 100644
index 0000000000..06a745334e
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/for-loop-destructuring.js
@@ -0,0 +1,47 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// destructuring in for-in and for-of loop heads
+
+var axbycz = objPatt([assignProp("a", ident("x")),
+ assignProp("b", ident("y")),
+ assignProp("c", ident("z"))]);
+var xyz = arrPatt([assignElem("x"), assignElem("y"), assignElem("z")]);
+
+assertStmt("for (var {a:x,b:y,c:z} in foo);", forInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (let {a:x,b:y,c:z} in foo);", forInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for ({a:x,b:y,c:z} in foo);", forInStmt(axbycz, ident("foo"), emptyStmt));
+assertStmt("for (var [x,y,z] in foo);", forInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (let [x,y,z] in foo);", forInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for ([x,y,z] in foo);", forInStmt(xyz, ident("foo"), emptyStmt));
+assertStmt("for (var {a:x,b:y,c:z} of foo);", forOfStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (let {a:x,b:y,c:z} of foo);", forOfStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for ({a:x,b:y,c:z} of foo);", forOfStmt(axbycz, ident("foo"), emptyStmt));
+assertStmt("for (var [x,y,z] of foo);", forOfStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (let [x,y,z] of foo);", forOfStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for ([x,y,z] of foo);", forOfStmt(xyz, ident("foo"), emptyStmt));
+
+assertStmt("for (const x in foo);",
+ forInStmt(constDecl([{ id: ident("x"), init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (const {a:x,b:y,c:z} in foo);",
+ forInStmt(constDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (const [x,y,z] in foo);",
+ forInStmt(constDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
+
+assertStmt("for (const x of foo);",
+ forOfStmt(constDecl([{id: ident("x"), init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (const {a:x,b:y,c:z} of foo);",
+ forOfStmt(constDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
+assertStmt("for (const [x,y,z] of foo);",
+ forOfStmt(constDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
+
+assertError("for (x = 22 in foo);", SyntaxError);-
+assertError("for ({a:x,b:y,c:z} = 22 in foo);", SyntaxError);
+assertError("for ([x,y,z] = 22 in foo);", SyntaxError);
+assertError("for (const x = 22 in foo);", SyntaxError);
+assertError("for (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
+assertError("for (const [x,y,z] = 22 in foo);", SyntaxError);
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/generators.js b/js/src/tests/non262/reflect-parse/generators.js
new file mode 100644
index 0000000000..14bac5b527
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/generators.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// generators
+
+assertDecl("function* gen() {}", genFunDecl("es6", ident("gen"), [], blockStmt([])));
+assertExpr("(function*() {})", genFunExpr("es6", null, [], blockStmt([])));
+assertExpr("(function* gen() {})", genFunExpr("es6", ident("gen"), [], blockStmt([])));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/lexicals.js b/js/src/tests/non262/reflect-parse/lexicals.js
new file mode 100644
index 0000000000..c42c43c32f
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/lexicals.js
@@ -0,0 +1,19 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// global let is var
+assertGlobalDecl("let {x:y} = foo;", letDecl([{ id: objPatt([assignProp("x", ident("y"))]),
+ init: ident("foo") }]));
+// function-global let is let
+assertLocalDecl("let {x:y} = foo;", letDecl([{ id: objPatt([assignProp("x", ident("y"))]),
+ init: ident("foo") }]));
+// block-local let is let
+assertBlockDecl("let {x:y} = foo;", letDecl([{ id: objPatt([assignProp("x", ident("y"))]),
+ init: ident("foo") }]));
+
+assertDecl("const {x:y} = foo;", constDecl([{ id: objPatt([assignProp("x", ident("y"))]),
+ init: ident("foo") }]));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/location.js b/js/src/tests/non262/reflect-parse/location.js
new file mode 100644
index 0000000000..09d3870848
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/location.js
@@ -0,0 +1,33 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// Source location information
+var withoutFileOrLine = Reflect.parse("42");
+var withFile = Reflect.parse("42", {source:"foo.js"});
+var withFileAndLine = Reflect.parse("42", {source:"foo.js", line:111});
+
+Pattern({ source: null, start: { line: 1, column: 1 }, end: { line: 1, column: 3 } }).match(withoutFileOrLine.loc);
+Pattern({ source: "foo.js", start: { line: 1, column: 1 }, end: { line: 1, column: 3 } }).match(withFile.loc);
+Pattern({ source: "foo.js", start: { line: 111, column: 1 }, end: { line: 111, column: 3 } }).match(withFileAndLine.loc);
+
+var withoutFileOrLine2 = Reflect.parse("foo +\nbar");
+var withFile2 = Reflect.parse("foo +\nbar", {source:"foo.js"});
+var withFileAndLine2 = Reflect.parse("foo +\nbar", {source:"foo.js", line:111});
+
+Pattern({ source: null, start: { line: 1, column: 1 }, end: { line: 2, column: 4 } }).match(withoutFileOrLine2.loc);
+Pattern({ source: "foo.js", start: { line: 1, column: 1 }, end: { line: 2, column: 4 } }).match(withFile2.loc);
+Pattern({ source: "foo.js", start: { line: 111, column: 1 }, end: { line: 112, column: 4 } }).match(withFileAndLine2.loc);
+
+var nested = Reflect.parse("(-b + sqrt(sqr(b) - 4 * a * c)) / (2 * a)", {source:"quad.js"});
+var fourAC = nested.body[0].expression.left.right.arguments[0].right;
+
+Pattern({ source: "quad.js", start: { line: 1, column: 21 }, end: { line: 1, column: 30 } }).match(fourAC.loc);
+
+// No source location
+
+assertEq("loc" in Reflect.parse("42", {loc:false}), false);
+program([exprStmt(lit(42))]).assert(Reflect.parse("42", {loc:false}));
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/methodDefn.js b/js/src/tests/non262/reflect-parse/methodDefn.js
new file mode 100644
index 0000000000..cad9b44435
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/methodDefn.js
@@ -0,0 +1,51 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// Bug 924672: Method definitions
+assertExpr("b = { a() { } }", aExpr("=", ident("b"),
+ objExpr([{ key: ident("a"), value: funExpr(ident("a"), [], blockStmt([])), method:
+ true}])));
+
+assertExpr("b = { *a() { } }", aExpr("=", ident("b"),
+ objExpr([{ key: ident("a"), value: genFunExpr("es6", ident("a"), [], blockStmt([])), method:
+ true}])));
+
+// Method definitions without braces
+assertError("({ a() void 0 })", SyntaxError);
+assertError("({ a() 1 })", SyntaxError);
+assertError("({ a() false })", SyntaxError);
+
+// getters and setters
+
+assertExpr("({ get x() { return 42 } })",
+ objExpr([ { key: ident("x"),
+ value: funExpr(ident("get x"), [], blockStmt([returnStmt(lit(42))])),
+ kind: "get" } ]));
+assertExpr("({ set x(v) { return 42 } })",
+ objExpr([ { key: ident("x"),
+ value: funExpr(ident("set x"), [ident("v")], blockStmt([returnStmt(lit(42))])),
+ kind: "set" } ]));
+
+// Bug 1073809 - Getter/setter syntax with generators
+assertExpr("({*get() { }})", objExpr([{ type: "Property", key: ident("get"), method: true,
+ value: genFunExpr("es6", ident("get"), [], blockStmt([]))}]));
+assertExpr("({*set() { }})", objExpr([{ type: "Property", key: ident("set"), method: true,
+ value: genFunExpr("es6", ident("set"), [], blockStmt([]))}]));
+assertError("({*get foo() { }})", SyntaxError);
+assertError("({*set foo() { }})", SyntaxError);
+
+assertError("({ *get 1() {} })", SyntaxError);
+assertError("({ *get \"\"() {} })", SyntaxError);
+assertError("({ *get foo() {} })", SyntaxError);
+assertError("({ *get []() {} })", SyntaxError);
+assertError("({ *get [1]() {} })", SyntaxError);
+
+assertError("({ *set 1() {} })", SyntaxError);
+assertError("({ *set \"\"() {} })", SyntaxError);
+assertError("({ *set foo() {} })", SyntaxError);
+assertError("({ *set []() {} })", SyntaxError);
+assertError("({ *set [1]() {} })", SyntaxError);
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/module-export-name.js b/js/src/tests/non262/reflect-parse/module-export-name.js
new file mode 100644
index 0000000000..9b51bf910b
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/module-export-name.js
@@ -0,0 +1,121 @@
+// |reftest| skip-if(!xulRuntime.shell) shell-option(--enable-import-assertions)
+
+function moduleRequest(source, attributes) {
+ return {
+ type: "ModuleRequest",
+ source,
+ attributes,
+ };
+}
+
+function importAttribute(key, value) {
+ return {
+ type: "ImportAttribute",
+ key,
+ value,
+ };
+}
+
+function importDecl(specifiers, moduleRequest) {
+ return {
+ type: "ImportDeclaration",
+ specifiers,
+ moduleRequest,
+ };
+}
+
+function importSpec(id, name) {
+ return {
+ type: "ImportSpecifier",
+ id,
+ name,
+ };
+}
+
+function exportDecl(declaration, specifiers, moduleRequest, isDefault) {
+ return {
+ type: "ExportDeclaration",
+ declaration,
+ specifiers,
+ moduleRequest,
+ isDefault,
+ };
+}
+
+function exportSpec(id, name) {
+ return {
+ type: "ExportSpecifier",
+ id,
+ name,
+ };
+}
+
+function exportNamespaceSpec(name) {
+ return {
+ type: "ExportNamespaceSpecifier",
+ name,
+ };
+}
+
+function assertModule(src, patt) {
+ program(patt).assert(Reflect.parse(src, {target: "module"}));
+}
+
+assertModule(`
+ import {"x" as y} from "module";
+`, [
+ importDecl([importSpec(literal("x"), ident("y"))], moduleRequest(literal("module"), [])),
+]);
+
+assertModule(`
+ var x;
+ export {x as "y"};
+`, [
+ varDecl([{id: ident("x"), init: null}]),
+ exportDecl(null, [exportSpec(ident("x"), literal("y"))], null, false),
+]);
+
+assertModule(`
+ export {x as "y"} from "module";
+`, [
+ exportDecl(null, [exportSpec(ident("x"), literal("y"))], moduleRequest(literal("module"), []), false),
+]);
+
+assertModule(`
+ export {"x" as y} from "module";
+`, [
+ exportDecl(null, [exportSpec(literal("x"), ident("y"))], moduleRequest(literal("module"), []), false),
+]);
+
+assertModule(`
+ export {"x" as "y"} from "module";
+`, [
+ exportDecl(null, [exportSpec(literal("x"), literal("y"))], moduleRequest(literal("module"), []), false),
+]);
+
+assertModule(`
+ export {"x"} from "module";
+`, [
+ exportDecl(null, [exportSpec(literal("x"), literal("x"))], moduleRequest(literal("module"), []), false),
+]);
+
+assertModule(`
+ export * as "x" from "module";
+`, [
+ exportDecl(null, [exportNamespaceSpec(literal("x"))], moduleRequest(literal("module"), []), false),
+]);
+if (getRealmConfiguration("importAttributes")) {
+ assertModule(`
+ import {"x" as y} from "module" with {type: "json"};
+ `, [
+ importDecl([importSpec(literal("x"), ident("y"))], moduleRequest(literal("module"), [importAttribute(ident("type"), literal("json"))])),
+ ]);
+ assertModule(`
+ import {"x" as y} from "module" assert {type: "json"};
+ `, [
+ importDecl([importSpec(literal("x"), ident("y"))], moduleRequest(literal("module"), [importAttribute(ident("type"), literal("json"))])),
+ ]);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/reflect-parse/newTarget.js b/js/src/tests/non262/reflect-parse/newTarget.js
new file mode 100644
index 0000000000..3db2c2726d
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/newTarget.js
@@ -0,0 +1,42 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function testNewTarget() {
+
+ // new.target is currently valid inside any non-arrow, non-generator function
+ assertInFunctionExpr("new.target", newTarget());
+
+ // even with gratuitous whitespace.
+ assertInFunctionExpr(`new.
+ target`, newTarget());
+
+ // invalid in top-level scripts
+ assertError("new.target", SyntaxError);
+
+ // valid in arrow functions inside functions
+ assertInFunctionExpr("()=>new.target", arrowExpr([], newTarget()));
+ assertError("(() => new.target))", SyntaxError);
+
+ // valid in generators, too!
+ assertStmt("function *foo() { new.target; }", genFunDecl("es6", ident("foo"), [],
+ blockStmt([exprStmt(newTarget())])));
+
+ // new.target is a member expression. You should be able to call, invoke, or
+ // access properties of it.
+ assertInFunctionExpr("new.target.foo", dotExpr(newTarget(), ident("foo")));
+ assertInFunctionExpr("new.target[\"foo\"]", memExpr(newTarget(), literal("foo")));
+
+ assertInFunctionExpr("new.target()", callExpr(newTarget(), []));
+ assertInFunctionExpr("new new.target()", newExpr(newTarget(), []));
+
+ // assignment to newTarget is an error
+ assertError("new.target = 4", SyntaxError);
+
+ // only new.target is a valid production, no shorn names or other names
+ assertError("new.", SyntaxError);
+ assertError("new.foo", SyntaxError);
+ assertError("new.targe", SyntaxError);
+
+ // obj.new.target is still a member expression
+ assertExpr("obj.new.target", dotExpr(dotExpr(ident("obj"), ident("new")), ident("target")));
+}
+
+runtest(testNewTarget);
diff --git a/js/src/tests/non262/reflect-parse/object-rest.js b/js/src/tests/non262/reflect-parse/object-rest.js
new file mode 100644
index 0000000000..1c35034aa1
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/object-rest.js
@@ -0,0 +1,41 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+function property(key, value = key, shorthand = key === value) {
+ return { key, value, shorthand };
+}
+
+function assertDestrAssign(src, pattern) {
+ assertExpr(`(${src} = 0)`, aExpr("=", pattern, lit(0)));
+}
+
+function assertDestrBinding(src, pattern) {
+ assertDecl(`var ${src} = 0`, varDecl([{id: pattern, init: lit(0)}]));
+}
+
+function test() {
+ // Target expression must be a simple assignment target in object assignment patterns.
+ assertDestrAssign("{...x}", objPatt([spread(ident("x"))]));
+ assertDestrAssign("{...(x)}", objPatt([spread(ident("x"))]));
+ assertDestrAssign("{...obj.p}", objPatt([spread(dotExpr(ident("obj"), ident("p")))]));
+ assertDestrAssign("{...(obj.p)}", objPatt([spread(dotExpr(ident("obj"), ident("p")))]));
+
+ // Object binding patterns only allow binding identifiers.
+ assertDestrBinding("{...x}", objPatt([spread(ident("x"))]));
+
+ // The rest-property can be preceded by other properties.
+ for (var assertDestr of [assertDestrAssign, assertDestrBinding]) {
+ assertDestr("{a, ...x}", objPatt([property(ident("a")), spread(ident("x"))]));
+ assertDestr("{a: b, ...x}", objPatt([property(ident("a"), ident("b")), spread(ident("x"))]));
+ assertDestr("{[a]: b, ...x}", objPatt([property(comp(ident("a")), ident("b")), spread(ident("x"))]));
+ }
+
+ // Tests when __proto__ is used in the object pattern.
+ for (var assertDestr of [assertDestrAssign, assertDestrBinding]) {
+ assertDestr("{...__proto__}", objPatt([spread(ident("__proto__"))]));
+ assertDestr("{__proto__, ...x}", objPatt([property(ident("__proto__")), spread(ident("x"))]));
+ }
+ assertDestrAssign("{__proto__: a, ...x}", objPatt([property(lit("__proto__"), ident("a")), spread(ident("x"))]));
+ assertDestrBinding("{__proto__: a, ...x}", objPatt([property(ident("__proto__"), ident("a")), spread(ident("x"))]));
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/object-spread.js b/js/src/tests/non262/reflect-parse/object-spread.js
new file mode 100644
index 0000000000..a4b269c409
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/object-spread.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!xulRuntime.shell)
+
+function property(key, value = key, shorthand = key === value) {
+ return { key, value, shorthand };
+}
+
+function test() {
+ // Any expression can be spreaded.
+ assertExpr("({...x})", objExpr([spread(ident("x"))]));
+ assertExpr("({...f()})", objExpr([spread(callExpr(ident("f"), []))]));
+ assertExpr("({...123})", objExpr([spread(lit(123))]));
+
+ // Multiple spread expression are allowed.
+ assertExpr("({...x, ...obj.p})", objExpr([spread(ident("x")), spread(dotExpr(ident("obj"), ident("p")))]));
+
+ // Spread expression can appear anywhere in an object literal.
+ assertExpr("({p, ...x})", objExpr([property(ident("p")), spread(ident("x"))]));
+ assertExpr("({p: a, ...x})", objExpr([property(ident("p"), ident("a")), spread(ident("x"))]));
+ assertExpr("({...x, p: a})", objExpr([spread(ident("x")), property(ident("p"), ident("a"))]));
+
+ // Trailing comma after spread expression is allowed.
+ assertExpr("({...x,})", objExpr([spread(ident("x"))]));
+
+ // __proto__ is not special in spread expressions.
+ assertExpr("({...__proto__})", objExpr([spread(ident("__proto__"))]));
+ assertExpr("({...__proto__, ...__proto__})", objExpr([spread(ident("__proto__")), spread(ident("__proto__"))]));
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/proxyArgs.js b/js/src/tests/non262/reflect-parse/proxyArgs.js
new file mode 100644
index 0000000000..771b61ad66
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/proxyArgs.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// |reftest| skip-if(!xulRuntime.shell)
+// bug 905774
+
+// Proxy options
+var opts = new Proxy({loc: false}, {});
+assertEq("loc" in Reflect.parse("0;", opts), false);
+opts.loc = true;
+assertEq(Reflect.parse("0;", opts).loc !== null, true);
+delete opts.loc;
+assertEq(Reflect.parse("0;", opts).loc !== null, true); // default is true
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/reflect-parse/shell.js b/js/src/tests/non262/reflect-parse/shell.js
new file mode 100644
index 0000000000..665e3fe59d
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/shell.js
@@ -0,0 +1,66 @@
+loadRelativeToScript('PatternAsserts.js');
+
+// various combinations of identifiers and destructuring patterns:
+function makePatternCombinations(id, destr)
+{
+ return [
+ [ id(1) ],
+ [ id(1), id(2) ],
+ [ id(1), id(2), id(3) ],
+ [ id(1), id(2), id(3), id(4) ],
+ [ id(1), id(2), id(3), id(4), id(5) ],
+
+ [ destr(1) ],
+ [ destr(1), destr(2) ],
+ [ destr(1), destr(2), destr(3) ],
+ [ destr(1), destr(2), destr(3), destr(4) ],
+ [ destr(1), destr(2), destr(3), destr(4), destr(5) ],
+
+ [ destr(1), id(2) ],
+
+ [ destr(1), id(2), id(3) ],
+ [ destr(1), id(2), id(3), id(4) ],
+ [ destr(1), id(2), id(3), id(4), id(5) ],
+ [ destr(1), id(2), id(3), id(4), destr(5) ],
+ [ destr(1), id(2), id(3), destr(4) ],
+ [ destr(1), id(2), id(3), destr(4), id(5) ],
+ [ destr(1), id(2), id(3), destr(4), destr(5) ],
+
+ [ destr(1), id(2), destr(3) ],
+ [ destr(1), id(2), destr(3), id(4) ],
+ [ destr(1), id(2), destr(3), id(4), id(5) ],
+ [ destr(1), id(2), destr(3), id(4), destr(5) ],
+ [ destr(1), id(2), destr(3), destr(4) ],
+ [ destr(1), id(2), destr(3), destr(4), id(5) ],
+ [ destr(1), id(2), destr(3), destr(4), destr(5) ],
+
+ [ id(1), destr(2) ],
+
+ [ id(1), destr(2), id(3) ],
+ [ id(1), destr(2), id(3), id(4) ],
+ [ id(1), destr(2), id(3), id(4), id(5) ],
+ [ id(1), destr(2), id(3), id(4), destr(5) ],
+ [ id(1), destr(2), id(3), destr(4) ],
+ [ id(1), destr(2), id(3), destr(4), id(5) ],
+ [ id(1), destr(2), id(3), destr(4), destr(5) ],
+
+ [ id(1), destr(2), destr(3) ],
+ [ id(1), destr(2), destr(3), id(4) ],
+ [ id(1), destr(2), destr(3), id(4), id(5) ],
+ [ id(1), destr(2), destr(3), id(4), destr(5) ],
+ [ id(1), destr(2), destr(3), destr(4) ],
+ [ id(1), destr(2), destr(3), destr(4), id(5) ],
+ [ id(1), destr(2), destr(3), destr(4), destr(5) ]
+ ];
+}
+
+function runtest(main) {
+ try {
+ main();
+ if (typeof reportCompare === 'function')
+ reportCompare(true, true);
+ } catch (exc) {
+ print(exc.stack);
+ throw exc;
+ }
+}
diff --git a/js/src/tests/non262/reflect-parse/stackOverflow.js b/js/src/tests/non262/reflect-parse/stackOverflow.js
new file mode 100644
index 0000000000..5fadbde4d8
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/stackOverflow.js
@@ -0,0 +1,8 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// Bug 632024: no crashing on stack overflow
+try {
+ Reflect.parse(Array(3000).join("x + y - ") + "z")
+} catch (e) { }
+
+if (typeof reportCompare === 'function')
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/reflect-parse/statements.js b/js/src/tests/non262/reflect-parse/statements.js
new file mode 100644
index 0000000000..36a8b3ecea
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/statements.js
@@ -0,0 +1,88 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// statements
+
+assertStmt("throw 42", throwStmt(lit(42)));
+assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null)));
+assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null)));
+assertStmt("for (var x; y; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), ident("z"), breakStmt(null)));
+assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), ident("z"), breakStmt(null)));
+assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null)));
+assertStmt("for (var x; ; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), null, ident("z"), breakStmt(null)));
+assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), null, ident("z"), breakStmt(null)));
+assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null)));
+assertStmt("for (var x; y; ) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), null, breakStmt(null)));
+assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), null, breakStmt(null)));
+assertStmt("for (var x in y) break", forInStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), breakStmt(null)));
+assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null)));
+assertStmt("{ }", blockStmt([]));
+assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]));
+assertStmt(";", emptyStmt);
+assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null));
+assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true))));
+assertStmt("if (foo) { throw 1; throw 2; throw 3; }",
+ ifStmt(ident("foo"),
+ blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
+ null));
+assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;",
+ ifStmt(ident("foo"),
+ blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
+ exprStmt(lit(true))));
+
+
+assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo")))));
+assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo")))));
+assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([])));
+assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))])));
+assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([])));
+assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))])));
+assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo")));
+assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo")));
+assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }",
+ switchStmt(ident("foo"),
+ [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
+ caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
+ defaultClause([ exprStmt(lit(3)) ]) ]));
+assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }",
+ switchStmt(ident("foo"),
+ [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
+ caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
+ defaultClause([ exprStmt(lit(3)) ]),
+ caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
+assertStmt("try { } catch (e) { }",
+ tryStmt(blockStmt([]),
+ catchClause(ident("e"), blockStmt([])),
+ null));
+assertStmt("try { } catch (e) { } finally { }",
+ tryStmt(blockStmt([]),
+ catchClause(ident("e"), blockStmt([])),
+ blockStmt([])));
+assertStmt("try { } finally { }",
+ tryStmt(blockStmt([]),
+ null,
+ blockStmt([])));
+assertStmt("try { } catch { }",
+ tryStmt(blockStmt([]),
+ catchClause(null, blockStmt([])),
+ null));
+assertStmt("try { } catch { } finally { }",
+ tryStmt(blockStmt([]),
+ catchClause(null, blockStmt([])),
+ blockStmt([])));
+
+
+// Bug 632028: yield outside of a function should throw
+(function() {
+ var threw = false;
+ try {
+ Reflect.parse("yield 0");
+ } catch (expected) {
+ threw = true;
+ }
+ assertEq(threw, true);
+})();
+
+}
+
+runtest(test);
diff --git a/js/src/tests/non262/reflect-parse/templateStrings.js b/js/src/tests/non262/reflect-parse/templateStrings.js
new file mode 100644
index 0000000000..d6c424c234
--- /dev/null
+++ b/js/src/tests/non262/reflect-parse/templateStrings.js
@@ -0,0 +1,42 @@
+// |reftest| skip-if(!xulRuntime.shell)
+function test() {
+
+// template strings
+assertStringExpr("`hey there`", literal("hey there"));
+assertStringExpr("`hey\nthere`", literal("hey\nthere"));
+assertExpr("`hey${\"there\"}`", templateLit([lit("hey"), lit("there"), lit("")]));
+assertExpr("`hey${\"there\"}mine`", templateLit([lit("hey"), lit("there"), lit("mine")]));
+assertExpr("`hey${a == 5}mine`", templateLit([lit("hey"), binExpr("==", ident("a"), lit(5)), lit("mine")]));
+assertExpr("func`hey\\x`", taggedTemplate(ident("func"), template(["hey\\x"], [void 0])));
+assertExpr("func`hey${4}\\x`", taggedTemplate(ident("func"), template(["hey","\\x"], ["hey",void 0], lit(4))));
+assertExpr("`hey${`there${\"how\"}`}mine`", templateLit([lit("hey"),
+ templateLit([lit("there"), lit("how"), lit("")]), lit("mine")]));
+assertExpr("func`hey`", taggedTemplate(ident("func"), template(["hey"], ["hey"])));
+assertExpr("func`hey${\"4\"}there`", taggedTemplate(ident("func"),
+ template(["hey", "there"], ["hey", "there"], lit("4"))));
+assertExpr("func`hey${\"4\"}there${5}`", taggedTemplate(ident("func"),
+ template(["hey", "there", ""], ["hey", "there", ""],
+ lit("4"), lit(5))));
+assertExpr("func`hey\r\n`", taggedTemplate(ident("func"), template(["hey\n"], ["hey\n"])));
+assertExpr("func`hey${4}``${5}there``mine`",
+ taggedTemplate(taggedTemplate(taggedTemplate(
+ ident("func"), template(["hey", ""], ["hey", ""], lit(4))),
+ template(["", "there"], ["", "there"], lit(5))),
+ template(["mine"], ["mine"])));
+
+// multi-line template string - line numbers
+var node = Reflect.parse("`\n\n ${2}\n\n\n`");
+Pattern({loc:{start:{line:1, column:1}, end:{line:6, column:2}, source:null}, type:"Program",
+body:[{loc:{start:{line:1, column:1}, end:{line:6, column:2}, source:null},
+type:"ExpressionStatement", expression:{loc:{start:{line:1, column:1}, end:{line:6, column:2},
+source:null}, type:"TemplateLiteral", elements:[{loc:{start:{line:1, column:1}, end:{line:3,
+column:6}, source:null}, type:"Literal", value:"\n\n "}, {loc:{start:{line:3, column:6},
+end:{line:3, column:7}, source:null}, type:"Literal", value:2}, {loc:{start:{line:3, column:7},
+end:{line:6, column:2}, source:null}, type:"Literal", value:"\n\n\n"}]}}]}).match(node);
+
+
+assertStringExpr("\"hey there\"", literal("hey there"));
+
+}
+
+runtest(test);