value and bound arguments
This allows Function objects produced by Function.prototype.bind, as well
as arrow functions to track their |this| values and bound arguments.
A MarkedValueList is basically a Vector<JS::Value> that registers with
the Heap and makes sure that the stored values don't get GC'd.
Before this change, we were unsafely keeping Vector<JS::Value> in some
places, which is out-of-reach for the live reference finding logic
since Vector puts its elements on the heap by default.
We now pass all the JavaScript tests even when running with "js -g",
which does a GC on every heap allocation.
Everyone who constructs an Object must now pass a prototype object when
applicable. There's still a fair amount of code that passes something
fetched from the Interpreter, but this brings us closer to being able
to detach prototypes from Interpreter eventually.
Let's start moving towards native JS objects taking their prototype as
a constructor argument.
This will eventually allow us to move prototypes off of Interpreter and
into GlobalObject.
This is not effectful since all constructors overwrite the type anyway,
but it seems reasonable that the default value of m_type would match
what Value() would give you.
This patch replaces the old variable lookup logic with a new one based
on lexical environments.
This brings us closer to the way JavaScript is actually specced, and
also gives us some basic support for closures.
The interpreter's call stack frames now have a pointer to the lexical
environment for that frame. Each lexical environment can have a chain
of parent environments.
Before calling a Function, we first ask it to create_environment().
This gives us a new LexicalEnvironment for that function, which has the
function's lexical parent's environment as its parent. This allows
inner functions to access variables in their outer function:
function foo() { <-- LexicalEnvironment A
var x = 1;
function() { <-- LexicalEnvironment B (parent: A)
console.log(x);
}
}
If we return the result of a function expression from a function, that
new function object will keep a reference to its parent environment,
which is how we get closures. :^)
I'm pretty sure I didn't get everything right here, but it's a pretty
good start. This is quite a bit slower than before, but also correcter!
The MDN example for creating a custom error type in javascript uses:
function CustomError(foo, message, fileName, lineNumber) {
var instance = new Error(message, fileName, lineNumber);
instance.name = 'CustomError';
instance.foo = foo;
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
return instance;
}
The name property on the Error prototype needs to be settable for
this to work properly.
The output of FunctionPrototype::to_string is now more in line
with the output in Firefox. The builtin constructors have been
extended to include their function name in the output.