Commit graph

39 commits

Author SHA1 Message Date
Linus Groh
0a329d2d70 LibJS: Make super() in catch block work
The TryStatement handler execution creates a new LexicalEnvironment
without a current function set, which we were not accounting for when
trying to get the super constructor while executing a SuperExpression.
This makes it work but isn't pretty - this needs some refactoring to be
close to the spec for that to happen.

Fixes #7045.
2021-05-11 23:31:30 +01:00
Linus Groh
c93c2dc72c LibJS: Rename RegExpLiteral m_content to m_pattern
This is what we call it elsewhere, let's be consistent.
2021-05-10 11:57:35 +01:00
FalseHonesty
bee16bb83a LibJS: Don't suppress GlobalObject variable lookup exceptions
In HackStudio's Debugger a custom GlobalObject is used to reflect
debugger variables into the JS scope by overriding GlobalObject's
get method. However, when throwing a custom error during that lookup
it was replaced with the generic "not found" js exception. This patch
makes it instead pass along the custom error.
2021-04-25 19:03:57 +02:00
Andreas Kling
3a4d42bbbb LibJS: Remove stray '%' from MemberExpression AST dump 2021-04-24 18:50:12 +02:00
Linus Groh
ebdeed087c Everywhere: Use linusg@serenityos.org for my copyright headers 2021-04-22 22:51:19 +02:00
Brian Gianforcaro
1682f0b760 Everything: Move to SPDX license identifiers in all files.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.

See: https://spdx.dev/resources/use/#identifiers

This was done with the `ambr` search and replace tool.

 ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
2021-04-22 11:22:27 +02:00
Linus Groh
726d631527 LibJS: Use references in CallExpression::compute_this_and_callee()
This has the nice side effect of giving us a decent error message for
something like undefined.foo() - another useless "ToObject on null or
undefined" gone. :^)
Also turn the various ternary operators into two separate if branches,
they don't really share that much.
2021-04-15 09:45:20 +02:00
Linus Groh
73a92c79b8 LibJS: Use reference in MemberExpression::execute()
This was basically duplicated code.
2021-04-14 22:37:12 +02:00
Linus Groh
4ee965f916 LibJS: Add set_exception() and change throw_exception() to take a reference
Sometimes we just want to set m_exception to some value we stored
previously, without really "throwing" it again - that's what
set_exception() does now. Since we have clear_exception(), it does take
a reference, i.e. you don't set_exception(nullptr). For consistency I
updated throw_exception() to do the same.
2021-04-13 15:40:52 +02:00
Linus Groh
f2abe42ecb LibJS: Update empty TryStatement result value to undefined
It's what the spec wants us to do, although I'm not sure if it has an
observable effect anywhere, as we don't expose empty values. Let's do it
anyway.
2021-04-13 15:40:52 +02:00
Linus Groh
7cbede4342 LibJS: Fix return value of TryStatement with finalizer
Previously we would always return the result of executing the finalizer,
however the spec dictates the finalizer result must only be returned for
a non-normal completion.
I added some more comments along the way, which should make it more
clear what's going on - the unwinding and exception flow isn't super
straightforward here.
2021-04-13 15:40:52 +02:00
Linus Groh
2172e51246 LibJS: Implicitly break for..in loop if the RHS result is nullish
This implements the missing step 6a of 14.7.5.6 ForIn/OfHeadEvaluation:

    a. If exprValue is undefined or null, then
        i. Return Completion { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }.

In other words, this should just do nothing instead of throwing during
the undefined to object coercion:

    for (const x in undefined);
2021-04-10 21:00:04 +02:00
Linus Groh
275da6fcc9 LibJS: Update Object::define_accessor() to take both getter and setter
This replaces the current 'function plus boolean indicating the type'
API, which makes it easier to set both getter and setter at once.
This was already possible before but required two calls of this
function, which wasn't intuitive:

    define_accessor(name, getter, true, ...);
    define_accessor(name, setter, false, ...);

Which now becomes:

    define_accessor(name, getter, setter, ...);
2021-04-10 21:00:04 +02:00
Linus Groh
ec62783af9 LibJS: Let Object::delete_property() return a bool, not Value
Just like the various define_property functions, this should return a
bool directly and let the caller deal with wrapping it in a Value, if
necessary.
2021-04-10 21:00:04 +02:00
Linus Groh
1c3eef5317 LibJS: Use MarkedValueList for internal own properties getter functions
Letting these create and return a JS::Array directly is pretty awkward
since we then need to go through the indexed properties for iteration.
Just use a MarkedValueList (i.e. Vector<Value>) for this and add a new
Array::create_from() function to turn the Vector into a returnable
Array as we did before.

This brings it a lot closer to the spec as well, which uses the
CreateArrayFromList abstract operation to do exactly this.

There's an optimization opportunity for the future here, since we know
the Vector's size we could prepare the newly created Array accordingly,
e.g. by switching to generic storage upfront if needed.
2021-04-07 09:05:01 +02:00
Linus Groh
1416027486 LibJS: Add Object::get_enumerable_own_property_names() and use it
Object::get_own_properties() is a bit unwieldy to use - especially as
StringOnly is about to no longer be the default value. The spec has an
abstract operation specifically for this (EnumerateObjectProperties),
so let's use that. No functionality change.
2021-04-05 19:30:30 +02:00
Linus Groh
afc86abe24 LibJS: Remove this_object parameter from get/put own property functions
Specifically:

- Object::get_own_properties()
- Object::put_own_property()
- Object::put_own_property_by_index()

These APIs make no sense (and are inconsistent, get_own_property()
didn't have this parameter, for example) - and as expected we were
always passing in the same object we were calling the method on anyway.
2021-04-05 19:30:30 +02:00
Linus Groh
f1fde01025 LibJS: Fix returning from try statement
Not sure if this regressed at some point or just never worked, it
definitely wasn't tested at all. We would always return undefined when
returning from a try statement block, handler, or finalizer.
2021-04-03 16:34:34 +02:00
Linus Groh
d6cffb82a2 LibJS: Move 'typeof' string functionality from AST to Value
We should be able to get the 'typeof' string for any value directly, so
this is now a standalone Value::typeof() method instead of being part of
UnaryExpression::execute().
2021-04-02 22:24:30 +02:00
Andreas Kling
0255c8d976 Only apply auto-naming of function expressions based on syntax
The auto naming of function expressions is a purely syntactic
decision, so shouldn't be decided based on the dynamic type of
an assignment. This moves the decision making into the parser.

One icky hack is that we add a field to FunctionExpression to
indicate whether we can autoname. The real solution is to actually
generate a CompoundExpression node so that the parser can make
the correct decision, however this would have a potentially
significant run time cost.

This does not correct the behaviour for class expressions.

Patch from Anonymous.
2021-03-22 12:44:07 +01:00
Andreas Kling
c8382c32e9 LibJS: Split Value::Type::Number into Int32 and Double
We now store 32-bit integers as 32-bit integers directly which avoids
having to convert them from doubles when they're only used as 32-bit
integers anyway. :^)

This patch feels a bit incomplete and there's a lot of opportunities
to take advantage of this information. We'll have to find and exploit
them eventually.
2021-03-21 21:39:39 +01:00
Andreas Kling
e0abfcb27d LibJS: Don't track executing AST nodes in a Vector
Instead just link together the InterpreterNodeScopes in a linked list.
This was surprisingly hot on CanvasCycle.
2021-03-21 21:39:39 +01:00
Andreas Kling
dc8817638e LibJS: Only update anonymous function names when necessary
Previously we would generate function names for anonymous functions
on every AssignmentExpression, even if we weren't assigning a function.

We were also setting names of anonymous functions in arrays, which is
apparently a SpiderMonkey specific behavior not supported by V8, JSC
or required by ECMA262. This patch removes that behavior.

This is a huge performance improvement on the CanvasCycle demo! :^)
2021-03-21 21:39:39 +01:00
Andreas Kling
1603623772 LibJS: Move AST node stack from VM to Interpreter 2021-03-21 16:02:11 +01:00
Andreas Kling
0bfdf95af6 LibJS: Make an RAII helper for entering/exiting AST nodes 2021-03-16 10:51:55 +01:00
Linus Groh
c499239137 LibJS: Implement non-value-producing statements properly
For various statements the spec states:

    Return NormalCompletion(empty).

In those cases we have been returning undefined so far, which is
incorrect.

In other cases it states:

    Return Completion(UpdateEmpty(stmtCompletion, undefined)).

Which essentially means a statement is evaluated and its completion
value returned if non-empty, and undefined otherwise.

While not actually noticeable in normal scripts as the VM's "last value"
can't be accessed from JS code directly (with the exception of eval(),
see below), it provided an inconsistent experience in the REPL:

    > if (true) 42;
    42
    > if (true) { 42; }
    undefined

This also fixes the case where eval() would return undefined if the last
executed statement is not a value-producing one:

    eval("1;;;;;")
    eval("1;{}")
    eval("1;var a;")

As a consequence of the changes outlined above, these now all correctly
return 1.

See https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation,
"NOTE 2".

Fixes #3609.
2021-03-16 10:08:07 +01:00
Andreas Kling
8fd69e9e56 LibJS: Fix a handful of clang-tidy complaints in AST.cpp 2021-03-03 22:57:45 +01:00
Jean-Baptiste Boric
6f668ca3a4 LibJS: Fix crash due to AST node tracking inside call stack 2021-03-01 22:27:27 +01:00
Jean-Baptiste Boric
6172cb3599 LibJS: Keep track of current AST node inside the call stack 2021-03-01 11:14:36 +01:00
speles
f7d64e9fa8 LibJS: Set declared for-in and for-of variables as first time.
These declarations might be const, and now when we're handling it
properly, we have to set values to them correctly.
2021-02-26 16:59:37 +01:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
Andreas Kling
70bd1724db LibJS: Include <typeinfo> in AST.cpp again
Linus points out that oss-fuzz wants this to be there.
2021-02-10 12:21:14 +01:00
Andreas Kling
635a5eec75 LibJS: Remove a whole bunch of unnecessary #includes 2021-02-10 09:13:29 +01:00
Linus Groh
509e5a3045 LibJS: Fix crash when printing error for missing class extends value prototype
If it's missing we get an empty value, but we can't use that with
to_string_without_side_effects() so we have to use undefined as the
default.

Fixes #5142.
2021-01-28 10:24:18 +01:00
Linus Groh
f37d3f25e6 LibJS: Remove redundant exception check from ClassExpression::execute()
as_object() cannot fail, leftover from ea55453.
2021-01-24 00:40:22 +01:00
Linus Groh
766f30f593 LibJS: Check if class extends value has a valid prototype
If we have a function as class extends value, we still cannot assume
that it has a prototype property and that property has a function or
null as its value - blindly calling to_object() on it may fail.

Fixes #5075.
2021-01-24 00:09:18 +01:00
Nico Weber
8ccd8b4a6f LibJS: Include <typeinfo> in AST.cpp
Without this, the oss-fuzz build says:

../Userland/Libraries/LibJS/AST.cpp:58:34: error: member access into incomplete type 'const std::type_info'
    return demangle(typeid(*this).name()).substring(4);
                                 ^
2021-01-20 21:00:27 +01:00
Andreas Kling
4da913bfab LibJS: Replace ASTNode::class_name() with RTTI
This is only used for debugging anyway, so performance doesn't matter
too much.
2021-01-17 14:36:53 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Renamed from Libraries/LibJS/AST.cpp (Browse further)