changeset 3:0c1314b3ea79

Removed narcissus, since it doesn't support JS 1.7 syntax.
author Atul Varma <varmaa@toolness.com>
date Mon, 05 Jan 2009 16:44:08 -0800
parents 4a813cef41b1
children ccc558eb70db
files js.js jsdefs.js jsexec.js jsparse.js thingy.html thingy.js
diffstat 6 files changed, 5 insertions(+), 2222 deletions(-) [+]
line wrap: on
line diff
--- a/js.js	Mon Jan 05 16:04:40 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/* ***** 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 <brendan@mozilla.org>.
- * 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.
- *
- * Native objects and classes implemented metacircularly:
- *      the global object (singleton)
- *      eval
- *      function objects, Function
- *
- * SpiderMonkey extensions used:
- *      catch guards
- *      const declarations
- *      get and set functions in object initialisers
- *      Object.prototype.__defineGetter__
- *      Object.prototype.__defineSetter__
- *      Object.prototype.__defineProperty__
- *      Object.prototype.__proto__
- *      filename and line number arguments to *Error constructors
- *      callable regular expression objects
- *
- * SpiderMonkey extensions supported metacircularly:
- *      catch guards
- *      const declarations
- *      get and set functions in object initialisers
- */
-
-/*
- * Loads a file relative to the calling script's (our) source directory, and not
- * the directory that the executing shell is being run out of.
- */
-function my_load(filename) {
-    evaluate(snarf(filename), filename, 1);
-}
-
-my_load('jsdefs.js');
-my_load('jsparse.js');
-my_load('jsexec.js');
-
--- a/jsdefs.js	Mon Jan 05 16:04:40 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/* ***** 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 <brendan@mozilla.org>.
- * 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.
- */
-const 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",
-    "let"
-];
-
-// 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 = "const ";
-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];
-}
--- a/jsexec.js	Mon Jan 05 16:04:40 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,944 +0,0 @@
-/* ***** 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 <brendan@mozilla.org>.
- * 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.
- */
-
-const GLOBAL_CODE = 0, EVAL_CODE = 1, FUNCTION_CODE = 2;
-
-function ExecutionContext(type) {
-    this.type = type;
-}
-
-var global = {
-    // Value properties.
-    NaN: NaN, Infinity: Infinity, undefined: undefined,
-
-    // Function properties.
-    eval: function eval(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 if e == THROW) {
-            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 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 Array(dummy) {
-        // Array when called as a function acts as a constructor.
-        return GLOBAL.Array.apply(this, arguments);
-    },
-    String: function String(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 load(s) {
-        if (typeof s != "string")
-            return s;
-
-        evaluate(snarf(s), s, 1)
-    },
-    print: print, version: null
-};
-
-// 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.__defineProperty__('prototype', proto, true, true, true);
-    proto.__defineProperty__('constructor', gctor, false, false, true);
-    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) {
-    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.__defineProperty__(n.name, v, true);
-            } else {
-                t = new Object;
-                x.scope = {object: t, parent: x.scope};
-                try {
-                    v = new FunctionObject(n, x.scope);
-                    t.__defineProperty__(n.name, v, true, true);
-                } 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.__defineProperty__(s, f, x.type != EVAL_CODE);
-        }
-        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.__defineProperty__(s, undefined, x.type != EVAL_CODE,
-                                     u.readOnly);
-            }
-        }
-        // FALL THROUGH
-
-      case BLOCK:
-        for (i = 0, j = n.length; i < j; i++)
-            execute(n[i], x);
-        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) {
-                            break switch_loop;
-                        }
-                    }
-                    if (++i == j)
-                        break switch_loop;
-                    t = a[i];
-                }
-                // NOT REACHED
-            }
-        }
-        break;
-
-      case FOR:
-        n.setup && getValue(execute(n.setup, x));
-        // FALL THROUGH
-      case WHILE:
-        while (!n.condition || getValue(execute(n.condition, x))) {
-            try {
-                execute(n.body, x);
-            } catch (e if e == BREAK && x.target == n) {
-                break;
-            } catch (e if e == CONTINUE && x.target == n) {
-                continue;
-            }
-            n.update && getValue(execute(n.update, x));
-        }
-        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;
-            } catch (e if e == CONTINUE && x.target == n) {
-                continue;
-            }
-        }
-        break;
-
-      case DO:
-        do {
-            try {
-                execute(n.body, x);
-            } catch (e if e == BREAK && x.target == n) {
-                break;
-            } catch (e if e == CONTINUE && x.target == n) {
-                continue;
-            }
-        } 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)) {
-            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.__defineProperty__(t.varName, e, true);
-                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.__defineProperty__(t, u, x.type != EVAL_CODE, true);
-            else
-                s.object[t] = u;
-        }
-        break;
-
-      case DEBUGGER:
-        throw "NYI: " + tokens[n.type];
-
-      case SEMICOLON:
-        if (n.expression)
-            x.result = getValue(execute(n.expression, x));
-        break;
-
-      case LABEL:
-        try {
-            execute(n.statement, x);
-        } catch (e if e == BREAK && x.target == n) {
-        }
-        break;
-
-      case COMMA:
-        for (i = 0, j = n.length; i < j; i++)
-            v = getValue(execute(n[i], x));
-        break;
-
-      case ASSIGN:
-        r = execute(n[0], x);
-        t = n[0].assignOp;
-        if (t)
-            u = getValue(r);
-        v = getValue(execute(n[1], x));
-        if (t) {
-            switch (t) {
-              case BITWISE_OR:  v = u | v; break;
-              case BITWISE_XOR: v = u ^ v; break;
-              case BITWISE_AND: v = u & v; break;
-              case LSH:         v = u << v; break;
-              case RSH:         v = u >> v; break;
-              case URSH:        v = u >>> v; break;
-              case PLUS:        v = u + v; break;
-              case MINUS:       v = u - v; break;
-              case MUL:         v = u * v; break;
-              case DIV:         v = u / v; break;
-              case MOD:         v = u % v; break;
-            }
-        }
-        putValue(r, v, n[0]);
-        break;
-
-      case HOOK:
-        v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x))
-                                       : getValue(execute(n[2], x));
-        break;
-
-      case OR:
-        v = getValue(execute(n[0], x)) || getValue(execute(n[1], x));
-        break;
-
-      case AND:
-        v = getValue(execute(n[0], x)) && getValue(execute(n[1], x));
-        break;
-
-      case BITWISE_OR:
-        v = getValue(execute(n[0], x)) | getValue(execute(n[1], x));
-        break;
-
-      case BITWISE_XOR:
-        v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x));
-        break;
-
-      case BITWISE_AND:
-        v = getValue(execute(n[0], x)) & getValue(execute(n[1], x));
-        break;
-
-      case EQ:
-        v = getValue(execute(n[0], x)) == getValue(execute(n[1], x));
-        break;
-
-      case NE:
-        v = getValue(execute(n[0], x)) != getValue(execute(n[1], x));
-        break;
-
-      case STRICT_EQ:
-        v = getValue(execute(n[0], x)) === getValue(execute(n[1], x));
-        break;
-
-      case STRICT_NE:
-        v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x));
-        break;
-
-      case LT:
-        v = getValue(execute(n[0], x)) < getValue(execute(n[1], x));
-        break;
-
-      case LE:
-        v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x));
-        break;
-
-      case GE:
-        v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x));
-        break;
-
-      case GT:
-        v = getValue(execute(n[0], x)) > getValue(execute(n[1], x));
-        break;
-
-      case IN:
-        v = getValue(execute(n[0], x)) in getValue(execute(n[1], x));
-        break;
-
-      case INSTANCEOF:
-        t = getValue(execute(n[0], x));
-        u = getValue(execute(n[1], x));
-        if (isObject(u) && typeof u.__hasInstance__ == "function")
-            v = u.__hasInstance__(t);
-        else
-            v = t instanceof u;
-        break;
-
-      case LSH:
-        v = getValue(execute(n[0], x)) << getValue(execute(n[1], x));
-        break;
-
-      case RSH:
-        v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x));
-        break;
-
-      case URSH:
-        v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x));
-        break;
-
-      case PLUS:
-        v = getValue(execute(n[0], x)) + getValue(execute(n[1], x));
-        break;
-
-      case MINUS:
-        v = getValue(execute(n[0], x)) - getValue(execute(n[1], x));
-        break;
-
-      case MUL:
-        v = getValue(execute(n[0], x)) * getValue(execute(n[1], x));
-        break;
-
-      case DIV:
-        v = getValue(execute(n[0], x)) / getValue(execute(n[1], x));
-        break;
-
-      case MOD:
-        v = getValue(execute(n[0], x)) % getValue(execute(n[1], x));
-        break;
-
-      case DELETE:
-        t = execute(n[0], x);
-        v = !(t instanceof Reference) || delete t.base[t.propertyName];
-        break;
-
-      case VOID:
-        getValue(execute(n[0], x));
-        break;
-
-      case TYPEOF:
-        t = execute(n[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));
-        break;
-
-      case BITWISE_NOT:
-        v = ~getValue(execute(n[0], x));
-        break;
-
-      case UNARY_PLUS:
-        v = +getValue(execute(n[0], x));
-        break;
-
-      case UNARY_MINUS:
-        v = -getValue(execute(n[0], x));
-        break;
-
-      case INCREMENT:
-      case DECREMENT:
-        t = execute(n[0], x);
-        u = Number(getValue(t));
-        if (n.postfix)
-            v = u;
-        putValue(t, (n.type == INCREMENT) ? ++u : --u, n[0]);
-        if (!n.postfix)
-            v = u;
-        break;
-
-      case DOT:
-        r = execute(n[0], x);
-        t = getValue(r);
-        u = n[1].value;
-        v = new Reference(toObject(t, r, n[0]), u, n);
-        break;
-
-      case INDEX:
-        r = execute(n[0], x);
-        t = getValue(r);
-        u = getValue(execute(n[1], x));
-        v = new Reference(toObject(t, r, n[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));
-            v.__defineProperty__(i, u, false, false, true);
-        }
-        v.__defineProperty__('length', i, false, false, true);
-        break;
-
-      case CALL:
-        r = execute(n[0], x);
-        a = execute(n[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);
-        }
-        t = (r instanceof Reference) ? r.base : null;
-        if (t instanceof Activation)
-            t = null;
-        v = f.__call__(t, a, x);
-        break;
-
-      case NEW:
-      case NEW_WITH_ARGS:
-        r = execute(n[0], x);
-        f = getValue(r);
-        if (n.type == NEW) {
-            a = {};
-            a.__defineProperty__('length', 0, false, false, true);
-        } else {
-            a = execute(n[1], x);
-        }
-        if (isPrimitive(f) || typeof f.__construct__ != "function") {
-            throw new TypeError(r + " is not a constructor",
-                                n[0].filename, n[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));
-        }
-        v.length = j;
-        break;
-
-      case OBJECT_INIT:
-        v = {};
-        for (i = 0, j = n.length; i < j; i++) {
-            t = n[i];
-            if (t.type == PROPERTY_INIT) {
-                v[t[0].value] = getValue(execute(t[1], x));
-            } else {
-                f = new FunctionObject(t, x.scope);
-                u = (t.type == GETTER) ? '__defineGetter__'
-                                       : '__defineSetter__';
-                v[u](t.name, thunk(f, x));
-            }
-        }
-        break;
-
-      case NULL:
-        v = null;
-        break;
-
-      case THIS:
-        v = x.thisObject;
-        break;
-
-      case TRUE:
-        v = true;
-        break;
-
-      case FALSE:
-        v = false;
-        break;
-
-      case IDENTIFIER:
-        for (s = x.scope; s; s = s.parent) {
-            if (n.value in s.object)
-                break;
-        }
-        v = new Reference(s && s.object, n.value, n);
-        break;
-
-      case NUMBER:
-      case STRING:
-      case REGEXP:
-        v = n.value;
-        break;
-
-      case GROUP:
-        v = execute(n[0], x);
-        break;
-
-      default:
-        throw "PANIC: unknown operation " + n.type + ": " + uneval(n);
-    }
-
-    return v;
-}
-
-function Activation(f, a) {
-    for (var i = 0, j = f.params.length; i < j; i++)
-        this.__defineProperty__(f.params[i], a[i], true);
-    this.__defineProperty__('arguments', a, true);
-}
-
-// Null Activation.prototype's proto slot so that Object.prototype.* does not
-// pollute the scope of heavyweight functions.  Also delete its 'constructor'
-// property so that it doesn't pollute function scopes.  But first, we must
-// copy __defineProperty__ down from Object.prototype.
-
-Activation.prototype.__defineProperty__ = Object.prototype.__defineProperty__;
-Activation.prototype.__proto__ = null;
-delete Activation.prototype.constructor;
-
-function FunctionObject(node, scope) {
-    this.node = node;
-    this.scope = scope;
-    this.__defineProperty__('length', node.params.length, true, true, true);
-    var proto = {};
-    this.__defineProperty__('prototype', proto, true);
-    proto.__defineProperty__('constructor', this, false, false, true);
-}
-
-var FOp = FunctionObject.prototype = {
-    // Internal methods.
-    __call__: function (t, a, x) {
-        var x2 = new ExecutionContext(FUNCTION_CODE);
-        x2.thisObject = t || global;
-        x2.caller = x;
-        x2.callee = this;
-        a.__defineProperty__('callee', this, false, false, true);
-        var f = this.node;
-        x2.scope = {object: new Activation(f, a), parent: this.scope};
-
-        ExecutionContext.current = x2;
-        try {
-            execute(f.body, x2);
-        } catch (e if e == RETURN) {
-            return x2.result;
-        } catch (e if e == THROW) {
-            x.result = x2.result;
-            throw THROW;
-        } finally {
-            ExecutionContext.current = x;
-        }
-        return undefined;
-    },
-
-    __construct__: function (a, x) {
-        var o = new Object;
-        var p = this.prototype;
-        if (isObject(p))
-            o.__proto__ = p;
-        // else o.__proto__ defaulted to Object.prototype
-
-        var v = this.__call__(o, a, x);
-        if (isObject(v))
-            return v;
-        return o;
-    },
-
-    __hasInstance__: function (v) {
-        if (isPrimitive(v))
-            return false;
-        var p = this.prototype;
-        if (isPrimitive(p)) {
-            throw new TypeError("'prototype' property is not an object",
-                                this.node.filename, this.node.lineno);
-        }
-        var o;
-        while ((o = v.__proto__)) {
-            if (o == p)
-                return true;
-            v = o;
-        }
-        return false;
-    },
-
-    // Standard methods.
-    toString: function () {
-        return this.node.getSource();
-    },
-
-    apply: function (t, a) {
-        // Curse ECMA again!
-        if (typeof this.__call__ != "function") {
-            throw new TypeError("Function.prototype.apply called on" +
-                                " uncallable object");
-        }
-
-        if (t === undefined || t === null)
-            t = global;
-        else if (typeof t != "object")
-            t = toObject(t, t);
-
-        if (a === undefined || a === null) {
-            a = {};
-            a.__defineProperty__('length', 0, false, false, true);
-        } else if (a instanceof Array) {
-            var v = {};
-            for (var i = 0, j = a.length; i < j; i++)
-                v.__defineProperty__(i, a[i], false, false, true);
-            v.__defineProperty__('length', i, false, false, true);
-            a = v;
-        } else if (!(a instanceof Object)) {
-            // XXX check for a non-arguments object
-            throw new TypeError("Second argument to Function.prototype.apply" +
-                                " must be an array or arguments object",
-                                this.node.filename, this.node.lineno);
-        }
-
-        return this.__call__(t, a, ExecutionContext.current);
-    },
-
-    call: function (t) {
-        // Curse ECMA a third time!
-        var a = Array.prototype.splice.call(arguments, 1);
-        return this.apply(t, a);
-    }
-};
-
-// Connect Function.prototype and Function.prototype.constructor in global.
-reflectClass('Function', FOp);
-
-// Help native and host-scripted functions be like FunctionObjects.
-var Fp = Function.prototype;
-var REp = RegExp.prototype;
-
-if (!('__call__' in Fp)) {
-    Fp.__defineProperty__('__call__', function (t, a, x) {
-        // Curse ECMA yet again!
-        a = Array.prototype.splice.call(a, 0, a.length);
-        return this.apply(t, a);
-    }, true, true, true);
-
-    REp.__defineProperty__('__call__', function (t, a, x) {
-        a = Array.prototype.splice.call(a, 0, a.length);
-        return this.exec.apply(this, a);
-    }, true, true, true);
-
-    Fp.__defineProperty__('__construct__', function (a, x) {
-        a = Array.prototype.splice.call(a, 0, a.length);
-        return this.__applyConstructor__(a);
-    }, true, true, true);
-
-    // Since we use native functions such as Date along with host ones such
-    // as global.eval, we want both to be considered instances of the native
-    // Function constructor.
-    Fp.__defineProperty__('__hasInstance__', function (v) {
-        return v instanceof Function || v instanceof global.Function;
-    }, true, true, true);
-}
-
-function thunk(f, x) {
-    return function () { return f.__call__(this, arguments, x); };
-}
-
-function evaluate(s, f, l) {
-    if (typeof s != "string")
-        return s;
-
-    var x = ExecutionContext.current;
-    var x2 = new ExecutionContext(GLOBAL_CODE);
-    ExecutionContext.current = x2;
-    try {
-        execute(parse(s, f, l), x2);
-    } catch (e if e == THROW) {
-        if (x) {
-            x.result = x2.result;
-            throw THROW;
-        }
-        throw x2.result;
-    } finally {
-        ExecutionContext.current = x;
-    }
-    return x2.result;
-}
--- a/jsparse.js	Mon Jan 05 16:04:40 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1020 +0,0 @@
-/* vim: set sw=4 ts=8 et tw=78: */
-/* ***** 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 <brendan@mozilla.org>.
- * 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.
- *
- * Lexical scanner and parser.
- */
-
-// Build a regexp that recognizes operators and punctuators (except newline).
-var opRegExpSrc = "^";
-for (i in opTypeNames) {
-    if (i == '\n')
-        continue;
-    if (opRegExpSrc != "^")
-        opRegExpSrc += "|^";
-    opRegExpSrc += i.replace(/[?|^&(){}\[\]+\-*\/\.]/g, "\\$&");
-}
-var opRegExp = new RegExp(opRegExpSrc);
-
-// A regexp to match floating point literals (but not integer literals).
-var fpRegExp = /^\d+\.\d*(?:[eE][-+]?\d+)?|^\d+(?:\.\d*)?[eE][-+]?\d+|^\.\d+(?:[eE][-+]?\d+)?/;
-
-// A regexp to match regexp literals.
-var reRegExp = /^\/((?:\\.|\[(?:\\.|[^\]])*\]|[^\/])+)\/([gimy]*)/;
-
-function Tokenizer(s, f, l) {
-    this.cursor = 0;
-    this.source = String(s);
-    this.tokens = [];
-    this.tokenIndex = 0;
-    this.lookahead = 0;
-    this.scanNewlines = false;
-    this.scanOperand = true;
-    this.filename = f || "";
-    this.lineno = l || 1;
-    this.comments = [];
-}
-
-Tokenizer.prototype = {
-    get input() {
-        return this.source.substring(this.cursor);
-    },
-
-    get done() {
-        return this.peek() == END;
-    },
-
-    get token() {
-        return this.tokens[this.tokenIndex];
-    },
-
-    match: function (tt) {
-        return this.get() == tt || this.unget();
-    },
-
-    mustMatch: function (tt) {
-        if (!this.match(tt))
-            throw this.newSyntaxError("Missing " + tokens[tt].toLowerCase());
-        return this.token;
-    },
-
-    peek: function () {
-        var tt, next;
-        if (this.lookahead) {
-            next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
-            if (this.scanNewlines && next.lineno != this.lineno)
-                tt = NEWLINE;
-            else
-                tt = next.type;
-        } else {
-            tt = this.get();
-            this.unget();
-        }
-        return tt;
-    },
-
-    peekOnSameLine: function () {
-        this.scanNewlines = true;
-        var tt = this.peek();
-        this.scanNewlines = false;
-        return tt;
-    },
-
-    get: function () {
-        var token;
-        while (this.lookahead) {
-            --this.lookahead;
-            this.tokenIndex = (this.tokenIndex + 1) & 3;
-            token = this.tokens[this.tokenIndex];
-            if (token.type != NEWLINE || this.scanNewlines)
-                return token.type;
-        }
-
-        for (;;) {
-            var input = this.input;
-            var match = (this.scanNewlines ? /^[ \t]+/ : /^\s+/)(input);
-            if (match) {
-                var spaces = match[0];
-                this.cursor += spaces.length;
-                var newlines = spaces.match(/\n/g);
-                if (newlines)
-                    this.lineno += newlines.length;
-                input = this.input;
-            }
-
-            if (!(match = /^\/(?:\*(?:.|\n)*?\*\/|\/.*)/(input)))
-                break;
-            var comment = match[0];
-            this.comments.push({lineno: this.lineno,
-                                cursor: this.cursor,
-                                text: comment});
-            this.cursor += comment.length;
-            newlines = comment.match(/\n/g);
-            if (newlines)
-                this.lineno += newlines.length
-        }
-
-        this.tokenIndex = (this.tokenIndex + 1) & 3;
-        token = this.tokens[this.tokenIndex];
-        if (!token)
-            this.tokens[this.tokenIndex] = token = {};
-
-        if (!input)
-            return token.type = END;
-
-        if ((match = fpRegExp(input))) {
-            token.type = NUMBER;
-            token.value = parseFloat(match[0]);
-        } else if ((match = /^0[xX][\da-fA-F]+|^0[0-7]*|^\d+/(input))) {
-            token.type = NUMBER;
-            token.value = parseInt(match[0]);
-        } else if ((match = /^[$_\w]+/(input))) {       // FIXME no ES3 unicode
-            var id = match[0];
-            token.type = keywords[id] || IDENTIFIER;
-            token.value = id;
-        } else if ((match = /^"(?:\\.|[^"])*"|^'(?:\\.|[^'])*'/(input))) { //"){
-            token.type = STRING;
-            token.value = eval(match[0]);
-        } else if (this.scanOperand && (match = reRegExp(input))) {
-            token.type = REGEXP;
-            token.value = new RegExp(match[1], match[2]);
-        } else if ((match = opRegExp(input))) {
-            var op = match[0];
-            if (assignOps[op] && input[op.length] == '=') {
-                token.type = ASSIGN;
-                token.assignOp = GLOBAL[opTypeNames[op]];
-                match[0] += '=';
-            } else {
-                token.type = GLOBAL[opTypeNames[op]];
-                if (this.scanOperand &&
-                    (token.type == PLUS || token.type == MINUS)) {
-                    token.type += UNARY_PLUS - PLUS;
-                }
-                token.assignOp = null;
-            }
-            token.value = op;
-        } else if (this.scanNewlines && (match = /^\n/(input))) {
-            token.type = NEWLINE;
-        } else {
-            throw this.newSyntaxError("Illegal token");
-        }
-
-        token.start = this.cursor;
-        this.cursor += match[0].length;
-        token.end = this.cursor;
-        token.lineno = this.lineno;
-        return token.type;
-    },
-
-    unget: function () {
-        if (++this.lookahead == 4) throw "PANIC: too much lookahead!";
-        this.tokenIndex = (this.tokenIndex - 1) & 3;
-    },
-
-    newSyntaxError: function (m) {
-        var e = new SyntaxError(m, this.filename, this.lineno);
-        e.source = this.source;
-        e.cursor = this.cursor;
-        return e;
-    }
-};
-
-function CompilerContext(inFunction) {
-    this.inFunction = inFunction;
-    this.stmtStack = [];
-    this.funDecls = [];
-    this.varDecls = [];
-}
-
-var CCp = CompilerContext.prototype;
-CCp.bracketLevel = CCp.curlyLevel = CCp.parenLevel = CCp.hookLevel = 0;
-CCp.ecmaStrictMode = CCp.inForLoopInit = false;
-
-function Script(t, x) {
-    var n = Statements(t, x);
-    n.type = SCRIPT;
-    n.funDecls = x.funDecls;
-    n.varDecls = x.varDecls;
-    return n;
-}
-
-// Node extends Array, which we extend slightly with a top-of-stack method.
-Array.prototype.__defineProperty__(
-    'top',
-    function () {
-        return this.length && this[this.length-1];
-    },
-    false, false, true
-);
-
-function Node(t, type) {
-    var token = t.token;
-    if (token) {
-        this.type = type || token.type;
-        this.value = token.value;
-        this.lineno = token.lineno;
-        this.start = token.start;
-        this.end = token.end;
-    } else {
-        this.type = type;
-        this.lineno = t.lineno;
-    }
-    this.tokenizer = t;
-
-    for (var i = 2; i < arguments.length; i++)
-        this.push(arguments[i]);
-}
-
-var Np = Node.prototype = new Array;
-Np.constructor = Node;
-Np.toSource = Object.prototype.toSource;
-
-// Always use push to add operands to an expression, to update start and end.
-Np.push = function (kid) {
-    if (kid.start < this.start)
-        this.start = kid.start;
-    if (this.end < kid.end)
-        this.end = kid.end;
-    return Array.prototype.push.call(this, kid);
-}
-
-Node.indentLevel = 0;
-
-function tokenstr(tt) {
-    var t = tokens[tt];
-    return /^\W/.test(t) ? opTypeNames[t] : t.toUpperCase();
-}
-
-Np.toString = function () {
-    var a = [];
-    for (var i in this) {
-        if (this.hasOwnProperty(i) && i != 'type' && i != 'target')
-            a.push({id: i, value: this[i]});
-    }
-    a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; });
-    const INDENTATION = "    ";
-    var n = ++Node.indentLevel;
-    var s = "{\n" + INDENTATION.repeat(n) + "type: " + tokenstr(this.type);
-    for (i = 0; i < a.length; i++)
-        s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value;
-    n = --Node.indentLevel;
-    s += "\n" + INDENTATION.repeat(n) + "}";
-    return s;
-}
-
-Np.getSource = function () {
-    return this.tokenizer.source.slice(this.start, this.end);
-};
-
-Np.__defineGetter__('filename',
-                    function () { return this.tokenizer.filename; });
-
-String.prototype.__defineProperty__(
-    'repeat',
-    function (n) {
-        var s = "", t = this + s;
-        while (--n >= 0)
-            s += t;
-        return s;
-    },
-    false, false, true
-);
-
-// Statement stack and nested statement handler.
-function nest(t, x, node, func, end) {
-    x.stmtStack.push(node);
-    var n = func(t, x);
-    x.stmtStack.pop();
-    end && t.mustMatch(end);
-    return n;
-}
-
-function Statements(t, x) {
-    var n = new Node(t, BLOCK);
-    x.stmtStack.push(n);
-    while (!t.done && t.peek() != RIGHT_CURLY)
-        n.push(Statement(t, x));
-    x.stmtStack.pop();
-    return n;
-}
-
-function Block(t, x) {
-    t.mustMatch(LEFT_CURLY);
-    var n = Statements(t, x);
-    t.mustMatch(RIGHT_CURLY);
-    return n;
-}
-
-const DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2;
-
-function Statement(t, x) {
-    var i, label, n, n2, ss, tt = t.get();
-
-    // Cases for statements ending in a right curly return early, avoiding the
-    // common semicolon insertion magic after this switch.
-    switch (tt) {
-      case FUNCTION:
-        return FunctionDefinition(t, x, true,
-                                  (x.stmtStack.length > 1)
-                                  ? STATEMENT_FORM
-                                  : DECLARED_FORM);
-
-      case LEFT_CURLY:
-        n = Statements(t, x);
-        t.mustMatch(RIGHT_CURLY);
-        return n;
-
-      case IF:
-        n = new Node(t);
-        n.condition = ParenExpression(t, x);
-        x.stmtStack.push(n);
-        n.thenPart = Statement(t, x);
-        n.elsePart = t.match(ELSE) ? Statement(t, x) : null;
-        x.stmtStack.pop();
-        return n;
-
-      case SWITCH:
-        n = new Node(t);
-        t.mustMatch(LEFT_PAREN);
-        n.discriminant = Expression(t, x);
-        t.mustMatch(RIGHT_PAREN);
-        n.cases = [];
-        n.defaultIndex = -1;
-        x.stmtStack.push(n);
-        t.mustMatch(LEFT_CURLY);
-        while ((tt = t.get()) != RIGHT_CURLY) {
-            switch (tt) {
-              case DEFAULT:
-                if (n.defaultIndex >= 0)
-                    throw t.newSyntaxError("More than one switch default");
-                // FALL THROUGH
-              case CASE:
-                n2 = new Node(t);
-                if (tt == DEFAULT)
-                    n.defaultIndex = n.cases.length;
-                else
-                    n2.caseLabel = Expression(t, x, COLON);
-                break;
-              default:
-                throw t.newSyntaxError("Invalid switch case");
-            }
-            t.mustMatch(COLON);
-            n2.statements = new Node(t, BLOCK);
-            while ((tt=t.peek()) != CASE && tt != DEFAULT && tt != RIGHT_CURLY)
-                n2.statements.push(Statement(t, x));
-            n.cases.push(n2);
-        }
-        x.stmtStack.pop();
-        return n;
-
-      case FOR:
-        n = new Node(t);
-        n.isLoop = true;
-        t.mustMatch(LEFT_PAREN);
-        if ((tt = t.peek()) != SEMICOLON) {
-            x.inForLoopInit = true;
-            if (tt == VAR || tt == CONST || tt == LET) {
-                t.get();
-                n2 = Variables(t, x);
-            } else {
-                n2 = Expression(t, x);
-            }
-            x.inForLoopInit = false;
-        }
-        if (n2 && t.match(IN)) {
-            n.type = FOR_IN;
-            if (n2.type == VAR || n2.type == LET) {
-                if (n2.length != 1) {
-                    throw new SyntaxError("Invalid for..in left-hand side",
-                                          t.filename, n2.lineno);
-                }
-
-                // NB: n2[0].type == IDENTIFIER and n2[0].value == n2[0].name.
-                n.iterator = n2[0];
-                n.varDecl = n2;
-            } else {
-                n.iterator = n2;
-                n.varDecl = null;
-            }
-            n.object = Expression(t, x);
-        } else {
-            n.setup = n2 || null;
-            t.mustMatch(SEMICOLON);
-            n.condition = (t.peek() == SEMICOLON) ? null : Expression(t, x);
-            t.mustMatch(SEMICOLON);
-            n.update = (t.peek() == RIGHT_PAREN) ? null : Expression(t, x);
-        }
-        t.mustMatch(RIGHT_PAREN);
-        n.body = nest(t, x, n, Statement);
-        return n;
-
-      case WHILE:
-        n = new Node(t);
-        n.isLoop = true;
-        n.condition = ParenExpression(t, x);
-        n.body = nest(t, x, n, Statement);
-        return n;
-
-      case DO:
-        n = new Node(t);
-        n.isLoop = true;
-        n.body = nest(t, x, n, Statement, WHILE);
-        n.condition = ParenExpression(t, x);
-        if (!x.ecmaStrictMode) {
-            // <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.
-            t.match(SEMICOLON);
-            return n;
-        }
-        break;
-
-      case BREAK:
-      case CONTINUE:
-        n = new Node(t);
-        if (t.peekOnSameLine() == IDENTIFIER) {
-            t.get();
-            n.label = t.token.value;
-        }
-        ss = x.stmtStack;
-        i = ss.length;
-        label = n.label;
-        if (label) {
-            do {
-                if (--i < 0)
-                    throw t.newSyntaxError("Label not found");
-            } while (ss[i].label != label);
-        } else {
-            do {
-                if (--i < 0) {
-                    throw t.newSyntaxError("Invalid " + ((tt == BREAK)
-                                                         ? "break"
-                                                         : "continue"));
-                }
-            } while (!ss[i].isLoop && (tt != BREAK || ss[i].type != SWITCH));
-        }
-        n.target = ss[i];
-        break;
-
-      case TRY:
-        n = new Node(t);
-        n.tryBlock = Block(t, x);
-        n.catchClauses = [];
-        while (t.match(CATCH)) {
-            n2 = new Node(t);
-            t.mustMatch(LEFT_PAREN);
-            n2.varName = t.mustMatch(IDENTIFIER).value;
-            if (t.match(IF)) {
-                if (x.ecmaStrictMode)
-                    throw t.newSyntaxError("Illegal catch guard");
-                if (n.catchClauses.length && !n.catchClauses.top().guard)
-                    throw t.newSyntaxError("Guarded catch after unguarded");
-                n2.guard = Expression(t, x);
-            } else {
-                n2.guard = null;
-            }
-            t.mustMatch(RIGHT_PAREN);
-            n2.block = Block(t, x);
-            n.catchClauses.push(n2);
-        }
-        if (t.match(FINALLY))
-            n.finallyBlock = Block(t, x);
-        if (!n.catchClauses.length && !n.finallyBlock)
-            throw t.newSyntaxError("Invalid try statement");
-        return n;
-
-      case CATCH:
-      case FINALLY:
-        throw t.newSyntaxError(tokens[tt] + " without preceding try");
-
-      case THROW:
-        n = new Node(t);
-        n.exception = Expression(t, x);
-        break;
-
-      case RETURN:
-        if (!x.inFunction)
-            throw t.newSyntaxError("Invalid return");
-        n = new Node(t);
-        tt = t.peekOnSameLine();
-        if (tt != END && tt != NEWLINE && tt != SEMICOLON && tt != RIGHT_CURLY)
-            n.value = Expression(t, x);
-        break;
-
-      case WITH:
-        n = new Node(t);
-        n.object = ParenExpression(t, x);
-        n.body = nest(t, x, n, Statement);
-        return n;
-
-      case VAR:
-      case CONST:
-      case LET:
-        n = Variables(t, x);
-        break;
-
-      case DEBUGGER:
-        n = new Node(t);
-        break;
-
-      case NEWLINE:
-      case SEMICOLON:
-        n = new Node(t, SEMICOLON);
-        n.expression = null;
-        return n;
-
-      default:
-        if (tt == IDENTIFIER) {
-            t.scanOperand = false;
-            tt = t.peek();
-            t.scanOperand = true;
-            if (tt == COLON) {
-                label = t.token.value;
-                ss = x.stmtStack;
-                for (i = ss.length-1; i >= 0; --i) {
-                    if (ss[i].label == label)
-                        throw t.newSyntaxError("Duplicate label");
-                }
-                t.get();
-                n = new Node(t, LABEL);
-                n.label = label;
-                n.statement = nest(t, x, n, Statement);
-                return n;
-            }
-        }
-
-        n = new Node(t, SEMICOLON);
-        t.unget();
-        n.expression = Expression(t, x);
-        n.end = n.expression.end;
-        break;
-    }
-
-    if (t.lineno == t.token.lineno) {
-        tt = t.peekOnSameLine();
-        if (tt != END && tt != NEWLINE && tt != SEMICOLON && tt != RIGHT_CURLY)
-            throw t.newSyntaxError("Missing ; before statement");
-    }
-    t.match(SEMICOLON);
-    return n;
-}
-
-function FunctionDefinition(t, x, requireName, functionForm) {
-    var f = new Node(t);
-    if (f.type != FUNCTION)
-        f.type = (f.value == "get") ? GETTER : SETTER;
-    if (t.match(IDENTIFIER))
-        f.name = t.token.value;
-    else if (requireName)
-        throw t.newSyntaxError("Missing function identifier");
-
-    t.mustMatch(LEFT_PAREN);
-    f.params = [];
-    var tt;
-    while ((tt = t.get()) != RIGHT_PAREN) {
-        if (tt != IDENTIFIER)
-            throw t.newSyntaxError("Missing formal parameter");
-        f.params.push(t.token.value);
-        if (t.peek() != RIGHT_PAREN)
-            t.mustMatch(COMMA);
-    }
-
-    t.mustMatch(LEFT_CURLY);
-    var x2 = new CompilerContext(true);
-    f.body = Script(t, x2);
-    t.mustMatch(RIGHT_CURLY);
-    f.end = t.token.end;
-
-    f.functionForm = functionForm;
-    if (functionForm == DECLARED_FORM)
-        x.funDecls.push(f);
-    return f;
-}
-
-function Variables(t, x) {
-    var n = new Node(t);
-    do {
-        t.mustMatch(IDENTIFIER);
-        var n2 = new Node(t);
-        n2.name = n2.value;
-        if (t.match(ASSIGN)) {
-            if (t.token.assignOp)
-                throw t.newSyntaxError("Invalid variable initialization");
-            n2.initializer = Expression(t, x, COMMA);
-        }
-        n2.readOnly = (n.type == CONST);
-        n.push(n2);
-        x.varDecls.push(n2);
-    } while (t.match(COMMA));
-    return n;
-}
-
-function ParenExpression(t, x) {
-    t.mustMatch(LEFT_PAREN);
-    var n = Expression(t, x);
-    t.mustMatch(RIGHT_PAREN);
-    return n;
-}
-
-var opPrecedence = {
-    SEMICOLON: 0,
-    COMMA: 1,
-    ASSIGN: 2, HOOK: 2, COLON: 2,
-    // The above all have to have the same precedence, see bug 330975.
-    OR: 4,
-    AND: 5,
-    BITWISE_OR: 6,
-    BITWISE_XOR: 7,
-    BITWISE_AND: 8,
-    EQ: 9, NE: 9, STRICT_EQ: 9, STRICT_NE: 9,
-    LT: 10, LE: 10, GE: 10, GT: 10, IN: 10, INSTANCEOF: 10,
-    LSH: 11, RSH: 11, URSH: 11,
-    PLUS: 12, MINUS: 12,
-    MUL: 13, DIV: 13, MOD: 13,
-    DELETE: 14, VOID: 14, TYPEOF: 14, // PRE_INCREMENT: 14, PRE_DECREMENT: 14,
-    NOT: 14, BITWISE_NOT: 14, UNARY_PLUS: 14, UNARY_MINUS: 14,
-    INCREMENT: 15, DECREMENT: 15,     // postfix
-    NEW: 16,
-    DOT: 17
-};
-
-// Map operator type code to precedence.
-for (i in opPrecedence)
-    opPrecedence[GLOBAL[i]] = opPrecedence[i];
-
-var opArity = {
-    COMMA: -2,
-    ASSIGN: 2,
-    HOOK: 3,
-    OR: 2,
-    AND: 2,
-    BITWISE_OR: 2,
-    BITWISE_XOR: 2,
-    BITWISE_AND: 2,
-    EQ: 2, NE: 2, STRICT_EQ: 2, STRICT_NE: 2,
-    LT: 2, LE: 2, GE: 2, GT: 2, IN: 2, INSTANCEOF: 2,
-    LSH: 2, RSH: 2, URSH: 2,
-    PLUS: 2, MINUS: 2,
-    MUL: 2, DIV: 2, MOD: 2,
-    DELETE: 1, VOID: 1, TYPEOF: 1,  // PRE_INCREMENT: 1, PRE_DECREMENT: 1,
-    NOT: 1, BITWISE_NOT: 1, UNARY_PLUS: 1, UNARY_MINUS: 1,
-    INCREMENT: 1, DECREMENT: 1,     // postfix
-    NEW: 1, NEW_WITH_ARGS: 2, DOT: 2, INDEX: 2, CALL: 2,
-    ARRAY_INIT: 1, OBJECT_INIT: 1, GROUP: 1
-};
-
-// Map operator type code to arity.
-for (i in opArity)
-    opArity[GLOBAL[i]] = opArity[i];
-
-function Expression(t, x, stop) {
-    var n, id, tt, operators = [], operands = [];
-    var bl = x.bracketLevel, cl = x.curlyLevel, pl = x.parenLevel,
-        hl = x.hookLevel;
-
-    function reduce() {
-        var n = operators.pop();
-        var op = n.type;
-        var arity = opArity[op];
-        if (arity == -2) {
-            // Flatten left-associative trees.
-            var left = operands.length >= 2 && operands[operands.length-2];
-            if (left.type == op) {
-                var right = operands.pop();
-                left.push(right);
-                return left;
-            }
-            arity = 2;
-        }
-
-        // Always use push to add operands to n, to update start and end.
-        var a = operands.splice(operands.length - arity);
-        for (var i = 0; i < arity; i++)
-            n.push(a[i]);
-
-        // Include closing bracket or postfix operator in [start,end).
-        if (n.end < t.token.end)
-            n.end = t.token.end;
-
-        operands.push(n);
-        return n;
-    }
-
-loop:
-    while ((tt = t.get()) != END) {
-        if (tt == stop &&
-            x.bracketLevel == bl && x.curlyLevel == cl && x.parenLevel == pl &&
-            x.hookLevel == hl) {
-            // Stop only if tt matches the optional stop parameter, and that
-            // token is not quoted by some kind of bracket.
-            break;
-        }
-        switch (tt) {
-          case SEMICOLON:
-            // NB: cannot be empty, Statement handled that.
-            break loop;
-
-          case ASSIGN:
-          case HOOK:
-          case COLON:
-            if (t.scanOperand)
-                break loop;
-            // Use >, not >=, for right-associative ASSIGN and HOOK/COLON.
-            while (opPrecedence[operators.top().type] > opPrecedence[tt] ||
-                   (tt == COLON && operators.top().type == ASSIGN)) {
-                reduce();
-            }
-            if (tt == COLON) {
-                n = operators.top();
-                if (n.type != HOOK)
-                    throw t.newSyntaxError("Invalid label");
-                --x.hookLevel;
-            } else {
-                operators.push(new Node(t));
-                if (tt == ASSIGN)
-                    operands.top().assignOp = t.token.assignOp;
-                else
-                    ++x.hookLevel;      // tt == HOOK
-            }
-            t.scanOperand = true;
-            break;
-
-          case IN:
-            // An in operator should not be parsed if we're parsing the head of
-            // a for (...) loop, unless it is in the then part of a conditional
-            // expression, or parenthesized somehow.
-            if (x.inForLoopInit && !x.hookLevel &&
-                !x.bracketLevel && !x.curlyLevel && !x.parenLevel) {
-                break loop;
-            }
-            // FALL THROUGH
-          case COMMA:
-            // Treat comma as left-associative so reduce can fold left-heavy
-            // COMMA trees into a single array.
-            // FALL THROUGH
-          case OR:
-          case AND:
-          case BITWISE_OR:
-          case BITWISE_XOR:
-          case BITWISE_AND:
-          case EQ: case NE: case STRICT_EQ: case STRICT_NE:
-          case LT: case LE: case GE: case GT:
-          case INSTANCEOF:
-          case LSH: case RSH: case URSH:
-          case PLUS: case MINUS:
-          case MUL: case DIV: case MOD:
-          case DOT:
-            if (t.scanOperand)
-                break loop;
-            while (opPrecedence[operators.top().type] >= opPrecedence[tt])
-                reduce();
-            if (tt == DOT) {
-                t.mustMatch(IDENTIFIER);
-                operands.push(new Node(t, DOT, operands.pop(), new Node(t)));
-            } else {
-                operators.push(new Node(t));
-                t.scanOperand = true;
-            }
-            break;
-
-          case DELETE: case VOID: case TYPEOF:
-          case NOT: case BITWISE_NOT: case UNARY_PLUS: case UNARY_MINUS:
-          case NEW:
-            if (!t.scanOperand)
-                break loop;
-            operators.push(new Node(t));
-            break;
-
-          case INCREMENT: case DECREMENT:
-            if (t.scanOperand) {
-                operators.push(new Node(t));  // prefix increment or decrement
-            } else {
-                // Don't cross a line boundary for postfix {in,de}crement.
-                if (t.tokens[(t.tokenIndex + t.lookahead - 1) & 3].lineno !=
-                    t.lineno) {
-                    break loop;
-                }
-
-                // Use >, not >=, so postfix has higher precedence than prefix.
-                while (opPrecedence[operators.top().type] > opPrecedence[tt])
-                    reduce();
-                n = new Node(t, tt, operands.pop());
-                n.postfix = true;
-                operands.push(n);
-            }
-            break;
-
-          case FUNCTION:
-            if (!t.scanOperand)
-                break loop;
-            operands.push(FunctionDefinition(t, x, false, EXPRESSED_FORM));
-            t.scanOperand = false;
-            break;
-
-          case NULL: case THIS: case TRUE: case FALSE:
-          case IDENTIFIER: case NUMBER: case STRING: case REGEXP:
-            if (!t.scanOperand)
-                break loop;
-            operands.push(new Node(t));
-            t.scanOperand = false;
-            break;
-
-          case LEFT_BRACKET:
-            if (t.scanOperand) {
-                // Array initialiser.  Parse using recursive descent, as the
-                // sub-grammar here is not an operator grammar.
-                n = new Node(t, ARRAY_INIT);
-                while ((tt = t.peek()) != RIGHT_BRACKET) {
-                    if (tt == COMMA) {
-                        t.get();
-                        n.push(null);
-                        continue;
-                    }
-                    n.push(Expression(t, x, COMMA));
-                    if (!t.match(COMMA))
-                        break;
-                }
-                t.mustMatch(RIGHT_BRACKET);
-                operands.push(n);
-                t.scanOperand = false;
-            } else {
-                // Property indexing operator.
-                operators.push(new Node(t, INDEX));
-                t.scanOperand = true;
-                ++x.bracketLevel;
-            }
-            break;
-
-          case RIGHT_BRACKET:
-            if (t.scanOperand || x.bracketLevel == bl)
-                break loop;
-            while (reduce().type != INDEX)
-                continue;
-            --x.bracketLevel;
-            break;
-
-          case LEFT_CURLY:
-            if (!t.scanOperand)
-                break loop;
-            // Object initialiser.  As for array initialisers (see above),
-            // parse using recursive descent.
-            ++x.curlyLevel;
-            n = new Node(t, OBJECT_INIT);
-          object_init:
-            if (!t.match(RIGHT_CURLY)) {
-                do {
-                    tt = t.get();
-                    if ((t.token.value == "get" || t.token.value == "set") &&
-                        t.peek() == IDENTIFIER) {
-                        if (x.ecmaStrictMode)
-                            throw t.newSyntaxError("Illegal property accessor");
-                        n.push(FunctionDefinition(t, x, true, EXPRESSED_FORM));
-                    } else {
-                        switch (tt) {
-                          case IDENTIFIER:
-                          case NUMBER:
-                          case STRING:
-                            id = new Node(t);
-                            break;
-                          case RIGHT_CURLY:
-                            if (x.ecmaStrictMode)
-                                throw t.newSyntaxError("Illegal trailing ,");
-                            break object_init;
-                          default:
-                            throw t.newSyntaxError("Invalid property name");
-                        }
-                        t.mustMatch(COLON);
-                        n.push(new Node(t, PROPERTY_INIT, id,
-                                        Expression(t, x, COMMA)));
-                    }
-                } while (t.match(COMMA));
-                t.mustMatch(RIGHT_CURLY);
-            }
-            operands.push(n);
-            t.scanOperand = false;
-            --x.curlyLevel;
-            break;
-
-          case RIGHT_CURLY:
-            if (!t.scanOperand && x.curlyLevel != cl)
-                throw "PANIC: right curly botch";
-            break loop;
-
-          case LEFT_PAREN:
-            if (t.scanOperand) {
-                operators.push(new Node(t, GROUP));
-            } else {
-                while (opPrecedence[operators.top().type] > opPrecedence[NEW])
-                    reduce();
-
-                // Handle () now, to regularize the n-ary case for n > 0.
-                // We must set scanOperand in case there are arguments and
-                // the first one is a regexp or unary+/-.
-                n = operators.top();
-                t.scanOperand = true;
-                if (t.match(RIGHT_PAREN)) {
-                    if (n.type == NEW) {
-                        --operators.length;
-                        n.push(operands.pop());
-                    } else {
-                        n = new Node(t, CALL, operands.pop(),
-                                     new Node(t, LIST));
-                    }
-                    operands.push(n);
-                    t.scanOperand = false;
-                    break;
-                }
-                if (n.type == NEW)
-                    n.type = NEW_WITH_ARGS;
-                else
-                    operators.push(new Node(t, CALL));
-            }
-            ++x.parenLevel;
-            break;
-
-          case RIGHT_PAREN:
-            if (t.scanOperand || x.parenLevel == pl)
-                break loop;
-            while ((tt = reduce().type) != GROUP && tt != CALL &&
-                   tt != NEW_WITH_ARGS) {
-                continue;
-            }
-            if (tt != GROUP) {
-                n = operands.top();
-                if (n[1].type != COMMA)
-                    n[1] = new Node(t, LIST, n[1]);
-                else
-                    n[1].type = LIST;
-            }
-            --x.parenLevel;
-            break;
-
-          // Automatic semicolon insertion means we may scan across a newline
-          // and into the beginning of another statement.  If so, break out of
-          // the while loop and let the t.scanOperand logic handle errors.
-          default:
-            break loop;
-        }
-    }
-
-    if (x.hookLevel != hl)
-        throw t.newSyntaxError("Missing : after ?");
-    if (x.parenLevel != pl)
-        throw t.newSyntaxError("Missing ) in parenthetical");
-    if (x.bracketLevel != bl)
-        throw t.newSyntaxError("Missing ] in index expression");
-    if (t.scanOperand)
-        throw t.newSyntaxError("Missing operand");
-
-    // Resume default mode, scanning for operands, not operators.
-    t.scanOperand = true;
-    t.unget();
-    while (operators.length)
-        reduce();
-    return operands.pop();
-}
-
-function parse(s, f, l) {
-    var t = new Tokenizer(s, f, l);
-    var x = new CompilerContext(false);
-    var n = Script(t, x);
-    if (!t.done)
-        throw t.newSyntaxError("Syntax error");
-    return n;
-}
--- a/thingy.html	Mon Jan 05 16:04:40 2009 -0800
+++ b/thingy.html	Mon Jan 05 16:44:08 2009 -0800
@@ -8,17 +8,7 @@
 <body>
 <div id="content"></div>
 </body>
-<script>
-// Hack found at:
-// http://www.nabble.com/Re%3A-__defineProperty__-by-default-in-SpiderMonkey-p2836854.html
-
-Object.prototype.__defineProperty__ = function(property, value) {
-        this[property] = value;
-}
-</script>
 <script src="jquery-1.2.6.min.js"></script>
-<script src="jsdefs.js"></script>
-<script src="jsparse.js"></script>
 <script src="wikicreole.js"></script>
 <script src="thingy.js"></script>
 </html>
--- a/thingy.js	Mon Jan 05 16:04:40 2009 -0800
+++ b/thingy.js	Mon Jan 05 16:44:08 2009 -0800
@@ -7,18 +7,18 @@
 };
 
 App.processCode = function processCode(code) {
-  var statements = parse(code, App.FILENAME, 1);
+  var lines = code.split('\n');
   var block = "";
 
   jQuery.each(
-    statements.tokenizer.comments,
+    lines,
     function(i) {
-      var comment = this;
-      var startIndex = comment.text.indexOf("//");
+      var line = this;
+      var startIndex = line.indexOf("//");
       if (startIndex == -1)
         // This is a /* */-style comment, skip it.
         return;
-      var text = comment.text.slice(startIndex + 3);
+      var text = line.slice(startIndex + 3);
       block += text + "\n";
     });