"
+}
+
+
diff --git a/tests/test_tools/selenium/core/scripts/narcissus-defs.js b/tests/test_tools/selenium/core/scripts/narcissus-defs.js
new file mode 100644
index 00000000..5869397d
--- /dev/null
+++ b/tests/test_tools/selenium/core/scripts/narcissus-defs.js
@@ -0,0 +1,175 @@
+/* ***** 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 the Narcissus JavaScript engine.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich .
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+/*
+ * Narcissus - JS implemented in JS.
+ *
+ * Well-known constants and lookup tables. Many consts are generated from the
+ * tokens table via eval to minimize redundancy, so consumers must be compiled
+ * separately to take advantage of the simple switch-case constant propagation
+ * done by SpiderMonkey.
+ */
+
+// jrh
+//module('JS.Defs');
+
+GLOBAL = this;
+
+var tokens = [
+ // End of source.
+ "END",
+
+ // Operators and punctuators. Some pair-wise order matters, e.g. (+, -)
+ // and (UNARY_PLUS, UNARY_MINUS).
+ "\n", ";",
+ ",",
+ "=",
+ "?", ":", "CONDITIONAL",
+ "||",
+ "&&",
+ "|",
+ "^",
+ "&",
+ "==", "!=", "===", "!==",
+ "<", "<=", ">=", ">",
+ "<<", ">>", ">>>",
+ "+", "-",
+ "*", "/", "%",
+ "!", "~", "UNARY_PLUS", "UNARY_MINUS",
+ "++", "--",
+ ".",
+ "[", "]",
+ "{", "}",
+ "(", ")",
+
+ // Nonterminal tree node type codes.
+ "SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
+ "ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
+ "GROUP", "LIST",
+
+ // Terminals.
+ "IDENTIFIER", "NUMBER", "STRING", "REGEXP",
+
+ // Keywords.
+ "break",
+ "case", "catch", "const", "continue",
+ "debugger", "default", "delete", "do",
+ "else", "enum",
+ "false", "finally", "for", "function",
+ "if", "in", "instanceof",
+ "new", "null",
+ "return",
+ "switch",
+ "this", "throw", "true", "try", "typeof",
+ "var", "void",
+ "while", "with",
+ // Extensions
+ "require", "bless", "mixin", "import"
+];
+
+// Operator and punctuator mapping from token to tree node type name.
+// NB: superstring tokens (e.g., ++) must come before their substring token
+// counterparts (+ in the example), so that the opRegExp regular expression
+// synthesized from this list makes the longest possible match.
+var opTypeNames = {
+ '\n': "NEWLINE",
+ ';': "SEMICOLON",
+ ',': "COMMA",
+ '?': "HOOK",
+ ':': "COLON",
+ '||': "OR",
+ '&&': "AND",
+ '|': "BITWISE_OR",
+ '^': "BITWISE_XOR",
+ '&': "BITWISE_AND",
+ '===': "STRICT_EQ",
+ '==': "EQ",
+ '=': "ASSIGN",
+ '!==': "STRICT_NE",
+ '!=': "NE",
+ '<<': "LSH",
+ '<=': "LE",
+ '<': "LT",
+ '>>>': "URSH",
+ '>>': "RSH",
+ '>=': "GE",
+ '>': "GT",
+ '++': "INCREMENT",
+ '--': "DECREMENT",
+ '+': "PLUS",
+ '-': "MINUS",
+ '*': "MUL",
+ '/': "DIV",
+ '%': "MOD",
+ '!': "NOT",
+ '~': "BITWISE_NOT",
+ '.': "DOT",
+ '[': "LEFT_BRACKET",
+ ']': "RIGHT_BRACKET",
+ '{': "LEFT_CURLY",
+ '}': "RIGHT_CURLY",
+ '(': "LEFT_PAREN",
+ ')': "RIGHT_PAREN"
+};
+
+// Hash of keyword identifier to tokens index. NB: we must null __proto__ to
+// avoid toString, etc. namespace pollution.
+var keywords = {__proto__: null};
+
+// Define const END, etc., based on the token names. Also map name to index.
+var consts = " ";
+for (var i = 0, j = tokens.length; i < j; i++) {
+ if (i > 0)
+ consts += "; ";
+ var t = tokens[i];
+ if (/^[a-z]/.test(t)) {
+ consts += t.toUpperCase();
+ keywords[t] = i;
+ } else {
+ consts += (/^\W/.test(t) ? opTypeNames[t] : t);
+ }
+ consts += " = " + i;
+ tokens[t] = i;
+}
+eval(consts + ";");
+
+// Map assignment operators to their indexes in the tokens array.
+var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
+
+for (i = 0, j = assignOps.length; i < j; i++) {
+ t = assignOps[i];
+ assignOps[t] = tokens[t];
+}
diff --git a/tests/test_tools/selenium/core/scripts/narcissus-exec.js b/tests/test_tools/selenium/core/scripts/narcissus-exec.js
new file mode 100644
index 00000000..e2c88f81
--- /dev/null
+++ b/tests/test_tools/selenium/core/scripts/narcissus-exec.js
@@ -0,0 +1,1054 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * vim: set ts=4 sw=4 et tw=80:
+ *
+ * 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 the Narcissus JavaScript engine.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich .
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+/*
+ * Narcissus - JS implemented in JS.
+ *
+ * Execution of parse trees.
+ *
+ * Standard classes except for eval, Function, Array, and String are borrowed
+ * from the host JS environment. Function is metacircular. Array and String
+ * are reflected via wrapping the corresponding native constructor and adding
+ * an extra level of prototype-based delegation.
+ */
+
+// jrh
+//module('JS.Exec');
+// end jrh
+
+GLOBAL_CODE = 0; EVAL_CODE = 1; FUNCTION_CODE = 2;
+
+function ExecutionContext(type) {
+ this.type = type;
+}
+
+// jrh
+var agenda = new Array();
+var skip_setup = 0;
+// end jrh
+
+var global = {
+ // Value properties.
+ NaN: NaN, Infinity: Infinity, undefined: undefined,
+ alert : function(msg) { alert(msg) },
+ confirm : function(msg) { return confirm(msg) },
+ document : document,
+ window : window,
+ // jrh
+ //debug: window.open('','debugwindow','width=600,height=400,scrollbars=yes,resizable=yes'),
+ // end jrh
+ navigator : navigator,
+ XMLHttpRequest : function() { return new XMLHttpRequest() },
+ // Function properties.
+ eval: function(s) {
+ if (typeof s != "string") {
+ return s;
+ }
+
+ var x = ExecutionContext.current;
+ var x2 = new ExecutionContext(EVAL_CODE);
+ x2.thisObject = x.thisObject;
+ x2.caller = x.caller;
+ x2.callee = x.callee;
+ x2.scope = x.scope;
+ ExecutionContext.current = x2;
+ try {
+ execute(parse(s), x2);
+ } catch (e) {
+ x.result = x2.result;
+ throw e;
+ } finally {
+ ExecutionContext.current = x;
+ }
+ return x2.result;
+ },
+ parseInt: parseInt, parseFloat: parseFloat,
+ isNaN: isNaN, isFinite: isFinite,
+ decodeURI: decodeURI, encodeURI: encodeURI,
+ decodeURIComponent: decodeURIComponent,
+ encodeURIComponent: encodeURIComponent,
+
+ // Class constructors. Where ECMA-262 requires C.length == 1, we declare
+ // a dummy formal parameter.
+ Object: Object,
+ Function: function(dummy) {
+ var p = "", b = "", n = arguments.length;
+ if (n) {
+ var m = n - 1;
+ if (m) {
+ p += arguments[0];
+ for (var k = 1; k < m; k++)
+ p += "," + arguments[k];
+ }
+ b += arguments[m];
+ }
+
+ // XXX We want to pass a good file and line to the tokenizer.
+ // Note the anonymous name to maintain parity with Spidermonkey.
+ var t = new Tokenizer("anonymous(" + p + ") {" + b + "}");
+
+ // NB: Use the STATEMENT_FORM constant since we don't want to push this
+ // function onto the null compilation context.
+ var f = FunctionDefinition(t, null, false, STATEMENT_FORM);
+ var s = {object: global, parent: null};
+ return new FunctionObject(f, s);
+ },
+ Array: function(dummy) {
+ // Array when called as a function acts as a constructor.
+ return GLOBAL.Array.apply(this, arguments);
+ },
+ String: function(s) {
+ // Called as function or constructor: convert argument to string type.
+ s = arguments.length ? "" + s : "";
+ if (this instanceof String) {
+ // Called as constructor: save the argument as the string value
+ // of this String object and return this object.
+ this.value = s;
+ return this;
+ }
+ return s;
+ },
+ Boolean: Boolean, Number: Number, Date: Date, RegExp: RegExp,
+ Error: Error, EvalError: EvalError, RangeError: RangeError,
+ ReferenceError: ReferenceError, SyntaxError: SyntaxError,
+ TypeError: TypeError, URIError: URIError,
+
+ // Other properties.
+ Math: Math,
+
+ // Extensions to ECMA.
+ //snarf: snarf,
+ evaluate: evaluate,
+ load: function(s) {
+ if (typeof s != "string")
+ return s;
+ var req = new XMLHttpRequest();
+ req.open('GET', s, false);
+ req.send(null);
+
+ evaluate(req.responseText, s, 1)
+ },
+ print: print, version: null
+};
+
+// jrh
+//global.debug.document.body.innerHTML = ''
+// end jrh
+
+// Helper to avoid Object.prototype.hasOwnProperty polluting scope objects.
+function hasDirectProperty(o, p) {
+ return Object.prototype.hasOwnProperty.call(o, p);
+}
+
+// Reflect a host class into the target global environment by delegation.
+function reflectClass(name, proto) {
+ var gctor = global[name];
+ gctor.prototype = proto;
+ proto.constructor = gctor;
+ return proto;
+}
+
+// Reflect Array -- note that all Array methods are generic.
+reflectClass('Array', new Array);
+
+// Reflect String, overriding non-generic methods.
+var gSp = reflectClass('String', new String);
+gSp.toSource = function () { return this.value.toSource(); };
+gSp.toString = function () { return this.value; };
+gSp.valueOf = function () { return this.value; };
+global.String.fromCharCode = String.fromCharCode;
+
+var XCp = ExecutionContext.prototype;
+ExecutionContext.current = XCp.caller = XCp.callee = null;
+XCp.scope = {object: global, parent: null};
+XCp.thisObject = global;
+XCp.result = undefined;
+XCp.target = null;
+XCp.ecmaStrictMode = false;
+
+function Reference(base, propertyName, node) {
+ this.base = base;
+ this.propertyName = propertyName;
+ this.node = node;
+}
+
+Reference.prototype.toString = function () { return this.node.getSource(); }
+
+function getValue(v) {
+ if (v instanceof Reference) {
+ if (!v.base) {
+ throw new ReferenceError(v.propertyName + " is not defined",
+ v.node.filename(), v.node.lineno);
+ }
+ return v.base[v.propertyName];
+ }
+ return v;
+}
+
+function putValue(v, w, vn) {
+ if (v instanceof Reference)
+ return (v.base || global)[v.propertyName] = w;
+ throw new ReferenceError("Invalid assignment left-hand side",
+ vn.filename(), vn.lineno);
+}
+
+function isPrimitive(v) {
+ var t = typeof v;
+ return (t == "object") ? v === null : t != "function";
+}
+
+function isObject(v) {
+ var t = typeof v;
+ return (t == "object") ? v !== null : t == "function";
+}
+
+// If r instanceof Reference, v == getValue(r); else v === r. If passed, rn
+// is the node whose execute result was r.
+function toObject(v, r, rn) {
+ switch (typeof v) {
+ case "boolean":
+ return new global.Boolean(v);
+ case "number":
+ return new global.Number(v);
+ case "string":
+ return new global.String(v);
+ case "function":
+ return v;
+ case "object":
+ if (v !== null)
+ return v;
+ }
+ var message = r + " (type " + (typeof v) + ") has no properties";
+ throw rn ? new TypeError(message, rn.filename(), rn.lineno)
+ : new TypeError(message);
+}
+
+function execute(n, x) {
+ if (!this.new_block)
+ new_block = new Array();
+ //alert (n)
+ var a, f, i, j, r, s, t, u, v;
+ switch (n.type) {
+ case FUNCTION:
+ if (n.functionForm != DECLARED_FORM) {
+ if (!n.name || n.functionForm == STATEMENT_FORM) {
+ v = new FunctionObject(n, x.scope);
+ if (n.functionForm == STATEMENT_FORM)
+ x.scope.object[n.name] = v;
+ } else {
+ t = new Object;
+ x.scope = {object: t, parent: x.scope};
+ try {
+ v = new FunctionObject(n, x.scope);
+ t[n.name] = v;
+ } finally {
+ x.scope = x.scope.parent;
+ }
+ }
+ }
+ break;
+
+ case SCRIPT:
+ t = x.scope.object;
+ a = n.funDecls;
+ for (i = 0, j = a.length; i < j; i++) {
+ s = a[i].name;
+ f = new FunctionObject(a[i], x.scope);
+ t[s] = f;
+ }
+ a = n.varDecls;
+ for (i = 0, j = a.length; i < j; i++) {
+ u = a[i];
+ s = u.name;
+ if (u.readOnly && hasDirectProperty(t, s)) {
+ throw new TypeError("Redeclaration of const " + s,
+ u.filename(), u.lineno);
+ }
+ if (u.readOnly || !hasDirectProperty(t, s)) {
+ t[s] = null;
+ }
+ }
+ // FALL THROUGH
+
+ case BLOCK:
+ for (i = 0, j = n.$length; i < j; i++) {
+ //jrh
+ //execute(n[i], x);
+ //new_block.unshift([n[i], x]);
+ new_block.push([n[i], x]);
+ }
+ new_block.reverse();
+ agenda = agenda.concat(new_block);
+ //agenda = new_block.concat(agenda)
+ // end jrh
+ break;
+
+ case IF:
+ if (getValue(execute(n.condition, x)))
+ execute(n.thenPart, x);
+ else if (n.elsePart)
+ execute(n.elsePart, x);
+ break;
+
+ case SWITCH:
+ s = getValue(execute(n.discriminant, x));
+ a = n.cases;
+ var matchDefault = false;
+ switch_loop:
+ for (i = 0, j = a.length; ; i++) {
+ if (i == j) {
+ if (n.defaultIndex >= 0) {
+ i = n.defaultIndex - 1; // no case matched, do default
+ matchDefault = true;
+ continue;
+ }
+ break; // no default, exit switch_loop
+ }
+ t = a[i]; // next case (might be default!)
+ if (t.type == CASE) {
+ u = getValue(execute(t.caseLabel, x));
+ } else {
+ if (!matchDefault) // not defaulting, skip for now
+ continue;
+ u = s; // force match to do default
+ }
+ if (u === s) {
+ for (;;) { // this loop exits switch_loop
+ if (t.statements.length) {
+ try {
+ execute(t.statements, x);
+ } catch (e) {
+ if (!(e == BREAK && x.target == n)) { throw e }
+ break switch_loop;
+ }
+ }
+ if (++i == j)
+ break switch_loop;
+ t = a[i];
+ }
+ // NOT REACHED
+ }
+ }
+ break;
+
+ case FOR:
+ // jrh
+ // added "skip_setup" so initialization doesn't get called
+ // on every call..
+ if (!skip_setup)
+ n.setup && getValue(execute(n.setup, x));
+ // FALL THROUGH
+ case WHILE:
+ // jrh
+ //while (!n.condition || getValue(execute(n.condition, x))) {
+ if (!n.condition || getValue(execute(n.condition, x))) {
+ try {
+ // jrh
+ //execute(n.body, x);
+ new_block.push([n.body, x]);
+ agenda.push([n.body, x])
+ //agenda.unshift([n.body, x])
+ // end jrh
+ } catch (e) {
+ if (e == BREAK && x.target == n) {
+ break;
+ } else if (e == CONTINUE && x.target == n) {
+ // jrh
+ // 'continue' is invalid inside an 'if' clause
+ // I don't know what commenting this out will break!
+ //continue;
+ // end jrh
+
+ } else {
+ throw e;
+ }
+ }
+ n.update && getValue(execute(n.update, x));
+ // jrh
+ new_block.unshift([n, x])
+ agenda.splice(agenda.length-1,0,[n, x])
+ //agenda.splice(1,0,[n, x])
+ skip_setup = 1
+ // end jrh
+ } else {
+ skip_setup = 0
+ }
+
+ break;
+
+ case FOR_IN:
+ u = n.varDecl;
+ if (u)
+ execute(u, x);
+ r = n.iterator;
+ s = execute(n.object, x);
+ v = getValue(s);
+
+ // ECMA deviation to track extant browser JS implementation behavior.
+ t = (v == null && !x.ecmaStrictMode) ? v : toObject(v, s, n.object);
+ a = [];
+ for (i in t)
+ a.push(i);
+ for (i = 0, j = a.length; i < j; i++) {
+ putValue(execute(r, x), a[i], r);
+ try {
+ execute(n.body, x);
+ } catch (e) {
+ if (e == BREAK && x.target == n) {
+ break;
+ } else if (e == CONTINUE && x.target == n) {
+ continue;
+ } else {
+ throw e;
+ }
+ }
+ }
+ break;
+
+ case DO:
+ do {
+ try {
+ execute(n.body, x);
+ } catch (e) {
+ if (e == BREAK && x.target == n) {
+ break;
+ } else if (e == CONTINUE && x.target == n) {
+ continue;
+ } else {
+ throw e;
+ }
+ }
+ } while (getValue(execute(n.condition, x)));
+ break;
+
+ case BREAK:
+ case CONTINUE:
+ x.target = n.target;
+ throw n.type;
+
+ case TRY:
+ try {
+ execute(n.tryBlock, x);
+ } catch (e) {
+ if (!(e == THROW && (j = n.catchClauses.length))) {
+ throw e;
+ }
+ e = x.result;
+ x.result = undefined;
+ for (i = 0; ; i++) {
+ if (i == j) {
+ x.result = e;
+ throw THROW;
+ }
+ t = n.catchClauses[i];
+ x.scope = {object: {}, parent: x.scope};
+ x.scope.object[t.varName] = e;
+ try {
+ if (t.guard && !getValue(execute(t.guard, x)))
+ continue;
+ execute(t.block, x);
+ break;
+ } finally {
+ x.scope = x.scope.parent;
+ }
+ }
+ } finally {
+ if (n.finallyBlock)
+ execute(n.finallyBlock, x);
+ }
+ break;
+
+ case THROW:
+ x.result = getValue(execute(n.exception, x));
+ throw THROW;
+
+ case RETURN:
+ x.result = getValue(execute(n.value, x));
+ throw RETURN;
+
+ case WITH:
+ r = execute(n.object, x);
+ t = toObject(getValue(r), r, n.object);
+ x.scope = {object: t, parent: x.scope};
+ try {
+ execute(n.body, x);
+ } finally {
+ x.scope = x.scope.parent;
+ }
+ break;
+
+ case VAR:
+ case CONST:
+ for (i = 0, j = n.$length; i < j; i++) {
+ u = n[i].initializer;
+ if (!u)
+ continue;
+ t = n[i].name;
+ for (s = x.scope; s; s = s.parent) {
+ if (hasDirectProperty(s.object, t))
+ break;
+ }
+ u = getValue(execute(u, x));
+ if (n.type == CONST)
+ s.object[t] = u;
+ else
+ s.object[t] = u;
+ }
+ break;
+
+ case DEBUGGER:
+ throw "NYI: " + tokens[n.type];
+
+ case REQUIRE:
+ var req = new XMLHttpRequest();
+ req.open('GET', n.filename, 'false');
+
+ case SEMICOLON:
+ if (n.expression)
+ // print debugging statements
+
+ var the_start = n.start
+ var the_end = n.end
+ var the_statement = parse_result.tokenizer.source.slice(the_start,the_end)
+ //global.debug.document.body.innerHTML += ('