зеркало из https://github.com/mozilla/pjs.git
JavaScript Tests - regression tests for bug 380237, by Jesse Ruderman, Brendan Eich
This commit is contained in:
Родитель
0240bdbc18
Коммит
0d826a3625
|
@ -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');
|
||||
}
|
|
@ -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');
|
||||
}
|
|
@ -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');
|
||||
}
|
|
@ -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("<x a={xx}/>");
|
||||
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');
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
gTestsubsuite = 'genexps';
|
Загрузка…
Ссылка в новой задаче