ripped out version option and ES3-only mode; modules are always available but not yet working

This commit is contained in:
Dave Herman 2012-01-10 07:39:49 -08:00
Родитель 31202acab0
Коммит 0587a3a826
5 изменённых файлов: 53 добавлений и 121 удалений

Просмотреть файл

@ -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
Просмотреть файл

@ -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; '