From 6a0bcf6ae5072985b18ccba3a30184b00cb9c1d2 Mon Sep 17 00:00:00 2001 From: "bclary@bclary.com" Date: Sat, 26 May 2007 09:10:20 -0700 Subject: [PATCH] JavaScript Tests - regression tests for bug 380237, by Jesse Ruderman, Brendan Eich --- js/tests/js1_8/genexps/browser.js | 0 js/tests/js1_8/genexps/regress-380237-01.js | 231 ++++++++++++++ js/tests/js1_8/genexps/regress-380237-02.js | 63 ++++ js/tests/js1_8/genexps/regress-380237-03.js | 190 ++++++++++++ js/tests/js1_8/genexps/regress-380237-04.js | 327 ++++++++++++++++++++ js/tests/js1_8/genexps/shell.js | 1 + 6 files changed, 812 insertions(+) create mode 100644 js/tests/js1_8/genexps/browser.js create mode 100755 js/tests/js1_8/genexps/regress-380237-01.js create mode 100755 js/tests/js1_8/genexps/regress-380237-02.js create mode 100755 js/tests/js1_8/genexps/regress-380237-03.js create mode 100644 js/tests/js1_8/genexps/regress-380237-04.js create mode 100644 js/tests/js1_8/genexps/shell.js diff --git a/js/tests/js1_8/genexps/browser.js b/js/tests/js1_8/genexps/browser.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/js/tests/js1_8/genexps/regress-380237-01.js b/js/tests/js1_8/genexps/regress-380237-01.js new file mode 100755 index 00000000000..9b9d7bce28e --- /dev/null +++ b/js/tests/js1_8/genexps/regress-380237-01.js @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Brendan + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gTestfile = 'regress-380237-01.js'; + +//----------------------------------------------------------------------------- +var BUGNUMBER = 380237; +var summary = 'Generator expressions - sudoku'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + +// XXX should be standard (and named clone, after Java?) +Object.prototype.copy = function () { + let o = {} + for (let i in this) + o[i] = this[i] + return o +} + +// Make arrays and strings act more like Python lists by iterating their values, not their keys. +Array.prototype.__iterator__ = String.prototype.__iterator__ = function () { + for (let i = 0; i < this.length; i++) + yield this[i] +} + +// Containment testing for arrays and strings that should be coherent with their __iterator__. +Array.prototype.contains = String.prototype.contains = function (e) { + return this.indexOf(e) != -1 +} + +Array.prototype.repeat = String.prototype.repeat = function (n) { + let s = this.constructor() + for (let i = 0; i < n; i++) + s = s.concat(this) + return s +} + +String.prototype.center = function (w) { + let n = this.length + if (w <= n) + return this + let m = Math.floor((w - n) / 2) + return ' '.repeat(m) + this + ' '.repeat(w - n - m) +} + +Array.prototype.toString = Array.prototype.toSource +Object.prototype.toString = Object.prototype.toSource + +// XXX thought spurred by the next two functions: array extras should default to identity function + +function all(seq) { + for (let e in seq) + if (!e) + return false + return true +} + +function some(seq) { + for (let e in seq) + if (e) + return e + return false +} + +function cross(A, B) { + return [a+b for (a in A) for (b in B)] +} + +function dict(A) { + let d = {} + for (let e in A) + d[e[0]] = e[1] + return d +} + +function set(A) { + let s = [] + for (let e in A) + if (!s.contains(e)) + s.push(e) + return s +} + +function zip(A, B) { + let z = [] + let n = Math.min(A.length, B.length) + for (let i = 0; i < n; i++) + z.push([A[i], B[i]]) + return z +} + +rows = 'ABCDEFGHI' +cols = '123456789' +digits = '123456789' +squares = cross(rows, cols) +unitlist = [cross(rows, c) for (c in cols)] + .concat([cross(r, cols) for (r in rows)]) + .concat([cross(rs, cs) for (rs in ['ABC','DEF','GHI']) for (cs in ['123','456','789'])]) +units = dict([s, [u for (u in unitlist) if (u.contains(s))]] + for (s in squares)) +peers = dict([s, set([s2 for (u in units[s]) for (s2 in u) if (s2 != s)])] + for (s in squares)) + +// Given a string of 81 digits (or . or 0 or -), return a dict of {cell:values}. +function parse_grid(grid) { + grid = [c for (c in grid) if ('0.-123456789'.contains(c))] + let values = dict([s, digits] for (s in squares)) + + // XXX should destructure [s, d] but JS1.7 is broken + for (let sd in zip(squares, grid)) + if (digits.contains(sd[1]) && !assign(values, sd[0], sd[1])) + return false + return values +} + +// Eliminate all the other values (except d) from values[s] and propagate. +function assign(values, s, d) { + if (all(eliminate(values, s, d2) for (d2 in values[s]) if (d2 != d))) + return values + return false +} + +// Eliminate d from values[s]; propagate when values or places <= 2. +function eliminate(values, s, d) { + if (!values[s].contains(d)) + return values // Already eliminated + values[s] = values[s].replace(d, '') + if (values[s].length == 0) + return false // Contradiction: removed last value + if (values[s].length == 1) { + // If there is only one value (d2) left in square, remove it from peers + let d2 = values[s][0] + if (!all(eliminate(values, s2, d2) for (s2 in peers[s]))) + return false + } + // Now check the places where d appears in the units of s + for (let u in units[s]) { + let dplaces = [s for (s in u) if (values[s].contains(d))] + if (dplaces.length == 0) + return false + if (dplaces.length == 1) + // d can only be in one place in unit; assign it there + if (!assign(values, dplaces[0], d)) + return false + } + return values +} + +// Used for debugging. +function print_board(values) { + let width = 1 + Math.max.apply(Math, [values[s].length for (s in squares)]) + let line = '\n' + ['-'.repeat(width*3)].repeat(3).join('+') + for (let r in rows) + print([values[r+c].center(width) + ('36'.contains(c) && '|' || '') + for (c in cols)].join('') + ('CF'.contains(r) && line || '')) + print() +} + +easy = "..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3.." + +print_board(parse_grid(easy)) + +// Using depth-first search and constraint propagation, try all possible values. +function search(values) { + if (!values) + return false // Failed earlier + if (all(values[s].length == 1 for (s in squares))) + return values // Solved! + + // Choose the unfilled square s with the fewest possibilities + // XXX Math.min etc. should work with generator expressions and other iterators + // XXX Math.min etc. should work on arrays (lists or tuples in Python) as well as numbers + let a = [values[s].length + s for (s in squares) if (values[s].length > 1)].sort() + let s = a[0].slice(-2) + + return some(search(assign(values.copy(), s, d)) for (d in values[s])) +} + +hard = '4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......' + +print_board(search(parse_grid(hard))) + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/tests/js1_8/genexps/regress-380237-02.js b/js/tests/js1_8/genexps/regress-380237-02.js new file mode 100755 index 00000000000..7fc460a4efe --- /dev/null +++ b/js/tests/js1_8/genexps/regress-380237-02.js @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gTestfile = 'regress-380237-02.js'; + +//----------------------------------------------------------------------------- +var BUGNUMBER = 380237; +var summary = 'Decompilation of generator expressions'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + var f = function() { g = (d for (d in [0])); g.next(); }; + expect = 'function() { g = (d for (d in [0])); g.next(); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/tests/js1_8/genexps/regress-380237-03.js b/js/tests/js1_8/genexps/regress-380237-03.js new file mode 100755 index 00000000000..154cf17f52b --- /dev/null +++ b/js/tests/js1_8/genexps/regress-380237-03.js @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gTestfile = 'regress-380237-02.js'; + +//----------------------------------------------------------------------------- +var BUGNUMBER = 380237; +var summary = 'Decompilation of generator expressions'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +expect = 'No Error'; +actual = ''; +try +{ + var g = ((yield i) for (i in [1,2,3])); + actual = 'No Error'; +} +catch(ex) +{ + actual = ex + ''; +} +reportCompare(expect, actual, summary + ': top level'); + + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + var f = (function() { g = (d for (d in [0]) for (e in [1])); }); + expect = 'function() { g = (d for (d in [0]) for (e in [1])); }'; + actual = f + ''; + compareSource(expect, actual, summary + ': see bug 380506'); + + f = function() { return (1 for (i in [])) }; + expect = 'function() { return (1 for (i in [])); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = function() { with((x for (x in []))) { } }; + expect = 'function() { with(x for (x in [])) { } }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = (function() { (1 for (w in []) if (0)) }); + expect = 'function() { (1 for (w in []) if (0)); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = (function() { (1 for (w in []) if (1)) }); + expect = 'function() { (1 for (w in []) if (1)); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = (function() { (x for ([{}, {}] in [])); }); + expect = 'function() { (x for ([{}, {}] in [])); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + expect = 'SyntaxError: invalid assignment left-hand side'; + actual = ''; + try + { + eval('(function() { (x for each (x in [])) = 3; })'); + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': Do not Assert: *pc == JSOP_CALL'); + + f = (function() { (x*x for (x in a)); }); + expect = 'function() { (x*x for (x in a)); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = (function () { (1 for (y in (yield 3))); }); + expect = 'function () { (1 for (y in yield 3)); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + expect = 'SyntaxError: invalid delete operand'; + try + { + eval('(function () { delete (x for (x in [])); })'); + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': Do not Assert: *pc == JSOP_CALL'); + + f = (function() { ([yield] for (x in [])); }); + expect = 'function() { ([(yield)] for (x in [])); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = function() { if(1, (x for (x in []))) { } }; + expect = 'function() { if(1, (x for (x in []))) { } }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = function () {return(i*j for each (i in [1,2,3,4]) + for each (j in [5,6,7,8]))}; + expect = 'function () {return(i*j for each (i in [1,2,3,4]) ' + + 'for each (j in [5,6,7,8]));}'; + actual = f + ''; + compareSource(expect, actual, summary); + + expect = 'No Error'; + actual = ''; + try + { + var g = ((yield i) for (i in [1,2,3])); + actual = 'No Error'; + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': nested'); + + f = function() { try { } catch(x if (1 for (x in []))) { } finally { } }; + expect = 'function() { try {} catch(x if (1 for (x in []))) {} finally {} }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = eval(uneval(f)); + expect = 'function() { try {} catch(x if (1 for (x in []))) {} finally {} }'; + actual = f + ''; + compareSource(expect, actual, summary + ': eval(uneval())'); + + f = function() { if (1, (x for (x in []))) { } }; + expect = 'function() { if (1, (x for (x in []))) { } }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = function() { ((a, b) for (x in [])) }; + expect = 'function() { ((a, b) for (x in [])); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + f = (function() { ({x setter: (function () {}).x }) }); + expect = 'function() { ({x setter: function () {}.x }); }'; + actual = f + ''; + compareSource(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/tests/js1_8/genexps/regress-380237-04.js b/js/tests/js1_8/genexps/regress-380237-04.js new file mode 100644 index 00000000000..6c9994e2e73 --- /dev/null +++ b/js/tests/js1_8/genexps/regress-380237-04.js @@ -0,0 +1,327 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gTestfile = 'regress-380237-04.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 380237; +var summary = 'Generator expressions parenthesization test'; +var actual = ''; +var expect = ''; + + +/* + +Given that parentheization seems so fragile *and* the rules for where +genexps are allowed keep changing, I thought it would be good to have +a way to test that: + +1) unparenthesized genexps are allowed in some places and the +decompilation is sane and not over-parenthesized + +2) unparenthesized genexps are disallowed in many places and when +there are parens, the decompilation is sane and not over-parenthesized + +*/ + +// |genexp| must have the exact same whitespace the decompiler uses +genexp = "x * x for (x in [])"; +genexpParened = "(" + genexp + ")"; +genexpParenedTwice = "(" + genexpParened + ")"; + +// Warning: be careful not to put [] around stuff, because that would +// cause it to be treated as an array comprehension instead of a +// generator expression! + +// Statements +doesNotNeedParens("if (xx) { }"); +needParens("if (1, xx) { }"); +needParens("if (xx, 1) { }"); +doesNotNeedParens("do { } while (xx);"); +doesNotNeedParens("while (xx) { }"); +doesNotNeedParens("switch (xx) { }"); +doesNotNeedParens("with (xx) { }"); +needParens("switch (x) { case xx: }"); +needParens("return xx;"); +needParens("yield xx;"); +needParens("for (xx;;) { }"); +needParens("for (;xx;) { }"); +needParens("for (;;xx) { }"); +needParens("for (i in xx) { }"); +needParens("throw xx"); +needParens("try { } catch (e if xx) { }"); +needParens("let (x=3) xx"); +needParens("let (x=xx) 3"); + +// Function calls +doesNotNeedParens("f(xx);"); +needParens("f(xx, 1);"); +needParens("f(1, xx);"); +doesNotNeedParens("/x/(xx);"); +needParens("/x/(xx, 1);"); +needParens("/x/(1, xx);"); + +// eval is special and often confuses the decompiler. +doesNotNeedParens("eval(xx);"); +needParens("eval(xx, 1);"); +needParens("eval(1, xx);"); + +// Expressions +needParens("xx;"); // ??? +needParens("var g = xx;"); // ??? +needParens("g += xx;"); +needParens("xx();"); +needParens("xx() = 3;"); +needParens("a ? xx : c"); +needParens("xx ? b : c"); +needParens("a ? b : xx"); +needParens("1 ? xx : c"); +needParens("0 ? b : xx"); +needParens("1 + xx"); +needParens("xx + 1"); +needParens("1, xx"); +doesNotNeedParens("+(xx)"); +doesNotNeedParens("!(xx)"); +needParens("xx, 1"); +needParens("[1, xx]"); +needParens("[xx, 1]"); +needParens("[#1=xx,3]"); +needParens("[#1=xx,#1#]"); +needParens("xx.p"); +needParens("xx.@p"); +needParens("typeof xx;"); +needParens("void xx;"); +needParens("({ a: xx })"); +needParens("({ a: 1, b: xx })"); +needParens("({ a: xx, b: 1 })"); +needParens("({ a getter: xx })"); +needParens(""); +doesNotNeedParens("new (xx);"); +doesNotNeedParens("new a(xx);"); + + +// Generator expressions cannot be used as LHS, even though they're syntactic +// sugar for something that looks a lot like an "lvalue return": (f() = 3). + +rejectLHS("++ (xx);"); +rejectLHS("delete xx;"); +rejectLHS("delete (xx);"); +rejectLHS("for (xx in []) { }"); +rejectLHS("for ((xx) in []) { }"); +rejectLHS("try { } catch(xx) { }"); +rejectLHS("try { } catch([(xx)]) { }"); +rejectLHS("xx += 3;"); +rejectLHS("(xx) += 3;"); +rejectLHS("xx = 3;"); + +// Assignment +rejectLHS(" (xx) = 3;"); +rejectLHS("var (xx) = 3;"); +rejectLHS("const (xx) = 3;"); +rejectLHS("let (xx) = 3;"); + +// Destructuring assignment +rejectLHS(" [(xx)] = 3;"); +rejectLHS("var [(xx)] = 3;"); +rejectLHS("const [(xx)] = 3;"); +rejectLHS("let [(xx)] = 3;"); + +// Group assignment (Spidermonkey optimization for certain +// destructuring assignments) +rejectLHS(" [(xx)] = [3];"); +rejectLHS("var [(xx)] = [3];"); +rejectLHS("const [(xx)] = [3];"); +rejectLHS("let [(xx)] = [3];"); + +// Destructuring & group assignment for array comprehensions, just for kicks. +rejectLHS(" [xx] = [3];"); +rejectLHS("var [xx] = [3];"); +rejectLHS("const [xx] = [3];"); +rejectLHS("let [xx] = 3;"); +rejectLHS(" [xx] = 3;"); +rejectLHS("var [xx] = 3;"); +rejectLHS("const [xx] = 3;"); +rejectLHS("let [xx] = 3;"); + +// This is crazy, ambiguous, and/or buggy. +// See https://bugzilla.mozilla.org/show_bug.cgi?id=380237#c23 et seq. +//doesNotNeedParens("(yield xx);"); + +print("Done!"); + +function doesNotNeedParens(pat) +{ + print("Testing " + pat); + + var f, ft; + sanityCheck(pat); + + expect = 'No Error'; + actual = ''; + ft = pat.replace(/xx/, genexp); + try { + f = new Function(ft); + actual = 'No Error'; + } catch(e) { + print("Unparenthesized genexp SHOULD have been accepted here!"); + actual = e + ''; + } + reportCompare(expect, actual, summary + ': doesNotNeedParens ' + pat); + + roundTripTest(f); + + // Make sure the decompilation is not over-parenthesized. + var uf = "" + f; + if (pat.indexOf("(xx)") != -1) + overParenTest(f); + // else + // print("Skipping the over-parenthesization test, because I don't know how to test for over-parenthesization when the pattern doesn't have parens snugly around it.") +} + +function needParens(pat) +{ + print("Testing " + pat); + + var f, ft; + sanityCheck(pat); + + expect = 'SyntaxError'; + actual = ''; + ft = pat.replace(/xx/, genexp); + try { + f = new Function(ft); + print("Unparenthesized genexp should NOT have been accepted here!"); + } catch(e) { + /* expected to throw */ + actual = e.name; + } + reportCompare(expect, actual, summary + ': needParens ' + pat); + + expect = 'No Error'; + actual = ''; + ft = pat.replace(/xx/, genexpParened); + try { + f = new Function(ft); + actual = 'No Error'; + } catch(e) { + print("Yikes!"); + actual = e + ''; + } + reportCompare(expect, actual, summary + ': needParens ' + ft); + + roundTripTest(f); + overParenTest(f); +} + +function rejectLHS(pat) +{ + print("Testing " + pat); + + // sanityCheck(pat); // because 'z' should be accepted as an LHS or binding + + var ft; + + expect = 'SyntaxError'; + actual = ''; + ft = pat.replace(/xx/, genexp) + try { + new Function(ft); + print("That should have been a syntax error!"); + actual = 'No Error'; + } catch(e) { + actual = e.name; + } + reportCompare(expect, actual, summary + ': rejectLHS'); +} + + +function overParenTest(f) +{ + var uf = "" + f; + + reportCompare(false, uf.indexOf(genexpParened) == -1, summary + + ': overParenTest genexp snugly in parentheses: ' + uf); + + if (uf.indexOf(genexpParened) != -1) { + reportCompare(true, uf.indexOf(genexpParenedTwice) == -1, summary + + ': overParensTest decompilation should not be over-parenthesized: ' + uf); + } +} + +function sanityCheck(pat) +{ + expect = ''; + actual = ''; + + if (pat.indexOf("xx") == -1) + { + actual += "No 'xx' in this pattern? "; + } + + var f, ft; + ft = pat.replace(/xx/, "z"); + try { + f = new Function(ft); + } catch(e) { + actual += "Yowzers! Probably a bogus test!"; + } + reportCompare(expect, actual, summary + ': sanityCheck ' + pat); +} + +function roundTripTest(f) +{ + // Decompile + var uf = "" + f; + + // Recompile + expect = 'No Error'; + actual = ''; + var euf; + try { + euf = eval("(" + uf + ")"); + actual = 'No Error'; + reportCompare(expect, actual, summary + ': roundTripTest: ' + uf); + } catch(e) { + actual = e + ''; + reportCompare(expect, actual, summary + ': roundTripTest: ' + uf); + return; + } + + // Decompile again and make sure the decompilations match exactly. + expect = uf; + actual = "" + euf; + reportCompare(expect, actual, summary + ': roundTripTest no round-trip change'); +} diff --git a/js/tests/js1_8/genexps/shell.js b/js/tests/js1_8/genexps/shell.js new file mode 100644 index 00000000000..e5b8b0831e7 --- /dev/null +++ b/js/tests/js1_8/genexps/shell.js @@ -0,0 +1 @@ +gTestsubsuite = 'genexps';