зеркало из https://github.com/mozilla/narcissus.git
ripped out version option and ES3-only mode; modules are always available but not yet working
This commit is contained in:
Родитель
31202acab0
Коммит
0587a3a826
|
@ -15,7 +15,7 @@ SUCCEED_PASS=0
|
|||
SUCCEED_FAIL=0
|
||||
|
||||
for f in harmony-tests/succeed/*.js ; do
|
||||
./njs -H -f $f >/dev/null 2>&1
|
||||
./njs -f $f >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
SUCCEED_PASS=$(($SUCCEED_PASS + 1))
|
||||
else
|
||||
|
@ -35,7 +35,7 @@ FAIL_RESOLVE_PASS=0
|
|||
FAIL_RESOLVE_FAIL=0
|
||||
|
||||
for f in harmony-tests/fail-resolve/*.js ; do
|
||||
./njs -H -E "Narcissus.resolver.resolve(Narcissus.parser.parse(snarf('$f')),Narcissus.interpreter.globalStaticEnv)" >/dev/null 2>&1
|
||||
./njs -E "Narcissus.resolver.resolve(Narcissus.parser.parse(snarf('$f')),Narcissus.interpreter.globalStaticEnv)" >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
FAIL_RESOLVE_FAIL=$((FAIL_RESOLVE_FAIL + 1))
|
||||
FAILURES="$FAILURES $f"
|
||||
|
@ -55,7 +55,7 @@ FAIL_EXECUTE_PASS=0
|
|||
FAIL_EXECUTE_FAIL=0
|
||||
|
||||
for f in harmony-tests/fail-execute ; do
|
||||
./njs -H -f $f >/dev/null 2>&1
|
||||
./njs -f $f >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
FAIL_EXECUTE_FAIL=$(($FAIL_EXECUTE_FAIL + 1))
|
||||
FAILURES="$FAILURES $f"
|
||||
|
|
|
@ -54,13 +54,16 @@
|
|||
|
||||
var narcissus = {
|
||||
options: {
|
||||
version: 185,
|
||||
// Global variables to hide from the interpreter
|
||||
hiddenHostGlobals: { Narcissus: true },
|
||||
// Desugar SpiderMonkey language extensions?
|
||||
desugarExtensions: false,
|
||||
// Allow HTML comments?
|
||||
allowHTMLComments: false
|
||||
allowHTMLComments: false,
|
||||
// Allow non-standard Mozilla extensions?
|
||||
mozillaMode: true,
|
||||
// Allow experimental paren-free mode?
|
||||
parenFreeMode: false
|
||||
},
|
||||
hostSupportsEvalConst: (function() {
|
||||
try {
|
||||
|
@ -374,29 +377,6 @@ Narcissus.definitions = (function(hostGlobal) {
|
|||
return mixinHandler(redirect, catchall);
|
||||
}
|
||||
|
||||
function mirrorHandler(target, writable) {
|
||||
var handler = makePassthruHandler(target);
|
||||
|
||||
var defineProperty = handler.defineProperty;
|
||||
handler.defineProperty = function(name, desc) {
|
||||
if (!desc.enumerable)
|
||||
throw new Error("mirror property must be enumerable");
|
||||
if (!desc.configurable)
|
||||
throw new Error("mirror property must be configurable");
|
||||
if (desc.writable !== writable)
|
||||
throw new Error("mirror property must " + (writable ? "" : "not ") + "be writable");
|
||||
defineProperty(name, desc);
|
||||
};
|
||||
|
||||
handler.fix = function() { };
|
||||
handler.getOwnPropertyDescriptor = handler.getPropertyDescriptor;
|
||||
handler.getOwnPropertyNames = getPropertyNames.bind(handler, target);
|
||||
handler.keys = handler.enumerate;
|
||||
handler["delete"] = function() { return false; };
|
||||
handler.hasOwn = handler.has;
|
||||
return handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mixin proxies break the single-inheritance model of prototypes, so
|
||||
* the handler treats all properties as own-properties:
|
||||
|
@ -721,7 +701,6 @@ Narcissus.definitions = (function(hostGlobal) {
|
|||
isNativeCode: isNativeCode,
|
||||
apply: apply,
|
||||
applyNew: applyNew,
|
||||
mirrorHandler: mirrorHandler,
|
||||
mixinHandler: mixinHandler,
|
||||
whitelistHandler: whitelistHandler,
|
||||
blacklistHandler: blacklistHandler,
|
||||
|
|
|
@ -86,14 +86,9 @@ Narcissus.interpreter = (function() {
|
|||
CONTINUE_SIGNAL = new InternalSignal,
|
||||
EXIT_SIGNAL = new InternalSignal;
|
||||
|
||||
function ExecutionContext(type, version) {
|
||||
function ExecutionContext(type, strict) {
|
||||
this.type = type;
|
||||
this.version = version;
|
||||
// In Harmony, the global scope record is not exposed to the program.
|
||||
if (type === GLOBAL_CODE && version === "harmony") {
|
||||
this.scope = {object: globalScope, parent: null};
|
||||
this.thisObject = globalMirror;
|
||||
}
|
||||
this.strict = !!strict;
|
||||
}
|
||||
|
||||
function isStackOverflow(e) {
|
||||
|
@ -112,13 +107,13 @@ Narcissus.interpreter = (function() {
|
|||
return s;
|
||||
|
||||
var x = ExecutionContext.current;
|
||||
var x2 = new ExecutionContext(EVAL_CODE, x.version);
|
||||
var x2 = new ExecutionContext(EVAL_CODE);
|
||||
x2.thisObject = x.thisObject;
|
||||
x2.thisModule = x.thisModule;
|
||||
x2.functionInstance = x.functionInstance;
|
||||
x2.scope = x.version === "harmony" ? { object: new Object, parent: x.scope } : x.scope;
|
||||
x2.scope = x.strict ? { object: new Object, parent: x.scope } : x.scope;
|
||||
var ast = parser.parse(s);
|
||||
if (x.version === "harmony") {
|
||||
if (ast.hasModules) {
|
||||
resolver.resolve(ast, new StaticEnv(x.staticEnv));
|
||||
instantiateModules(ast, x2.scope);
|
||||
}
|
||||
|
@ -184,7 +179,6 @@ Narcissus.interpreter = (function() {
|
|||
throw new TypeError("only works on scripts");
|
||||
return fint.getBytecode().toString();
|
||||
},
|
||||
version: function() { return ExecutionContext.current.version; },
|
||||
quit: function() { throw EXIT_SIGNAL; },
|
||||
assertEq: function() {
|
||||
return assertEq.apply(null, arguments);
|
||||
|
@ -197,24 +191,7 @@ Narcissus.interpreter = (function() {
|
|||
return Proxy.createFunction(
|
||||
definitions.makePassthruHandler(val),
|
||||
function() { return val.apply(hostGlobal, arguments); },
|
||||
function() {
|
||||
var a = arguments;
|
||||
switch (a.length) {
|
||||
case 0:
|
||||
return new val();
|
||||
case 1:
|
||||
return new val(a[0]);
|
||||
case 2:
|
||||
return new val(a[0], a[1]);
|
||||
case 3:
|
||||
return new val(a[0], a[1], a[2]);
|
||||
default:
|
||||
var argStr = "";
|
||||
for (var i = 0; i < a.length; i++)
|
||||
argStr += 'a[' + i + '],';
|
||||
return eval('new ' + name + '(' + argStr.slice(0,-1) + ');');
|
||||
}
|
||||
});
|
||||
function() { return applyNew(val, arguments); });
|
||||
}
|
||||
|
||||
var hostHandler = definitions.blacklistHandler(hostGlobal,
|
||||
|
@ -227,23 +204,14 @@ Narcissus.interpreter = (function() {
|
|||
|
||||
var globalStaticEnv; // global static scope
|
||||
var moduleInstances = new WeakMap(); // maps module instance objects -> module instances
|
||||
var global = Object.create(hostProxy, {}); // exposed global object (legacy)
|
||||
|
||||
// unexposed global scope record (Harmony)
|
||||
var globalScope = Object.create(hostProxy, {});
|
||||
|
||||
// exposed global scope mirror (Harmony)
|
||||
var globalMirror = Proxy.create(definitions.mirrorHandler(globalScope, true));
|
||||
var global = Object.create(hostProxy, {}); // user global object
|
||||
|
||||
function resetEnvironment() {
|
||||
ExecutionContext.current = new ExecutionContext(GLOBAL_CODE, Narcissus.options.version);
|
||||
ExecutionContext.current = new ExecutionContext(GLOBAL_CODE);
|
||||
let names = Object.getOwnPropertyNames(global);
|
||||
for (let i = 0, n = names.length; i < n; i++) {
|
||||
delete global[names[i]];
|
||||
}
|
||||
for (let key in globalScope) {
|
||||
delete globalScope[key];
|
||||
}
|
||||
moduleInstances = new WeakMap();
|
||||
globalStaticEnv = new StaticEnv();
|
||||
|
||||
|
@ -254,7 +222,6 @@ Narcissus.interpreter = (function() {
|
|||
for (let key in globalBase) {
|
||||
let val = globalBase[key];
|
||||
global[key] = val;
|
||||
globalScope[key] = val;
|
||||
// NB: this assumes globalBase never contains module or import bindings
|
||||
globalStaticEnv.bind(key, new Def());
|
||||
}
|
||||
|
@ -293,7 +260,6 @@ Narcissus.interpreter = (function() {
|
|||
functionInstance: null,
|
||||
result: undefined,
|
||||
target: null,
|
||||
ecma3OnlyMode: false,
|
||||
|
||||
// Execute a node in this execution context.
|
||||
execute: function(n) {
|
||||
|
@ -419,7 +385,7 @@ Narcissus.interpreter = (function() {
|
|||
function executeModule(n, x) {
|
||||
var m = x.scope.object[n.name];
|
||||
var inst = moduleInstances.get(m);
|
||||
var x2 = new ExecutionContext(MODULE_CODE, x.version);
|
||||
var x2 = new ExecutionContext(MODULE_CODE, true);
|
||||
x2.scope = inst.scope;
|
||||
x2.thisObject = m;
|
||||
x2.thisModule = m;
|
||||
|
@ -594,10 +560,7 @@ Narcissus.interpreter = (function() {
|
|||
s = execute(n.object, x);
|
||||
v = getValue(s);
|
||||
|
||||
// ECMA deviation to track extant browser JS implementation behavior.
|
||||
t = ((v === null || v === undefined) && !x.ecma3OnlyMode)
|
||||
? v
|
||||
: toObject(v, s, n.object);
|
||||
t = (v === null || v === undefined) ? v : toObject(v, s, n.object);
|
||||
a = [];
|
||||
for (i in t)
|
||||
a.push(i);
|
||||
|
@ -1218,7 +1181,7 @@ Narcissus.interpreter = (function() {
|
|||
|
||||
var FIp = FunctionInternals.prototype = {
|
||||
call: function(f, t, a, x) {
|
||||
var x2 = new ExecutionContext(FUNCTION_CODE, x.version);
|
||||
var x2 = new ExecutionContext(FUNCTION_CODE, this.node.body.strict);
|
||||
x2.thisObject = t || global;
|
||||
x2.thisModule = null;
|
||||
x2.functionInstance = this;
|
||||
|
@ -1275,11 +1238,11 @@ Narcissus.interpreter = (function() {
|
|||
if (typeof s !== "string")
|
||||
return s;
|
||||
|
||||
var x = new ExecutionContext(GLOBAL_CODE, Narcissus.options.version);
|
||||
var x = new ExecutionContext(GLOBAL_CODE);
|
||||
var ast = parser.parse(s, f, l);
|
||||
if (Narcissus.options.desugarExtensions)
|
||||
ast = desugaring.desugar(ast);
|
||||
if (x.version === "harmony") {
|
||||
if (ast.hasModules) {
|
||||
resolveGlobal(ast);
|
||||
instantiateModules(ast, x.scope);
|
||||
}
|
||||
|
@ -1364,7 +1327,7 @@ Narcissus.interpreter = (function() {
|
|||
return false;
|
||||
}
|
||||
|
||||
var x = new ExecutionContext(GLOBAL_CODE, Narcissus.options.version);
|
||||
var x = new ExecutionContext(GLOBAL_CODE);
|
||||
|
||||
// Line number in/out parameter to parser.parseStdin.
|
||||
var ln = {value: 0};
|
||||
|
|
|
@ -82,8 +82,7 @@ Narcissus.parser = (function() {
|
|||
this.t = tokenizer;
|
||||
this.x = null;
|
||||
this.unexpectedEOF = false;
|
||||
Narcissus.options.ecma3OnlyMode && (this.ecma3OnlyMode = true);
|
||||
Narcissus.options.version === 185 && (this.mozillaMode = true);
|
||||
Narcissus.options.mozillaMode && (this.mozillaMode = true);
|
||||
Narcissus.options.parenFreeMode && (this.parenFreeMode = true);
|
||||
}
|
||||
|
||||
|
@ -162,8 +161,6 @@ Narcissus.parser = (function() {
|
|||
|
||||
var Pp = Parser.prototype;
|
||||
|
||||
Pp.ecma3OnlyMode = false;
|
||||
|
||||
Pp.mozillaMode = false;
|
||||
|
||||
Pp.parenFreeMode = false;
|
||||
|
@ -214,9 +211,8 @@ Narcissus.parser = (function() {
|
|||
var node = this.newNode(scriptInit());
|
||||
var x2 = new StaticContext(node, node, inModule, inFunction);
|
||||
this.withContext(x2, function() {
|
||||
this.Statements(node, false);
|
||||
this.Statements(node, true);
|
||||
});
|
||||
for (var i = 0, n = node.children.length; i < n && Pragma(node.children[i]); i++);
|
||||
if (expectEnd && !this.done())
|
||||
this.fail("expected end of input");
|
||||
return node;
|
||||
|
@ -431,14 +427,23 @@ Narcissus.parser = (function() {
|
|||
}
|
||||
|
||||
/*
|
||||
* Statements :: (node) -> void
|
||||
* Statements :: (node[, boolean]) -> void
|
||||
*
|
||||
* Parses a sequence of Statements.
|
||||
*/
|
||||
Pp.Statements = function Statements(n) {
|
||||
Pp.Statements = function Statements(n, topLevel) {
|
||||
var prologue = !!topLevel;
|
||||
try {
|
||||
while (!this.done() && this.peek(true) !== RIGHT_CURLY)
|
||||
n.push(this.Statement());
|
||||
while (!this.done() && this.peek(true) !== RIGHT_CURLY) {
|
||||
var n2 = this.Statement();
|
||||
n.push(n2);
|
||||
if (prologue && Pragma(n2)) {
|
||||
this.x.strictMode = true;
|
||||
n.strict = true;
|
||||
} else {
|
||||
prologue = false;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (this.done())
|
||||
this.unexpectedEOF = true;
|
||||
|
@ -453,7 +458,7 @@ Narcissus.parser = (function() {
|
|||
this.withContext(x2, function() {
|
||||
this.Statements(n);
|
||||
});
|
||||
t.mustMatch(RIGHT_CURLY);
|
||||
this.mustMatch(RIGHT_CURLY);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -647,7 +652,7 @@ Narcissus.parser = (function() {
|
|||
}
|
||||
this.mustMatch(COLON);
|
||||
n2.statements = this.newNode(blockInit());
|
||||
while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT &&
|
||||
while ((tt=this.peek(true)) !== CASE && tt !== DEFAULT &&
|
||||
tt !== RIGHT_CURLY)
|
||||
n2.statements.push(this.Statement());
|
||||
n.cases.push(n2);
|
||||
|
@ -761,16 +766,13 @@ Narcissus.parser = (function() {
|
|||
this.withContext(x2, function() {
|
||||
n.body = this.Statement();
|
||||
});
|
||||
t.mustMatch(WHILE);
|
||||
this.mustMatch(WHILE);
|
||||
n.condition = this.HeadExpression();
|
||||
if (!this.ecma3OnlyMode) {
|
||||
// <script language="JavaScript"> (without version hints) may need
|
||||
// automatic semicolon insertion without a newline after do-while.
|
||||
// See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
|
||||
this.match(SEMICOLON);
|
||||
return n;
|
||||
}
|
||||
break;
|
||||
// <script language="JavaScript"> (without version hints) may need
|
||||
// automatic semicolon insertion without a newline after do-while.
|
||||
// See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
|
||||
this.match(SEMICOLON);
|
||||
return n;
|
||||
|
||||
case BREAK:
|
||||
case CONTINUE:
|
||||
|
@ -824,7 +826,7 @@ Narcissus.parser = (function() {
|
|||
break;
|
||||
}
|
||||
if (this.match(IF)) {
|
||||
if (this.ecma3OnlyMode)
|
||||
if (!this.mozillaMode)
|
||||
this.fail("Illegal catch guard");
|
||||
if (n.catchClauses.length && !n.catchClauses.top().guard)
|
||||
this.fail("Guarded catch after unguarded");
|
||||
|
@ -871,7 +873,7 @@ Narcissus.parser = (function() {
|
|||
break;
|
||||
|
||||
case LET:
|
||||
if (t.peek() === LEFT_PAREN) {
|
||||
if (this.peek() === LEFT_PAREN) {
|
||||
n = this.LetBlock(true);
|
||||
return n;
|
||||
}
|
||||
|
@ -1208,8 +1210,6 @@ Narcissus.parser = (function() {
|
|||
this.fail("missing function identifier");
|
||||
|
||||
var inModule = this.x.inModule;
|
||||
// var x0 = this.x;
|
||||
// this.x = new StaticContext(null, null, inModule, true, this.x.strictMode);
|
||||
x2 = new StaticContext(null, null, inModule, true, this.x.strictMode);
|
||||
this.withContext(x2, function() {
|
||||
this.mustMatch(LEFT_PAREN);
|
||||
|
@ -1245,7 +1245,6 @@ Narcissus.parser = (function() {
|
|||
f.body = this.Script(inModule, true);
|
||||
}
|
||||
});
|
||||
// this.x = x0;
|
||||
|
||||
if (tt === LEFT_CURLY)
|
||||
this.mustMatch(RIGHT_CURLY);
|
||||
|
@ -1274,7 +1273,7 @@ Narcissus.parser = (function() {
|
|||
var n1, n2;
|
||||
do {
|
||||
n1 = this.Identifier();
|
||||
if (t.match(ASSIGN)) {
|
||||
if (this.match(ASSIGN)) {
|
||||
n2 = this.ModuleExpression();
|
||||
n1.initializer = n2;
|
||||
if (n2.type === STRING)
|
||||
|
@ -1460,7 +1459,7 @@ Narcissus.parser = (function() {
|
|||
n = this.newNode({ type: FOR_IN, isLoop: true });
|
||||
if (this.match(IDENTIFIER)) {
|
||||
// But sometimes they're for each..in.
|
||||
if (this.t.token.value === "each")
|
||||
if (this.mozillaMode && this.t.token.value === "each")
|
||||
n.isEach = true;
|
||||
else
|
||||
this.t.unget();
|
||||
|
@ -1923,8 +1922,6 @@ Narcissus.parser = (function() {
|
|||
tt = this.t.get();
|
||||
if ((this.t.token.value === "get" || this.t.token.value === "set") &&
|
||||
this.peek() === IDENTIFIER) {
|
||||
if (this.ecma3OnlyMode)
|
||||
this.fail("Illegal property accessor");
|
||||
n.push(this.FunctionDefinition(true, EXPRESSED_FORM));
|
||||
} else {
|
||||
var comments = this.t.blockComments;
|
||||
|
@ -1933,8 +1930,6 @@ Narcissus.parser = (function() {
|
|||
id = this.newNode({ type: IDENTIFIER });
|
||||
break;
|
||||
case RIGHT_CURLY:
|
||||
if (this.ecma3OnlyMode)
|
||||
this.fail("Illegal trailing ,");
|
||||
break object_init;
|
||||
default:
|
||||
if (this.t.token.value in definitions.keywords) {
|
||||
|
|
13
njs
13
njs
|
@ -44,12 +44,10 @@ if __name__ == '__main__':
|
|||
help='load Narcissus but run interactive SpiderMonkey shell')
|
||||
op.add_option('-E', '--expression-meta', dest='js_exps_meta', action='append',
|
||||
help='expression to evaluate with SpiderMonkey after loading Narcissus')
|
||||
op.add_option('-H', '--harmony', dest='js_harmony', action='store_true',
|
||||
help='enable ECMAScript Harmony mode')
|
||||
op.add_option('-P', '--parse-only', dest='js_parseonly', action='store_true',
|
||||
help='stop after the parsing stage and output pretty-printed source code')
|
||||
op.add_option('-3', '--ecma3-only', dest='js_ecma3only', action='store_true',
|
||||
help='restrict source language to ECMA-262 Edition 3')
|
||||
op.add_option('-w', '--web-compatible', dest='js_webcompatible', action='store_true',
|
||||
help='disable non-standard Mozilla extensions')
|
||||
op.add_option('-p', '--paren-free', dest='js_parenfree', action='store_true',
|
||||
help='use experimental paren-free syntax')
|
||||
op.add_option('-d', '--desugar', dest='js_desugar', action='store_true',
|
||||
|
@ -59,11 +57,8 @@ if __name__ == '__main__':
|
|||
|
||||
cmd = ""
|
||||
|
||||
if options.js_harmony:
|
||||
cmd += 'Narcissus.options.version = "harmony"; '
|
||||
|
||||
if options.js_ecma3only:
|
||||
cmd += 'Narcissus.options.ecma3OnlyMode = true; '
|
||||
if options.js_webcompatible:
|
||||
cmd += 'Narcissus.options.mozillaMode = false; '
|
||||
|
||||
if options.js_parenfree:
|
||||
cmd += 'Narcissus.options.parenFreeMode = true; '
|
||||
|
|
Загрузка…
Ссылка в новой задаче