Commit graph

86 commits

Author SHA1 Message Date
Andreas Kling
75f2510de9 LibJS: Make make_super_property_reference() take a PropertyKey
Let's get rid of StringOrSymbol usage outside of Shape.
2021-10-24 17:18:08 +02:00
Andreas Kling
398c181c79 LibJS: Rename PropertyName to PropertyKey
Let's use the same name as the spec. :^)
2021-10-24 17:18:07 +02:00
davidot
13ead80ee6 LibJS: Add PrivateEnvironment 2021-10-20 23:19:17 +01:00
Idan Horowitz
40eb3a39d4 LibJS: Rename define_native_function => define_old_native_function
This method will eventually be removed once all native functions are
converted to ThrowCompletionOr
2021-10-20 12:27:19 +01:00
Idan Horowitz
aad12b050b LibJS: Convert to_length() to ThrowCompletionOr 2021-10-18 08:01:38 +03:00
Idan Horowitz
20d990563c LibJS: Convert to_number() to ThrowCompletionOr 2021-10-18 08:01:38 +03:00
davidot
c3cb44ca8a LibJS: Remove ErrorType::FixmeAddAnErrorStringWithMessage 2021-10-15 10:27:16 +01:00
Linus Groh
c70784bb82 LibJS: Implement ShadowRealm.prototype.evaluate() 2021-10-14 00:41:41 +01:00
Linus Groh
96ab116f0d LibJS: Convert to_primitive_string() to ThrowCompletionOr 2021-10-13 09:55:10 +01:00
Linus Groh
da59c77fe3 LibJS: Convert to_utf16_string() to ThrowCompletionOr 2021-10-13 09:55:10 +01:00
Linus Groh
4d8912a92b LibJS: Convert to_string() to ThrowCompletionOr
Also update get_function_name() to use ThrowCompletionOr, but this is
not a standard AO and should be refactored out of existence eventually.
2021-10-13 09:55:10 +01:00
Linus Groh
f35e268024 LibJS: Convert get_binding_value() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
7652138ce0 LibJS: Convert set_mutable_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
ae397541fb LibJS: Convert initialize_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
2691c65639 LibJS: Convert create_immutable_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
4baf3a91e8 LibJS: Convert create_mutable_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
fbb176c926 LibJS: Convert has_binding() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
4f03138971 LibJS: Convert get_super_base() to ThrowCompletionOr
Also add spec step comments to it while we're here.
2021-10-09 21:53:47 +01:00
Linus Groh
fe5c2b7bb9 LibJS: Decouple new_function_environment() from FunctionObject
Now that only ECMAScriptFunctionObject uses this, we can remove the
FunctionObject::new_function_environment() pure virtual method and just
implement it as a standalone AO with an ECMAScriptFunctionObject
parameter, next to the other NewFooEnvironment AOs.
2021-10-09 14:29:20 +01:00
Linus Groh
cf168fac50 LibJS: Implement [[Call]] and [[Construct]] internal slots properly
This patch implements:

- Spec compliant [[Call]] and [[Construct]] internal slots, as virtual
  FunctionObject::internal_{call,construct}(). These effectively replace
  the old virtual FunctionObject::{call,construct}(), but with several
  advantages:
  - Clear and consistent naming, following the object internal methods
  - Use of completions
  - internal_construct() returns an Object, and not Value! This has been
    a source of confusion for a long time, since in the spec there's
    always an Object returned but the Value return type in LibJS meant
    that this could not be fully trusted and something could screw you
    over.
  - Arguments are passed explicitly in form of a MarkedValueList,
    allowing manipulation (BoundFunction). We still put them on the
    execution context as a lot of code depends on it (VM::arguments()),
    but not from the Call() / Construct() AOs anymore, which now allows
    for bypassing them and invoking [[Call]] / [[Construct]] directly.
    Nothing but Call() / Construct() themselves do that at the moment,
    but future additions to ECMA262 or already existing web specs might.
- Spec compliant, standalone Call() and Construct() AOs: currently the
  closest we have is VM::{call,construct}(), but those try to cater to
  all the different function object subclasses at once, resulting in a
  horrible mess and calling AOs with functions they should never be
  called with; most prominently PrepareForOrdinaryCall and
  OrdinaryCallBindThis, which are only for ECMAScriptFunctionObject.

As a result this also contains an implicit optimization: we no longer
need to create a new function environment for NativeFunctions - which,
worth mentioning, is what started this whole crusade in the first place
:^)
2021-10-09 14:29:20 +01:00
Andreas Kling
421845b0cd LibJS: Taint variable environment chain after non-strict direct eval()
Since non-strict direct eval() can insert new bindings into a
surrounding var scope, we cannot safely cache some assumptions about
environment chain layout after eval() has taken place.

Since eval() is rare, let's do what other engines do and simply
deoptimize in its presence. This patch adds a new "permanently screwed"
flag to JS::Environment that will be set on the entire variable
environment chain upon non-strict direct eval().
2021-10-07 11:53:18 +02:00
Linus Groh
4fa5748093 LibJS: Add an optimization to avoid needless arguments object creation
This gives FunctionNode a "might need arguments object" boolean flag and
sets it based on the simplest possible heuristic for this: if we
encounter an identifier called "arguments" or "eval" up to the next
(nested) function declaration or expression, we won't need an arguments
object. Otherwise, we *might* need one - the final decision is made in
the FunctionDeclarationInstantiation AO.

Now, this is obviously not perfect. Even if you avoid eval, something
like `foo.arguments` will still trigger a false positive - but it's a
start and already massively cuts down on needlessly allocated objects,
especially in real-world code that is often minified, and so a full
"arguments" identifier will be an actual arguments object more often
than not.

To illustrate the actual impact of this change, here's the number of
allocated arguments objects during a full test-js run:

Before:
- Unmapped arguments objects: 78765
- Mapped arguments objects: 2455

After:
- Unmapped arguments objects: 18
- Mapped arguments objects: 37

This results in a ~5% speedup of test-js on my Linux host machine, and
about 3.5% on i686 Serenity in QEMU (warm runs, average of 5).

The following microbenchmark (calling an empty function 1M times) runs
25% faster on Linux and 45% on Serenity:

    function foo() {}
    for (var i = 0; i < 1_000_000; ++i)
        foo();

test262 reports no changes in either direction, apart from a speedup :^)
2021-10-05 10:15:14 +01:00
Andreas Kling
d872f0d503 LibJS: Avoid an unnecessary String in create_mapped_arguments_object() 2021-10-04 22:54:50 +02:00
Andreas Kling
f4180b7269 LibJS: Avoid an unnecessary String in create_list_from_array_like() 2021-10-04 22:54:50 +02:00
Linus Groh
fe86b04b42 LibJS: Convert define_property_or_throw() to ThrowCompletionOr 2021-10-03 20:14:03 +01:00
Linus Groh
364dd42fc8 LibJS: Convert create_data_property_or_throw() to ThrowCompletionOr 2021-10-03 20:14:03 +01:00
Linus Groh
b7e5f08e56 LibJS: Convert Object::get() to ThrowCompletionOr
To no one's surprise, this patch is pretty big - this is possibly the
most used AO of all of them. Definitely worth it though.
2021-10-03 20:14:03 +01:00
Linus Groh
4d5bd092ea LibJS: Use MUST() where applicable 2021-10-03 20:14:03 +01:00
davidot
830ea0414c LibJS: Make scoping follow the spec
Before this we used an ad-hoc combination of references and 'variables'
stored in a hashmap. This worked in most cases but is not spec like.
Additionally hoisting, dynamically naming functions and scope analysis
was not done properly.

This patch fixes all of that by:
  - Implement BindingInitialization for destructuring assignment.
  - Implementing a new ScopePusher which tracks the lexical and var
    scoped declarations. This hoists functions to the top level if no
    lexical declaration name overlaps. Furthermore we do checking of
    redeclarations in the ScopePusher now requiring less checks all over
    the place.
  - Add methods for parsing the directives and statement lists instead
    of having that code duplicated in multiple places. This allows
    declarations to pushed to the appropriate scope more easily.
  - Remove the non spec way of storing 'variables' in
    DeclarativeEnvironment and make Reference follow the spec instead of
    checking both the bindings and 'variables'.
  - Remove all scoping related things from the Interpreter. And instead
    use environments as specified by the spec. This also includes fixing
    that NativeFunctions did not produce a valid FunctionEnvironment
    which could cause issues with callbacks and eval. All
    FunctionObjects now have a valid NewFunctionEnvironment
    implementation.
  - Remove execute_statements from Interpreter and instead use
    ASTNode::execute everywhere this simplifies AST.cpp as you no longer
    need to worry about which method to call.
  - Make ScopeNodes setup their own environment. This uses four
    different methods specified by the spec
    {Block, Function, Eval, Global}DeclarationInstantiation with the
    annexB extensions.
  - Implement and use NamedEvaluation where specified.

Additionally there are fixes to things exposed by these changes to eval,
{for, for-in, for-of} loops and assignment.

Finally it also fixes some tests in test-js which where passing before
but not now that we have correct behavior :^).
2021-09-30 08:16:32 +01:00
Linus Groh
5148150e1c LibJS: Convert internal_get_prototype_of() to ThrowCompletionOr 2021-09-29 23:49:53 +01:00
Linus Groh
4566472ed6 LibJS: Rename BoundFunction::m_target_function to match spec name 2021-09-25 17:51:30 +02:00
Idan Horowitz
1da8faebf5 LibJS: Convert perform_eval to ThrowCompletionOr 2021-09-21 23:28:38 +03:00
Idan Horowitz
f302b114f3 LibJS: Convert get_substitution to ThrowCompletionOr 2021-09-21 23:28:38 +03:00
Idan Horowitz
69430855e0 LibJS: Remove non-specification compliant exception check 2021-09-21 23:28:38 +03:00
Idan Horowitz
e90e4ac1e2 LibJS: Convert length_of_array_like to ThrowCompletionOr 2021-09-21 23:28:38 +03:00
Idan Horowitz
02a88c5063 LibJS: Convert make_super_property_reference to ThrowCompletionOr 2021-09-21 23:28:38 +03:00
Brian Gianforcaro
9f50e288f7 LibJS: Fix Clang Toolchain CI build
Clang was failing because because it rightfully saw we were attempting
to call a deleted constructor of `MarkedValueList`. If you explicitly
called move(list) then GCC would complain that the move was unnecessary.

For what ever reason both tool chains accept when we construct the
ThrowCompletionOr explicitly that we move the list into and return that.
2021-09-16 10:05:45 +01:00
Linus Groh
2d4650714f LibJS: Use ThrowCompletionOr in get_prototype_from_constructor()
Also add spec step comments to it while we're here.
2021-09-15 23:46:53 +01:00
Linus Groh
bc1b8f9cc8 LibJS: Use ThrowCompletionOr in get_function_realm() 2021-09-15 23:46:53 +01:00
Linus Groh
3d43eb0774 LibJS: Use ThrowCompletionOr in species_constructor()
Also add spec step comments to it as well as a missing exception check
while we're here.
2021-09-15 23:46:53 +01:00
Linus Groh
c4c40f4cf3 LibJS: Use ThrowCompletionOr in create_list_from_array_like()
Also add spec step comments to it while we're here.
2021-09-15 23:46:53 +01:00
Linus Groh
568296d0cc LibJS: Use ThrowCompletionOr in require_object_coercible() 2021-09-15 23:46:53 +01:00
Linus Groh
1a7828a9f3 LibJS: Return default-constructed values instead of the INVALID constant
This is much more common across the whole codebase and even these two
files. The same is used to return an empty JS::Value in an exception
check, for example.
2021-09-15 18:41:33 +01:00
Linus Groh
657d17ace3 LibJS: Remove two unused includes from AbstractOperations.cpp 2021-09-15 18:36:06 +01:00
Linus Groh
80e58dab9a LibJS: Make get_function_realm() actually return a Realm 2021-09-12 11:10:20 +01:00
Linus Groh
06e89311fa LibJS: Set the callee context's realm in prepare_for_ordinary_call()
This includes making FunctionObject::realm() actually return a Realm,
instead of a GlobalObject.
2021-09-12 11:10:20 +01:00
Linus Groh
f29a82dd84 LibJS: Move the GlobalEnvironment from GlobalObject to Realm
This is where the spec wants to have it. Requires a couple of hacks as
currently everything that needs a Realm actually has a GlobalObject, so
we need to go via the Interpreter.
2021-09-12 11:10:20 +01:00
Andreas Kling
19ee5e01ad LibJS: Use Span<Cell*> instead of Vector<Cell*> in more places 2021-09-11 14:10:11 +02:00
Timothy Flynn
6c45620709 LibJS: Reduce copying of string data in String.prototype
The primary themes here are invoking js_string() with existing instances
of Utf16String when possible, and not creating entire UTF-8 copies when
not needed.
2021-08-10 23:07:50 +02:00
Timothy Flynn
c1e99fca1a LibJS: Replace Vector<u16> usage in PrimitiveString wth Utf16String
This commit does not go out of its way to reduce copying of the string
data yet, but is a minimum set of changes to compile LibJS after making
PrimitiveString hold a Utf16String.
2021-08-10 23:07:50 +02:00