michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: var BUGNUMBER = 634472; michael@0: var summary = 'contextual restrictions for yield and arguments'; michael@0: var actual = ''; michael@0: var expect = ''; michael@0: michael@0: michael@0: function error(str) { michael@0: let base; michael@0: try { michael@0: // the following line must not be broken up into multiple lines michael@0: base = (function(){try{eval('throw new Error()')}catch(e){return e.lineNumber}})(); eval(str); michael@0: return null; michael@0: } catch (e) { michael@0: e.lineNumber = e.lineNumber - base + 1; michael@0: return e; michael@0: } michael@0: } michael@0: michael@0: const JSMSG_GENEXP_YIELD = error("(function(){((yield) for (x in []))})").message; michael@0: const JSMSG_TOP_YIELD = error("yield").message; michael@0: const JSMSG_YIELD_PAREN = error("(function(){yield, 1})").message; michael@0: const JSMSG_YIELD_FOR = error("(function(){yield for})").message; michael@0: const JSMSG_BAD_GENERATOR_SYNTAX = error("(1, x for (x in []))").message; michael@0: michael@0: const cases = [ michael@0: // yield expressions michael@0: { expr: "yield", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "simple yield" }, michael@0: { expr: "yield 1", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg" }, michael@0: { expr: "1, yield", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "simple yield at end of list" }, michael@0: { expr: "1, yield 2", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg at end of list" }, michael@0: { expr: "yield, 1", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "simple yield in list" }, michael@0: { expr: "yield 1, 2", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "yield w/ arg in list" }, michael@0: { expr: "(yield)", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "simple yield, parenthesized" }, michael@0: { expr: "(yield 1)", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg, parenthesized" }, michael@0: { expr: "(1, yield)", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "simple yield at end of list, parenthesized" }, michael@0: { expr: "(1, yield 2)", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg at end of list, parenthesized" }, michael@0: { expr: "(yield, 1)", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "simple yield in list, parenthesized" }, michael@0: { expr: "(yield 1, 2)", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "yield w/ arg in list, parenthesized" }, michael@0: michael@0: // deeply nested yield expressions michael@0: { expr: "((((yield))))", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "deeply nested yield" }, michael@0: { expr: "((((yield 1))))", top: JSMSG_TOP_YIELD, fun: null, gen: JSMSG_GENEXP_YIELD, desc: "deeply nested yield w/ arg" }, michael@0: michael@0: // arguments michael@0: { expr: "arguments", top: null, fun: null, gen: null, desc: "arguments in list" }, michael@0: { expr: "1, arguments", top: null, fun: null, gen: null, desc: "arguments in list" }, michael@0: michael@0: // yield in generator expressions michael@0: { expr: "(yield for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_FOR, gen: JSMSG_YIELD_FOR, desc: "simple yield in genexp" }, michael@0: { expr: "(yield 1 for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg in genexp" }, michael@0: { expr: "(yield, 1 for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "simple yield in list in genexp" }, michael@0: { expr: "(yield 1, 2 for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "yield w/ arg in list in genexp" }, michael@0: { expr: "(1, yield for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_FOR, gen: JSMSG_YIELD_FOR, desc: "simple yield at end of list in genexp" }, michael@0: { expr: "(1, yield 2 for (x in []))", top: JSMSG_TOP_YIELD, fun: { simple: JSMSG_GENEXP_YIELD, call: JSMSG_GENEXP_YIELD }, michael@0: gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg at end of list in genexp" }, michael@0: { expr: "((yield) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "simple yield, parenthesized in genexp" }, michael@0: { expr: "((yield 1) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg, parenthesized in genexp" }, michael@0: { expr: "(1, (yield) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "simple yield, parenthesized in list in genexp" }, michael@0: { expr: "(1, (yield 2) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg, parenthesized in list in genexp" }, michael@0: { expr: "((1, yield) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "simple yield at end of list, parenthesized in genexp" }, michael@0: { expr: "((1, yield 2) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg at end of list, parenthesized in genexp" }, michael@0: { expr: "(1, (2, yield) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "simple yield at end of list, parenthesized in list in genexp" }, michael@0: { expr: "(1, (2, yield 3) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "yield w/ arg at end of list, parenthesized in list in genexp" }, michael@0: { expr: "((yield, 1) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "simple yield in list, parenthesized in genexp" }, michael@0: { expr: "((yield 1, 2) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "yield w/ arg in list, parenthesized in genexp" }, michael@0: { expr: "(1, (yield, 2) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "simple yield in list, parenthesized in list in genexp" }, michael@0: { expr: "(1, (yield 2, 3) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_YIELD_PAREN, gen: JSMSG_YIELD_PAREN, desc: "yield w/ arg in list, parenthesized in list in genexp" }, michael@0: michael@0: // deeply nested yield in generator expressions michael@0: { expr: "((((1, yield 2))) for (x in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "deeply nested yield in genexp" }, michael@0: { expr: "((((1, yield 2)) for (x in [])) for (y in []))", top: JSMSG_TOP_YIELD, fun: JSMSG_GENEXP_YIELD, gen: JSMSG_GENEXP_YIELD, desc: "deeply nested yield in multiple genexps" }, michael@0: michael@0: // arguments in generator expressions michael@0: { expr: "(arguments for (x in []))", top: null, fun: null, gen: null, desc: "simple arguments in genexp" }, michael@0: { expr: "(1, arguments for (x in []))", top: JSMSG_BAD_GENERATOR_SYNTAX, fun: JSMSG_BAD_GENERATOR_SYNTAX, gen: JSMSG_BAD_GENERATOR_SYNTAX, desc: "arguments in list in genexp" }, michael@0: { expr: "((arguments) for (x in []))", top: null, fun: null, gen: null, desc: "arguments, parenthesized in genexp" }, michael@0: { expr: "(1, (arguments) for (x in []))", top: JSMSG_BAD_GENERATOR_SYNTAX, fun: JSMSG_BAD_GENERATOR_SYNTAX, gen: JSMSG_BAD_GENERATOR_SYNTAX, desc: "arguments, parenthesized in list in genexp" }, michael@0: { expr: "((1, arguments) for (x in []))", top: null, fun: null, gen: null, desc: "arguments in list, parenthesized in genexp" }, michael@0: { expr: "(1, (2, arguments) for (x in []))", top: JSMSG_BAD_GENERATOR_SYNTAX, fun: JSMSG_BAD_GENERATOR_SYNTAX, gen: JSMSG_BAD_GENERATOR_SYNTAX, desc: "arguments in list, parenthesized in list in genexp" }, michael@0: michael@0: // deeply nested arguments in generator expressions michael@0: { expr: "((((1, arguments))) for (x in []))", top: null, fun: null, gen: null, desc: "deeply nested arguments in genexp" }, michael@0: { expr: "((((1, arguments)) for (x in [])) for (y in []))", top: null, fun: null, gen: null, desc: "deeply nested arguments in multiple genexps" }, michael@0: michael@0: // legal yield/arguments in nested function michael@0: { expr: "((function() { yield }) for (x in []))", top: null, fun: null, gen: null, desc: "legal yield in nested function" }, michael@0: { expr: "((function() { arguments }) for (x in []))", top: null, fun: null, gen: null, desc: "legal arguments in nested function" }, michael@0: { expr: "((function() arguments) for (x in []))", top: null, fun: null, gen: null, desc: "legal arguments in nested expression-closure" } michael@0: ]; michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: test(); michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: function splitKeyword(str) { michael@0: return str. michael@0: replace(/yield for/, '\nyield for\n'). michael@0: replace(/yield ([0-9])/, '\nyield $1\n'). michael@0: replace(/yield([^ ]|$)/, '\nyield\n$1'). michael@0: replace(/arguments/, '\narguments\n'); michael@0: } michael@0: michael@0: function expectError1(err, ctx, msg) { michael@0: reportCompare('object', typeof err, 'exn for: ' + msg); michael@0: reportCompare(ctx, err.message, 'exn message for: ' + msg); michael@0: if (ctx !== JSMSG_BAD_GENERATOR_SYNTAX) michael@0: reportCompare(2, err.lineNumber, 'exn token for: ' + msg); michael@0: } michael@0: michael@0: function expectError(expr, call, wrapCtx, expect, msg) { michael@0: let exps = (typeof expect === "string") michael@0: ? { simple: expect, call: expect } michael@0: : expect; michael@0: expectError1(error(wrapCtx(expr)), exps.simple, msg); michael@0: if (call) michael@0: expectError1(error(wrapCtx(call)), exps.call, 'call argument in ' + msg); michael@0: } michael@0: michael@0: function expectSuccess(err, msg) { michael@0: reportCompare(null, err, 'parse: ' + msg); michael@0: } michael@0: michael@0: function atTop(str) { return str } michael@0: function inFun(str) { return '(function(){' + str + '})' } michael@0: function inGen(str) { return '(y for (y in ' + str + '))' } michael@0: michael@0: function test() michael@0: { michael@0: enterFunc ('test'); michael@0: printBugNumber(BUGNUMBER); michael@0: printStatus (summary); michael@0: michael@0: for (let i = 0, len = cases.length; i < len; i++) { michael@0: let {expr, top, fun, gen, desc} = cases[i]; michael@0: michael@0: let call = (expr[0] === "(") ? ("print" + expr) : null; michael@0: michael@0: expr = splitKeyword(expr); michael@0: if (call) michael@0: call = splitKeyword(call); michael@0: michael@0: if (top) michael@0: expectError(expr, call, atTop, top, 'top-level context, ' + desc); michael@0: else michael@0: expectSuccess(error(expr), 'top-level context, ' + desc); michael@0: michael@0: if (fun) michael@0: expectError(expr, call, inFun, fun, 'function context, ' + desc); michael@0: else michael@0: expectSuccess(error(inFun(expr)), 'function context, ' + desc); michael@0: michael@0: if (gen) michael@0: expectError(expr, call, inGen, gen, 'genexp context, ' + desc); michael@0: else michael@0: expectSuccess(error(inGen(expr)), 'genexp context, ' + desc); michael@0: } michael@0: michael@0: exitFunc ('test'); michael@0: }