Commit graph

1458 commits

Author SHA1 Message Date
Stephan Unverwerth
07f838dc4e LibJS: Implement automatic semicolon insertion 2020-04-17 15:22:31 +02:00
Andreas Kling
72df9c7417 LibJS: Dump a JavaScript backtrace when throwing exceptions 2020-04-16 20:23:03 +02:00
Kesse Jones
b0b204822f LibJS: Add String.prototype.substring 2020-04-16 18:47:24 +02:00
Andreas Kling
60d1ef6af4 LibJS: Remove no-op code in ScriptFunction constructor 2020-04-16 16:58:44 +02:00
Kesse Jones
7725b1970e LibJS: Add String.prototype.concat 2020-04-16 16:36:51 +02:00
Andreas Kling
e72a537033 LibJS: Make Value::m_type default to Type::Empty
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.
2020-04-16 16:11:11 +02:00
Andreas Kling
1b391d78ae LibJS: Allow cells to mark null pointers
This simplifies the cell visiting functions by letting them not worry
about the pointers they pass to the visitor being null.
2020-04-16 16:10:38 +02:00
Andreas Kling
13865c7c3d LibJS: Remove unreachable code in Interpreter::enter_scope()
Functions are handled and short-circuited at the head of enter_scope().
2020-04-16 10:25:00 +02:00
Andreas Kling
9b9086dcf0 LibJS: Oops, fix StringPrototype build 2020-04-16 10:24:32 +02:00
Andreas Kling
1108dd1659 LibJS: Add some missing |this| checks in StringPrototype
Also some style tweaks
2020-04-16 10:04:21 +02:00
Linus Groh
640a24dce8 LibJS: Remove outdated FIXME now that we have lexical environments 2020-04-16 09:41:07 +02:00
Andreas Kling
54c95d44ce LibJS: Functions with no variables don't need to create environment
Just hand out the parent environment instead.
2020-04-15 22:17:17 +02:00
Andreas Kling
ed80952cb6 LibJS: Introduce LexicalEnvironment
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!
2020-04-15 22:07:20 +02:00
Linus Groh
cea950fd70 LibJS: Support empty values in array expression 2020-04-15 21:23:06 +02:00
Linus Groh
d30db07048 LibJS: Implement void operator 2020-04-15 19:12:51 +02:00
Andreas Kling
beda751d33 LibJS: Math.round() should call round() instead of roundf()
Neither LibM functions are very strong right now, but let's at least
call the right one.
2020-04-15 19:12:10 +02:00
Linus Groh
a8406aa117 LibJS: Check length property of Array.prototype.join in its test
I assume this was copied from the Array.prototype.push() test :^)
2020-04-15 12:20:08 +02:00
Andreas Kling
ad2aac5fde LibJS: Add Array.prototype.join()
And share the code with Array.prototype.toString() :^)
2020-04-15 10:06:01 +02:00
Andreas Kling
fa30355194 LibJS: Adding two values should convert them to primitives first 2020-04-15 09:48:25 +02:00
Andreas Kling
63499c2c9f LibJS: Pass the Interpreter& to binary/logical/unary helpers 2020-04-15 09:28:41 +02:00
Kesse Jones
994f1a79ad
LibJS: Add String.prototype.{trim, trimStart, trimEnd} (#1792) 2020-04-15 08:47:40 +02:00
Linus Groh
1dee4d0049 LibJS: Redirect stderr to /dev/null when running js in run-tests
This "mutes" output from dbg() calls - which is not an issue inside
serenity itself but if the script is run on the host machine and stdout
and stderr are displayed in the same terminal window.
2020-04-14 18:38:55 +02:00
Linus Groh
823fb9d9aa LibJS: Add missing load("test-common.js") to comments-basic.js
This fixes the test which is currently failing with
"ReferenceError: 'assert' not known".
2020-04-14 17:26:57 +02:00
Linus Groh
f7df521073 LibJS: Add Array.prototype.map() 2020-04-14 13:40:04 +02:00
Linus Groh
f03d005bc4 LibJS: Add Array.prototype.filter() 2020-04-14 13:40:04 +02:00
Linus Groh
866172a721 LibJS: Add Array.prototype.forEach() 2020-04-14 13:40:04 +02:00
Linus Groh
29253bf932 LibJS: Add Array.prototype.unshift() 2020-04-14 13:40:04 +02:00
Linus Groh
5da1a40ccf LibJS: Support multiple arguments in Array.prototype.push() 2020-04-14 13:40:04 +02:00
Linus Groh
9fab52a390 LibJS: Remove shift, pop, push functions from Array object
This abstraction isn't really that useful, as we can access the
underlying Vector<Value> using elements() and operate on it directly.
2020-04-14 13:40:04 +02:00
Brian Gianforcaro
d74ad81402 js/LibJS: Move test functions to pure javascript.
The addition of assert functions to Userland/js
was done before we had load(..) implemented. Now
that it exists, it seems like the right move the
test helper functions to pure javascript instead
of poluting js with random global functions.
2020-04-14 12:55:31 +02:00
Stephan Unverwerth
9477efe970 LibJS: Handle HTML-style comments 2020-04-14 12:54:09 +02:00
Andreas Kling
8249280500 LibJS: Use HashMap::ensure_capacity() in enter_scope()
Preallocate some space in the scope variable map. This avoids a bunch
of incremental rehashing in the common case.
2020-04-13 17:27:25 +02:00
Stephan Unverwerth
8f82f6c574 LibJS: Add more number test cases for #1680 2020-04-13 17:23:22 +02:00
Andreas Kling
062d6af16e LibJS: Remove Interpreter::declare_variable()
Since declarations are now hoisted and handled on scope entry, the job
of a VariableDeclaration becomes to actually initialize variables.

As such, we can remove the part where we insert variables into the
nearest relevant scope. Less work == more speed! :^)
2020-04-13 17:22:24 +02:00
Andreas Kling
ac7459cb40 LibJS: Hoist variable declarations to the nearest relevant scope
"var" declarations are hoisted to the nearest function scope, while
"let" and "const" are hoisted to the nearest block scope.

This is done by the parser, which keeps two scope stacks, one stack
for the current var scope and one for the current let/const scope.

When the interpreter enters a scope, we walk all of the declarations
and insert them into the variable environment.

We don't support the temporal dead zone for let/const yet.
2020-04-13 17:22:23 +02:00
Linus Groh
b9415dc0e9 LibJS: Use assertNotReached() in tests 2020-04-13 16:28:50 +02:00
Linus Groh
92a9fe0e49 LibJS: Fix test files indentation (4 spaces) 2020-04-13 16:28:50 +02:00
Brian Gianforcaro
2a65db7c12
LibJS: Implement Error.prototype.name setter (#1776)
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.
2020-04-13 11:19:53 +02:00
Stephan Unverwerth
984c290ec0 LibJS: Do not execute scripts with parse errors
This adds missing checks in several LibJS consumers.
2020-04-13 10:42:25 +02:00
Stephan Unverwerth
bbd592cb6c LibJS: Tweak FunctionPrototype::to_string and constructors
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.
2020-04-13 01:14:21 +02:00
Brian Gianforcaro
0d41e542b7 LibJS: Throw on assignment of an const variable
Was stubbed out as an assert, should be handled with a runtime exception.
2020-04-13 01:12:31 +02:00
Stephan Unverwerth
f8f65053bd LibJS: Parse "this" as ThisExpression 2020-04-13 00:45:25 +02:00
Andreas Kling
110ca6b0b6 LibJS: Cache a FlyString for "this" to speed up variable lookup
We were hitting strcmp() in every variable lookup to see if the lookup
was for "this". Caching a FlyString("this") turns that check into one
pointer comparison instead. :^)
2020-04-12 20:40:02 +02:00
Linus Groh
dd7796515f LibJS: Add console.{debug,info,warn,error}() 2020-04-12 18:42:42 +02:00
Linus Groh
97de93eed1 LibJS: Add js_negative_infinity()
Value(-js_infinity().as_double()) is kind of awkward.
2020-04-12 14:39:38 +02:00
Linus Groh
f226746394 LibJS: Handle Infinity in Value::to_number() 2020-04-12 14:39:38 +02:00
Andreas Kling
ff33c5b286 LibJS: Let's show a few more decimals when stringifying numeric values
I'm not sure what the correct behavior is supposed to be, but at least
this makes printing numbers show some more interesting detail for now.
2020-04-12 10:59:29 +02:00
Linus Groh
3b21c4aa56 LibJS: Add console.trace() 2020-04-11 14:10:42 +02:00
Linus Groh
eece424694 LibJS: Make Function and CallFrame aware of their function name 2020-04-11 14:10:42 +02:00
4ourbit
02c9f4c951
LibJS: Improve Object.defineProperty test 2020-04-10 23:33:02 +02:00