зеркало из https://github.com/mozilla/gecko-dev.git
bug 584787, r=pcwalton: Node shouldn't subclass Array
This commit is contained in:
Родитель
e2941e77c7
Коммит
b3fd89a22a
|
@ -313,8 +313,8 @@ Narcissus.interpreter = (function() {
|
|||
return;
|
||||
|
||||
for (var i = 0, j = ps.length; i < j; i++) {
|
||||
// If the thing we're valuating is already equal to the thing we want
|
||||
// to valuate it to, we have fully saturated (and have a cycle), and
|
||||
// If the thing we're evaluating is already equal to the thing we want
|
||||
// to evaluate it to, we have fully saturated (and have a cycle), and
|
||||
// thus we should break.
|
||||
if (ps[i].v === v)
|
||||
break;
|
||||
|
@ -324,7 +324,7 @@ Narcissus.interpreter = (function() {
|
|||
}
|
||||
|
||||
function execute(n, x) {
|
||||
var a, f, i, j, r, s, t, u, v;
|
||||
var a, c, f, i, j, r, s, t, u, v;
|
||||
|
||||
switch (n.type) {
|
||||
case FUNCTION:
|
||||
|
@ -370,8 +370,9 @@ Narcissus.interpreter = (function() {
|
|||
// FALL THROUGH
|
||||
|
||||
case BLOCK:
|
||||
for (i = 0, j = n.length; i < j; i++)
|
||||
execute(n[i], x);
|
||||
c = n.children;
|
||||
for (i = 0, j = c.length; i < j; i++)
|
||||
execute(c[i], x);
|
||||
break;
|
||||
|
||||
case IF:
|
||||
|
@ -405,7 +406,7 @@ Narcissus.interpreter = (function() {
|
|||
}
|
||||
if (u === s) {
|
||||
for (;;) { // this loop exits switch_loop
|
||||
if (t.statements.length) {
|
||||
if (t.statements.children.length) {
|
||||
try {
|
||||
execute(t.statements, x);
|
||||
} catch (e if e === BREAK && x.target === n) {
|
||||
|
@ -532,11 +533,12 @@ Narcissus.interpreter = (function() {
|
|||
|
||||
case VAR:
|
||||
case CONST:
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
u = n[i].initializer;
|
||||
c = n.children;
|
||||
for (i = 0, j = c.length; i < j; i++) {
|
||||
u = c[i].initializer;
|
||||
if (!u)
|
||||
continue;
|
||||
t = n[i].name;
|
||||
t = c[i].name;
|
||||
for (s = x.scope; s; s = s.parent) {
|
||||
if (hasDirectProperty(s.object, t))
|
||||
break;
|
||||
|
@ -565,16 +567,18 @@ Narcissus.interpreter = (function() {
|
|||
break;
|
||||
|
||||
case COMMA:
|
||||
for (i = 0, j = n.length; i < j; i++)
|
||||
v = getValue(execute(n[i], x));
|
||||
c = n.children;
|
||||
for (i = 0, j = c.length; i < j; i++)
|
||||
v = getValue(execute(c[i], x));
|
||||
break;
|
||||
|
||||
case ASSIGN:
|
||||
r = execute(n[0], x);
|
||||
c = n.children;
|
||||
r = execute(c[0], x);
|
||||
t = n.assignOp;
|
||||
if (t)
|
||||
u = getValue(r);
|
||||
v = getValue(execute(n[1], x));
|
||||
v = getValue(execute(c[1], x));
|
||||
if (t) {
|
||||
switch (t) {
|
||||
case BITWISE_OR: v = u | v; break;
|
||||
|
@ -590,73 +594,89 @@ Narcissus.interpreter = (function() {
|
|||
case MOD: v = u % v; break;
|
||||
}
|
||||
}
|
||||
putValue(r, v, n[0]);
|
||||
putValue(r, v, c[0]);
|
||||
break;
|
||||
|
||||
case HOOK:
|
||||
v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x))
|
||||
: getValue(execute(n[2], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) ? getValue(execute(c[1], x))
|
||||
: getValue(execute(c[2], x));
|
||||
break;
|
||||
|
||||
case OR:
|
||||
v = getValue(execute(n[0], x)) || getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) || getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case AND:
|
||||
v = getValue(execute(n[0], x)) && getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) && getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case BITWISE_OR:
|
||||
v = getValue(execute(n[0], x)) | getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) | getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case BITWISE_XOR:
|
||||
v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) ^ getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case BITWISE_AND:
|
||||
v = getValue(execute(n[0], x)) & getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) & getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case EQ:
|
||||
v = getValue(execute(n[0], x)) == getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) == getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case NE:
|
||||
v = getValue(execute(n[0], x)) != getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) != getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case STRICT_EQ:
|
||||
v = getValue(execute(n[0], x)) === getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) === getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case STRICT_NE:
|
||||
v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) !== getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case LT:
|
||||
v = getValue(execute(n[0], x)) < getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) < getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case LE:
|
||||
v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) <= getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case GE:
|
||||
v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) >= getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case GT:
|
||||
v = getValue(execute(n[0], x)) > getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) > getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case IN:
|
||||
v = getValue(execute(n[0], x)) in getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) in getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case INSTANCEOF:
|
||||
t = getValue(execute(n[0], x));
|
||||
u = getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
t = getValue(execute(c[0], x));
|
||||
u = getValue(execute(c[1], x));
|
||||
if (isObject(u) && typeof u.__hasInstance__ === "function")
|
||||
v = u.__hasInstance__(t);
|
||||
else
|
||||
|
@ -664,111 +684,122 @@ Narcissus.interpreter = (function() {
|
|||
break;
|
||||
|
||||
case LSH:
|
||||
v = getValue(execute(n[0], x)) << getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) << getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case RSH:
|
||||
v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) >> getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case URSH:
|
||||
v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) >>> getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
v = getValue(execute(n[0], x)) + getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) + getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
v = getValue(execute(n[0], x)) - getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) - getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case MUL:
|
||||
v = getValue(execute(n[0], x)) * getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) * getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
v = getValue(execute(n[0], x)) / getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) / getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
v = getValue(execute(n[0], x)) % getValue(execute(n[1], x));
|
||||
c = n.children;
|
||||
v = getValue(execute(c[0], x)) % getValue(execute(c[1], x));
|
||||
break;
|
||||
|
||||
case DELETE:
|
||||
t = execute(n[0], x);
|
||||
t = execute(n.children[0], x);
|
||||
v = !(t instanceof Reference) || delete t.base[t.propertyName];
|
||||
break;
|
||||
|
||||
case VOID:
|
||||
getValue(execute(n[0], x));
|
||||
getValue(execute(n.children[0], x));
|
||||
break;
|
||||
|
||||
case TYPEOF:
|
||||
t = execute(n[0], x);
|
||||
t = execute(n.children[0], x);
|
||||
if (t instanceof Reference)
|
||||
t = t.base ? t.base[t.propertyName] : undefined;
|
||||
v = typeof t;
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
v = !getValue(execute(n[0], x));
|
||||
v = !getValue(execute(n.children[0], x));
|
||||
break;
|
||||
|
||||
case BITWISE_NOT:
|
||||
v = ~getValue(execute(n[0], x));
|
||||
v = ~getValue(execute(n.children[0], x));
|
||||
break;
|
||||
|
||||
case UNARY_PLUS:
|
||||
v = +getValue(execute(n[0], x));
|
||||
v = +getValue(execute(n.children[0], x));
|
||||
break;
|
||||
|
||||
case UNARY_MINUS:
|
||||
v = -getValue(execute(n[0], x));
|
||||
v = -getValue(execute(n.children[0], x));
|
||||
break;
|
||||
|
||||
case INCREMENT:
|
||||
case DECREMENT:
|
||||
t = execute(n[0], x);
|
||||
t = execute(n.children[0], x);
|
||||
u = Number(getValue(t));
|
||||
if (n.postfix)
|
||||
v = u;
|
||||
putValue(t, (n.type === INCREMENT) ? ++u : --u, n[0]);
|
||||
putValue(t, (n.type === INCREMENT) ? ++u : --u, n.children[0]);
|
||||
if (!n.postfix)
|
||||
v = u;
|
||||
break;
|
||||
|
||||
case DOT:
|
||||
r = execute(n[0], x);
|
||||
c = n.children;
|
||||
r = execute(c[0], x);
|
||||
t = getValue(r);
|
||||
u = n[1].value;
|
||||
v = new Reference(toObject(t, r, n[0]), u, n);
|
||||
u = c[1].value;
|
||||
v = new Reference(toObject(t, r, c[0]), u, n);
|
||||
break;
|
||||
|
||||
case INDEX:
|
||||
r = execute(n[0], x);
|
||||
c = n.children;
|
||||
r = execute(c[0], x);
|
||||
t = getValue(r);
|
||||
u = getValue(execute(n[1], x));
|
||||
v = new Reference(toObject(t, r, n[0]), String(u), n);
|
||||
u = getValue(execute(c[1], x));
|
||||
v = new Reference(toObject(t, r, c[0]), String(u), n);
|
||||
break;
|
||||
|
||||
case LIST:
|
||||
// Curse ECMA for specifying that arguments is not an Array object!
|
||||
v = {};
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
u = getValue(execute(n[i], x));
|
||||
c = n.children;
|
||||
for (i = 0, j = c.length; i < j; i++) {
|
||||
u = getValue(execute(c[i], x));
|
||||
definitions.defineProperty(v, i, u, false, false, true);
|
||||
}
|
||||
definitions.defineProperty(v, "length", i, false, false, true);
|
||||
break;
|
||||
|
||||
case CALL:
|
||||
r = execute(n[0], x);
|
||||
a = execute(n[1], x);
|
||||
c = n.children;
|
||||
r = execute(c[0], x);
|
||||
a = execute(c[1], x);
|
||||
f = getValue(r);
|
||||
if (isPrimitive(f) || typeof f.__call__ !== "function") {
|
||||
throw new TypeError(r + " is not callable",
|
||||
n[0].filename, n[0].lineno);
|
||||
throw new TypeError(r + " is not callable", c[0].filename, c[0].lineno);
|
||||
}
|
||||
t = (r instanceof Reference) ? r.base : null;
|
||||
if (t instanceof Activation)
|
||||
|
@ -778,36 +809,39 @@ Narcissus.interpreter = (function() {
|
|||
|
||||
case NEW:
|
||||
case NEW_WITH_ARGS:
|
||||
r = execute(n[0], x);
|
||||
c = n.children;
|
||||
r = execute(c[0], x);
|
||||
f = getValue(r);
|
||||
if (n.type === NEW) {
|
||||
a = {};
|
||||
definitions.defineProperty(a, "length", 0, false, false, true);
|
||||
} else {
|
||||
a = execute(n[1], x);
|
||||
a = execute(c[1], x);
|
||||
}
|
||||
if (isPrimitive(f) || typeof f.__construct__ !== "function") {
|
||||
throw new TypeError(r + " is not a constructor",
|
||||
n[0].filename, n[0].lineno);
|
||||
throw new TypeError(r + " is not a constructor", c[0].filename, c[0].lineno);
|
||||
}
|
||||
v = f.__construct__(a, x);
|
||||
break;
|
||||
|
||||
case ARRAY_INIT:
|
||||
v = [];
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
if (n[i])
|
||||
v[i] = getValue(execute(n[i], x));
|
||||
c = n.children;
|
||||
for (i = 0, j = c.length; i < j; i++) {
|
||||
if (c[i])
|
||||
v[i] = getValue(execute(c[i], x));
|
||||
}
|
||||
v.length = j;
|
||||
break;
|
||||
|
||||
case OBJECT_INIT:
|
||||
v = {};
|
||||
for (i = 0, j = n.length; i < j; i++) {
|
||||
t = n[i];
|
||||
c = n.children;
|
||||
for (i = 0, j = c.length; i < j; i++) {
|
||||
t = c[i];
|
||||
if (t.type === PROPERTY_INIT) {
|
||||
v[t[0].value] = getValue(execute(t[1], x));
|
||||
let c2 = t.children;
|
||||
v[c2[0].value] = getValue(execute(c2[1], x));
|
||||
} else {
|
||||
f = newFunction(t, x);
|
||||
u = (t.type === GETTER) ? '__defineGetter__'
|
||||
|
@ -834,6 +868,9 @@ Narcissus.interpreter = (function() {
|
|||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
if (typeof n.resolve !== "function")
|
||||
throw n;
|
||||
|
||||
// Identifiers with forward pointers that weren't intervened can't be
|
||||
// lvalues, so we safely get the cached value directly.
|
||||
var resolved = n.resolve();
|
||||
|
@ -859,7 +896,7 @@ Narcissus.interpreter = (function() {
|
|||
break;
|
||||
|
||||
case GROUP:
|
||||
v = execute(n[0], x);
|
||||
v = execute(n.children[0], x);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1132,6 +1169,22 @@ Narcissus.interpreter = (function() {
|
|||
print(e.toString());
|
||||
} catch (e) {
|
||||
print("internal Narcissus error");
|
||||
if (typeof e === "object" && e.stack) {
|
||||
let st = String(e.stack).split(/\n/);
|
||||
// beautify stack trace:
|
||||
// - eliminate blank lines
|
||||
// - sanitize confusing trace lines for getters and js -e expressions
|
||||
// - simplify source location reporting
|
||||
// - indent
|
||||
for (let i = 0; i < st.length; i++) {
|
||||
let line = st[i].trim();
|
||||
if (line) {
|
||||
line = line.replace(/^(\(\))?@/, "<unknown>@");
|
||||
line = line.replace(/@(.*\/|\\)?([^\/\\]+:[0-9]+)/, " at $2");
|
||||
print(" in " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -657,15 +657,15 @@ Narcissus.parser = (function() {
|
|||
},
|
||||
|
||||
setCondition: function(n, e) {
|
||||
n[0] = e;
|
||||
n.children[0] = e;
|
||||
},
|
||||
|
||||
setThenPart: function(n, n2) {
|
||||
n[1] = n2;
|
||||
n.children[1] = n2;
|
||||
},
|
||||
|
||||
setElsePart: function(n, n2) {
|
||||
n[2] = n2;
|
||||
n.children[2] = n2;
|
||||
},
|
||||
|
||||
finish: function(n) {
|
||||
|
@ -906,11 +906,12 @@ Narcissus.parser = (function() {
|
|||
// Nodes use a tokenizer for debugging (getSource, filename getter).
|
||||
this.tokenizer = t;
|
||||
|
||||
this.children = [];
|
||||
for (var i = 2; i < arguments.length; i++)
|
||||
this.push(arguments[i]);
|
||||
}
|
||||
|
||||
var Np = Node.prototype = new Array;
|
||||
var Np = Node.prototype = {};
|
||||
Np.constructor = Node;
|
||||
Np.toSource = Object.prototype.toSource;
|
||||
|
||||
|
@ -923,7 +924,7 @@ Narcissus.parser = (function() {
|
|||
if (this.end < kid.end)
|
||||
this.end = kid.end;
|
||||
}
|
||||
return Array.prototype.push.call(this, kid);
|
||||
return this.children.push(kid);
|
||||
}
|
||||
|
||||
Node.indentLevel = 0;
|
||||
|
@ -959,6 +960,11 @@ Narcissus.parser = (function() {
|
|||
return this.tokenizer.filename;
|
||||
});
|
||||
|
||||
definitions.defineGetter(Np, "length",
|
||||
function() {
|
||||
throw new Error("Node.prototype.length is gone; use n.children.length instead");
|
||||
});
|
||||
|
||||
definitions.defineProperty(String.prototype, "repeat",
|
||||
function(n) {
|
||||
var s = "", t = this + s;
|
||||
|
@ -1027,7 +1033,7 @@ Narcissus.parser = (function() {
|
|||
* Parses a Statement.
|
||||
*/
|
||||
function Statement(t, x) {
|
||||
var i, label, n, n2, ss, tt = t.get(true);
|
||||
var i, label, n, n2, c, ss, tt = t.get(true);
|
||||
var builder = x.builder, b, b2, b3;
|
||||
|
||||
// Cases for statements ending in a right curly return early, avoiding the
|
||||
|
@ -1141,17 +1147,19 @@ Narcissus.parser = (function() {
|
|||
b.rebuildForIn(n);
|
||||
b.setObject(n, Expression(t, x));
|
||||
if (n2.type === VAR || n2.type === LET) {
|
||||
c = n2.children;
|
||||
|
||||
// Destructuring turns one decl into multiples, so either
|
||||
// there must be only one destructuring or only one
|
||||
// decl.
|
||||
if (n2.length !== 1 && n2.destructurings.length !== 1) {
|
||||
if (c.length !== 1 && n2.destructurings.length !== 1) {
|
||||
throw new SyntaxError("Invalid for..in left-hand side",
|
||||
t.filename, n2.lineno);
|
||||
}
|
||||
if (n2.destructurings.length > 0) {
|
||||
b.setIterator(n, n2.destructurings[0], n2, forBlock);
|
||||
} else {
|
||||
b.setIterator(n, n2[0], n2, forBlock);
|
||||
b.setIterator(n, c[0], n2, forBlock);
|
||||
}
|
||||
} else {
|
||||
if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
|
||||
|
@ -1181,8 +1189,9 @@ Narcissus.parser = (function() {
|
|||
if (forBlock) {
|
||||
builder.BLOCK.finish(forBlock);
|
||||
x.stmtStack.pop();
|
||||
for (var i = 0, j = forBlock.length; i < j; i++) {
|
||||
n.body.unshift(forBlock[i]);
|
||||
c = forBlock.children;
|
||||
for (var i = 0, j = c.length; i < j; i++) {
|
||||
n.body.unshift(c[i]);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
|
@ -1726,13 +1735,14 @@ Narcissus.parser = (function() {
|
|||
return;
|
||||
|
||||
var lhss = {};
|
||||
var nn, n2, idx, sub;
|
||||
for (var i = 0, j = n.length; i < j; i++) {
|
||||
if (!(nn = n[i]))
|
||||
var nn, n2, idx, sub, cc, c = n.children;
|
||||
for (var i = 0, j = c.length; i < j; i++) {
|
||||
if (!(nn = c[i]))
|
||||
continue;
|
||||
if (nn.type === PROPERTY_INIT) {
|
||||
sub = nn[1];
|
||||
idx = nn[0].value;
|
||||
cc = nn.children;
|
||||
sub = cc[1];
|
||||
idx = cc[0].value;
|
||||
} else if (n.type === OBJECT_INIT) {
|
||||
// Do we have destructuring shorthand {foo, bar}?
|
||||
sub = nn;
|
||||
|
@ -1891,7 +1901,7 @@ Narcissus.parser = (function() {
|
|||
b.addOperand(n2, n);
|
||||
n = n2;
|
||||
do {
|
||||
n2 = n[n.length-1];
|
||||
n2 = n.children[n.children.length-1];
|
||||
if (n2.type === YIELD && !n2.parenthesized)
|
||||
throw t.newSyntaxError("Yield expression must be parenthesized");
|
||||
b.addOperand(n, AssignExpression(t, x));
|
||||
|
@ -2233,7 +2243,7 @@ Narcissus.parser = (function() {
|
|||
throw t.newSyntaxError("Yield " + err);
|
||||
if (t.match(FOR)) {
|
||||
n2 = GeneratorExpression(t, x, n2);
|
||||
if (n.length > 1 || t.peek(true) === COMMA)
|
||||
if (n.children.length > 1 || t.peek(true) === COMMA)
|
||||
throw t.newSyntaxError("Generator " + err);
|
||||
}
|
||||
b.addOperand(n, n2);
|
||||
|
@ -2274,9 +2284,9 @@ Narcissus.parser = (function() {
|
|||
|
||||
// If we matched exactly one element and got a FOR, we have an
|
||||
// array comprehension.
|
||||
if (n.length === 1 && t.match(FOR)) {
|
||||
if (n.children.length === 1 && t.match(FOR)) {
|
||||
n2 = bArrayComp.build(t);
|
||||
bArrayComp.setExpression(n2, n[0]);
|
||||
bArrayComp.setExpression(n2, n.children[0]);
|
||||
bArrayComp.setTail(n2, comprehensionTail(t, x));
|
||||
n = n2;
|
||||
}
|
||||
|
@ -2379,9 +2389,6 @@ Narcissus.parser = (function() {
|
|||
parse: parse,
|
||||
Node: Node,
|
||||
DefaultBuilder: DefaultBuilder,
|
||||
get SSABuilder() {
|
||||
throw new Error("SSA builder not yet supported");
|
||||
},
|
||||
bindSubBuilders: bindSubBuilders,
|
||||
DECLARED_FORM: DECLARED_FORM,
|
||||
EXPRESSED_FORM: EXPRESSED_FORM,
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* SSA builder and optimizations.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
Narcissus.parser.SSABuilder = (function() {
|
||||
|
||||
const parser = Narcissus.parser;
|
||||
const definitions = Narcissus.definitions;
|
||||
|
@ -717,7 +717,7 @@
|
|||
if (allDashes) {
|
||||
return null;
|
||||
}
|
||||
rhs.reverse();
|
||||
rhs.children.reverse();
|
||||
|
||||
e = new Node(ft, ASSIGN);
|
||||
e.push(lhs);
|
||||
|
@ -732,20 +732,21 @@
|
|||
continue;
|
||||
}
|
||||
|
||||
rhs = e2[1];
|
||||
rhs = e2.children[1];
|
||||
|
||||
// Optimize away phis that are only one branch, but we still need
|
||||
// to propagate them!
|
||||
if (branches == 1) {
|
||||
rhs = rhs[0];
|
||||
rhs = rhs.children[0];
|
||||
} else {
|
||||
// Push a phi use for each operand so the phis can be filled
|
||||
// in during exec.
|
||||
for (var i = 0, j = rhs.length; i < j; i++) {
|
||||
if (rhs[i].type == INTERVENED) {
|
||||
var rhsc = rhs.children;
|
||||
for (var i = 0, j = rhsc.length; i < j; i++) {
|
||||
if (rhsc[i].type == INTERVENED) {
|
||||
rhs.intervened = true;
|
||||
}
|
||||
rhs[i].pushPhiUse(rhs);
|
||||
rhsc[i].pushPhiUse(rhs);
|
||||
}
|
||||
e.push(e2);
|
||||
}
|
||||
|
@ -753,7 +754,7 @@
|
|||
propagate(x, rhs);
|
||||
}
|
||||
|
||||
return e.length > 0 ? e : null;
|
||||
return e.children.length > 0 ? e : null;
|
||||
}
|
||||
|
||||
SSAJoin.prototype = {
|
||||
|
@ -904,9 +905,10 @@
|
|||
uu = u[i];
|
||||
// Phi nodes might have stale branches.
|
||||
if (uu.type == PHI) {
|
||||
for (var k = 0, l = uu.length; k < l; k++) {
|
||||
if (uu[k] === old.def) {
|
||||
uu[k] = rhs;
|
||||
var uuc = uu.children;
|
||||
for (var k = 0, l = uuc.length; k < l; k++) {
|
||||
if (uuc[k] === old.def) {
|
||||
uuc[k] = rhs;
|
||||
rhs.pushPhiUse(uu);
|
||||
}
|
||||
}
|
||||
|
@ -1279,7 +1281,7 @@
|
|||
// do.
|
||||
var bComma = this.COMMA;
|
||||
|
||||
e2.push(n.setup[0]);
|
||||
e2.push(n.setup.children[0]);
|
||||
n.setup = e2;
|
||||
|
||||
var comma = bComma.build(t);
|
||||
|
@ -1318,7 +1320,7 @@
|
|||
this.join = breakJoin.parent;
|
||||
// Add update to the top if we were a for-in
|
||||
if (n.type == FOR_IN) {
|
||||
n.body.unshift(n.update);
|
||||
n.body.children.unshift(n.update);
|
||||
n.update = null;
|
||||
n.type = FOR;
|
||||
}
|
||||
|
@ -1973,7 +1975,7 @@
|
|||
|
||||
ASSIGN: {
|
||||
addOperand: function(n, n2) {
|
||||
if (n.length == 0) {
|
||||
if (n.children.length === 0) {
|
||||
this.binds.inRHS++;
|
||||
}
|
||||
|
||||
|
@ -1981,15 +1983,16 @@
|
|||
},
|
||||
|
||||
finish: function(n) {
|
||||
if (n.length == 0) {
|
||||
if (n.children.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var join = this.join;
|
||||
var binds = this.binds;
|
||||
var fb = binds.nearestFunction;
|
||||
var lhs = n[0];
|
||||
var init = n[1];
|
||||
var nc = n.children;
|
||||
var lhs = nc[0];
|
||||
var init = nc[1];
|
||||
var upvars = init.upvars || new Upvars;
|
||||
|
||||
if (--binds.inRHS > 0) {
|
||||
|
@ -2001,7 +2004,7 @@
|
|||
var t = n.tokenizer;
|
||||
// Rebuild as COMMA.
|
||||
n.type = COMMA;
|
||||
n.length = 0;
|
||||
n.children = [];
|
||||
desugarDestructuringAssign(this, n, lhs, init);
|
||||
return;
|
||||
}
|
||||
|
@ -2053,12 +2056,11 @@
|
|||
// Transform op= into a normal assignment only if the
|
||||
// lhs is an identifier we _know_ to be from a var.
|
||||
var nt = n.tokenizer;
|
||||
var lhs = n[0];
|
||||
var n2 = mkRawIdentifier(nt, name, null, true);
|
||||
this.PRIMARY.finish(n2);
|
||||
var o = n.assignOp;
|
||||
n.assignOp = undefined;
|
||||
n.length = 0;
|
||||
n.children = [];
|
||||
n.push(lhs);
|
||||
n.push(new Node(nt, o, n2, init));
|
||||
n2.setForward(c.def);
|
||||
|
@ -2066,17 +2068,17 @@
|
|||
}
|
||||
|
||||
// Clear the forward pointer and upvars on lefthand side.
|
||||
if (n[0].forward) {
|
||||
n[0].forward = null;
|
||||
n[0].upvars = null;
|
||||
if (lhs.forward) {
|
||||
lhs.forward = null;
|
||||
lhs.upvars = null;
|
||||
}
|
||||
// Set local to help decomp to do value numbering.
|
||||
n[0].local = c.type;
|
||||
lhs.local = c.type;
|
||||
|
||||
// Get the rightmost expression in case of compound
|
||||
// assignment.
|
||||
while (init.type == ASSIGN)
|
||||
init = init[1];
|
||||
init = init.children[1];
|
||||
|
||||
if (join) {
|
||||
// If the name is not a local let, we need a phi.
|
||||
|
@ -2124,21 +2126,21 @@
|
|||
},
|
||||
|
||||
setCondition: function(n, e) {
|
||||
n[0] = e;
|
||||
n.children[0] = e;
|
||||
n.rhsUnionUpvars(e);
|
||||
this.join = new SSAJoin(this.join, this.binds, false);
|
||||
},
|
||||
|
||||
setThenPart: function(n, n2) {
|
||||
var join = this.join;
|
||||
n[1] = n2;
|
||||
n.children[1] = n2;
|
||||
n.rhsUnionUpvars(n2);
|
||||
join.finishBranch();
|
||||
join.restore(this.binds);
|
||||
},
|
||||
|
||||
setElsePart: function(n, n2) {
|
||||
n[2] = n2;
|
||||
n.children[2] = n2;
|
||||
n.rhsUnionUpvars(n2);
|
||||
},
|
||||
|
||||
|
@ -2158,7 +2160,7 @@
|
|||
},
|
||||
|
||||
addOperand: function(n, n2) {
|
||||
if (n.length == 0) {
|
||||
if (n.children.length == 0) {
|
||||
// Short circuiting means the right hand expression needs
|
||||
// to be parsed in a new context.
|
||||
var join = this.join = new SSAJoin(this.join, this.binds, false);
|
||||
|
@ -2186,7 +2188,7 @@
|
|||
},
|
||||
|
||||
addOperand: function(n, n2) {
|
||||
if (n.length == 0) {
|
||||
if (n.children.length == 0) {
|
||||
// Short circuiting means the right hand expression needs
|
||||
// to be parsed in a new context.
|
||||
var join = this.join = new SSAJoin(this.join, this.binds, false);
|
||||
|
@ -2213,7 +2215,9 @@
|
|||
|
||||
var join = this.join;
|
||||
var binds = this.binds;
|
||||
if (!(n[0].type == IDENTIFIER && binds.hasCurrent(n[0].value)))
|
||||
var nc = n.children;
|
||||
var lhs = nc[0];
|
||||
if (!(lhs.type == IDENTIFIER && binds.hasCurrent(lhs.value)))
|
||||
return;
|
||||
|
||||
//
|
||||
|
@ -2230,7 +2234,7 @@
|
|||
// effect, so we do not duplicate side effects in an unsafe
|
||||
// fashion.
|
||||
//
|
||||
var name = n[0].value;
|
||||
var name = lhs.value;
|
||||
var c = binds.current(name);
|
||||
// Don't transform vars inside of withs
|
||||
if (binds.isWith && c.type == VAR)
|
||||
|
@ -2255,7 +2259,7 @@
|
|||
if (n.postfix) {
|
||||
n.parenthesized = true;
|
||||
n.type = COMMA;
|
||||
n.length = 0;
|
||||
n.children = [];
|
||||
n.push(mkAssignSimple(this, t, ptmp,
|
||||
mkIdentifier(this, t, name)));
|
||||
}
|
||||
|
@ -2270,9 +2274,11 @@
|
|||
n.push(mkIdentifier(this, t, ptmp));
|
||||
} else {
|
||||
n.type = ASSIGN;
|
||||
n.length = 0;
|
||||
n.push(assign[0]);
|
||||
n.push(assign[1]);
|
||||
n.children = [];
|
||||
|
||||
var assignc = assign.children;
|
||||
n.push(assignc[0]);
|
||||
n.push(assignc[1]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2296,12 +2302,13 @@
|
|||
var join = this.join;
|
||||
var binds = this.binds;
|
||||
var fb = binds.nearestFunction;
|
||||
var nc = n.children;
|
||||
|
||||
if (--binds.inRHS > 0) {
|
||||
if (unionOnRight) {
|
||||
n.upvars = n[1].upvars;
|
||||
n.upvars = nc[1].upvars;
|
||||
} else {
|
||||
n.upvars = n[0].upvars;
|
||||
n.upvars = nc[0].upvars;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2357,8 +2364,9 @@
|
|||
// local ones, so blast away context.
|
||||
//
|
||||
var inners = this.binds.inners;
|
||||
var base = baseOfCall(n[0]);
|
||||
var target = targetOfCall(n[0], IDENTIFIER);
|
||||
var call = nc[0];
|
||||
var base = baseOfCall(call);
|
||||
var target = targetOfCall(call, IDENTIFIER);
|
||||
|
||||
if (target == "eval") {
|
||||
escapeEval(join, binds);
|
||||
|
@ -2454,7 +2462,7 @@
|
|||
var unionOnRight = n.type == CALL || n.type == NEW_WITH_ARGS ||
|
||||
n.type == INDEX;
|
||||
if (unionOnRight) {
|
||||
escapeVars(join, binds, n[1].upvars || new Upvars);
|
||||
escapeVars(join, binds, nc[1].upvars || new Upvars);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2581,7 +2589,7 @@
|
|||
},
|
||||
|
||||
finish: function(n) {
|
||||
n.rhsUnionUpvars(n[1]);
|
||||
n.rhsUnionUpvars(n.children[1]);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2837,9 +2845,9 @@
|
|||
function baseOfCall(n) {
|
||||
switch (n.type) {
|
||||
case DOT:
|
||||
return baseOfCall(n[0]);
|
||||
return baseOfCall(n.children[0]);
|
||||
case INDEX:
|
||||
return baseOfCall(n[0]);
|
||||
return baseOfCall(n.children[0]);
|
||||
default:
|
||||
return n;
|
||||
}
|
||||
|
@ -2850,9 +2858,9 @@
|
|||
case ident:
|
||||
return n.value;
|
||||
case DOT:
|
||||
return targetOfCall(n[1], IDENTIFIER);
|
||||
return targetOfCall(n.children[1], IDENTIFIER);
|
||||
case INDEX:
|
||||
return targetOfCall(n[1], STRING);
|
||||
return targetOfCall(n.children[1], STRING);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -2948,9 +2956,9 @@
|
|||
builder.genDestructuringSym(),
|
||||
e, false);
|
||||
builder.binds.block.push(decl);
|
||||
decl[0].setForward(e);
|
||||
|
||||
go(n.destructuredNames, decl[0]);
|
||||
var declc = decl.children[0];
|
||||
declc[0].setForward(e);
|
||||
go(n.destructuredNames, declc[0]);
|
||||
}
|
||||
|
||||
function desugarDestructuringInit(builder, n, e) {
|
||||
|
@ -2984,8 +2992,9 @@
|
|||
var dtmp = builder.genDestructuringSym();
|
||||
var decl = mkDecl(builder, "LET", t, dtmp, e, false);
|
||||
block.push(decl);
|
||||
decl[0].setForward(e);
|
||||
go(ddecls, decl[0]);
|
||||
var declc = decl.children[0];
|
||||
declc[0].setForward(e);
|
||||
go(ddecls, declc[0]);
|
||||
} else {
|
||||
// This only happens when we have destructuring for a catch var,
|
||||
// in which case that catch var already has let-scoping, so we
|
||||
|
@ -3139,6 +3148,6 @@
|
|||
this.phiUses.push(p);
|
||||
};
|
||||
|
||||
parser.SSABuilder = SSABuilder;
|
||||
return SSABuilder;
|
||||
|
||||
}());
|
||||
|
|
|
@ -16,6 +16,7 @@ js_cmd = os.path.abspath(os.path.join(THIS_DIR, "js"))
|
|||
narc_jsdefs = os.path.join(NARC_JS_DIR, "jsdefs.js")
|
||||
narc_jslex = os.path.join(NARC_JS_DIR, "jslex.js")
|
||||
narc_jsparse = os.path.join(NARC_JS_DIR, "jsparse.js")
|
||||
narc_jsssa = os.path.join(NARC_JS_DIR, "jsssa.js")
|
||||
narc_jsexec = os.path.join(NARC_JS_DIR, "jsexec.js")
|
||||
|
||||
def handler(signum, frame):
|
||||
|
@ -62,5 +63,5 @@ if __name__ == '__main__':
|
|||
if options.js_interactive:
|
||||
cmd += 'Narcissus.interpreter.repl();'
|
||||
|
||||
Popen([js_cmd, '-f', narc_jsdefs, '-f', narc_jslex, '-f', narc_jsparse, '-f', narc_jsexec, '-e', cmd]).wait()
|
||||
Popen([js_cmd, '-f', narc_jsdefs, '-f', narc_jslex, '-f', narc_jsparse, '-f', narc_jsssa, '-f', narc_jsexec, '-e', cmd]).wait()
|
||||
|
||||
|
|
|
@ -259,6 +259,7 @@ e4x/extensions/regress-410192.js
|
|||
e4x/extensions/regress-450871-01.js
|
||||
e4x/extensions/regress-450871-02.js
|
||||
e4x/extensions/regress-462734-01.js
|
||||
e4x/extensions/extensibility.js
|
||||
ecma/Array/15.4.4.3-1.js
|
||||
ecma/Boolean/15.6.4.1.js
|
||||
ecma/Boolean/15.6.4.2-4-n.js
|
||||
|
@ -606,10 +607,13 @@ ecma_5/Object/15.2.3.6-redefinition-2-of-4.js
|
|||
ecma_5/Object/15.2.3.6-redefinition-3-of-4.js
|
||||
ecma_5/Object/15.2.3.6-redefinition-4-of-4.js
|
||||
ecma_5/Object/15.2.3.7-01.js
|
||||
ecma_5/Object/extensibility-01.js
|
||||
ecma_5/Object/vacuous-accessor-unqualified-name.js
|
||||
ecma_5/RegExp/15.10.7.5-01.js
|
||||
ecma_5/Types/8.12.5-01.js
|
||||
ecma_5/extensions/8.12.5-01.js
|
||||
ecma_5/extensions/string-literal-getter-setter-decompilation.js
|
||||
ecma_5/extensions/15.4.4.11.js
|
||||
ecma_5/misc/enumerate-undefined.js
|
||||
ecma_5/misc/global-numeric-properties.js
|
||||
ecma_5/strict/10.4.2.js
|
||||
|
@ -629,6 +633,21 @@ ecma_5/strict/8.7.2.js
|
|||
ecma_5/strict/B.1.1.js
|
||||
ecma_5/strict/B.1.2.js
|
||||
ecma_5/strict/regress-532254.js
|
||||
ecma_5/strict/8.12.5.js
|
||||
ecma_5/strict/8.12.7.js
|
||||
ecma_5/strict/10.6.js
|
||||
ecma_5/strict/15.3.5.1.js
|
||||
ecma_5/strict/15.3.5.2.js
|
||||
ecma_5/strict/15.4.4.9.js
|
||||
ecma_5/strict/15.4.4.6.js
|
||||
ecma_5/strict/15.4.4.8.js
|
||||
ecma_5/strict/15.4.4.12.js
|
||||
ecma_5/strict/15.4.5.1.js
|
||||
ecma_5/strict/15.4.4.13.js
|
||||
ecma_5/strict/15.5.5.1.js
|
||||
ecma_5/strict/15.5.5.2.js
|
||||
ecma_5/strict/15.10.7.js
|
||||
ecma_5/strict/function-name-arity.js
|
||||
js1_2/regexp/RegExp_multiline.js
|
||||
js1_2/regexp/RegExp_multiline_as_array.js
|
||||
js1_2/regexp/alphanumeric.js
|
||||
|
@ -1335,6 +1354,9 @@ js1_8_5/extensions/destructure-accessor.js
|
|||
js1_8_5/extensions/reflect-parse.js
|
||||
js1_8_5/extensions/scripted-proxies.js
|
||||
js1_8_5/extensions/typedarray.js
|
||||
js1_8_5/extensions/clone-object.js
|
||||
js1_8_5/extensions/clone-errors.js
|
||||
js1_8_5/extensions/clone-typed-array.js
|
||||
js1_8_5/regress/regress-500528.js
|
||||
js1_8_5/regress/regress-533876.js
|
||||
js1_8_5/regress/regress-541255-0.js
|
||||
|
@ -1354,6 +1376,10 @@ js1_8_5/regress/regress-577648-1.js
|
|||
js1_8_5/regress/regress-577648-2.js
|
||||
js1_8_5/regress/regress-584355.js
|
||||
js1_8_5/regress/regress-588339.js
|
||||
js1_8_5/regress/regress-592217.js
|
||||
js1_8_5/regress/regress-596805-2.js
|
||||
js1_8_5/regress/regress-597870.js
|
||||
js1_8_5/regress/regress-597945-1.js
|
||||
narcissus/../ecma/Date/15.9.5.10-2.js
|
||||
narcissus/../ecma/Date/15.9.5.11-2.js
|
||||
narcissus/../ecma/Date/15.9.5.12-2.js
|
||||
|
|
Загрузка…
Ссылка в новой задаче