Commit graph

29 commits

Author SHA1 Message Date
Luke Wilde
f71f404e0c LibWeb: Introduce the Environment Settings Object
The environment settings object is effectively the context a piece of
script is running under, for example, it contains the origin,
responsible document, realm, global object and event loop for the
current context. This effectively replaces ScriptExecutionContext, but
it cannot be removed in this commit as EventTarget still depends on it.

https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
2022-02-08 17:47:44 +00:00
Idan Horowitz
853fab352d LibJS: Convert the InitializeReferencedBinding AO to ThrowCompletionOr 2021-11-02 19:48:35 +01:00
Idan Horowitz
1aaaf521b8 LibJS: Convert the PutValue AO to ThrowCompletionOr 2021-11-02 19:48:35 +01:00
Idan Horowitz
390a04a985 LibJS: Convert the GetValue AO to ThrowCompletionOr 2021-11-02 19:48:35 +01:00
Idan Horowitz
d73b258874 LibJS: Convert reference deletion to ThrowCompletionOr 2021-11-02 19:48:35 +01:00
Andreas Kling
a97d75bb63 LibJS: Add default constructor for PrivateName
This avoids a round-trip through FlyString("") for every Reference.
2021-10-25 13:29:44 +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
c7a6572789 LibJS: Add private references 2021-10-20 23:19:17 +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
Ali Mohammad Pur
13138811df LibJS: Partially revert 12b283f
This commit partially reverts "LibJS: Make accessing the current
function's arguments cheaper".
While the change passed all the currently passing test262 tests, it
seems to have _some_ flaw that silently breaks with some real-world
websites.
As the speedup with negligible at best, let's just revert it until we
can implement it more correctly.
2021-10-08 19:56:02 +03:30
Ali Mohammad Pur
12b283f32f LibJS: Make accessing the current function's arguments cheaper
Instead of going through an environment record, make arguments of the
currently executing function generate references via the argument index,
which can later be resolved directly through the ExecutionContext.
2021-10-08 12:25:24 +02:00
Andreas Kling
41a072bded LibJS: Fast non-local variable access :^)
This patch introduces the "environment coordinate" concept, which
encodes the distance from a variable access to the binding it ends up
resolving to.

EnvironmentCoordinate has two fields:

    - hops:  The number of hops up the lexical environment chain we have
             to make before getting to the resolved binding.

    - index: The index of the resolved binding within its declarative
             environment record.

Whenever a variable lookup resolves somewhere inside a declarative
environment, we now cache the coordinates and reuse them in subsequent
lookups. This is achieved via a coordinate cache in JS::Identifier.

Note that non-strict direct eval() breaks this optimization and so it
will not be performed if the resolved environment has been permanently
screwed by eval().

This makes variable access *significantly* faster. :^)
2021-10-07 11:53:18 +02:00
Andreas Kling
4444bcabde LibJS: Make Reference aware of DeclarativeEnvironment indices
VM::resolve_binding() can now return a Reference that knows the exact
binding index if it's pointing into a DeclarativeEnvironment.

Reading/writing through the Reference will now use direct environment
access when possible.
2021-10-07 00:23:36 +02: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
davidot
7081fb4eb0 LibJS: Make the default constructed reference invalid
Since we have the to_reference method on every expression class we must
somehow communicate it did not actually return a reference.
This (ab)uses the fact that property name is only invalid with the
default constructor and already has is_valid().
2021-09-30 08:16:32 +01:00
Ali Mohammad Pur
72ddaa31e3 LibJS: Implement parsing and execution of optional chains 2021-09-14 20:03:27 +01:00
Ali Mohammad Pur
f7a68ae998 LibJS: Mark two JS::Reference functions const
These two are inherently const, and the next commit needs to call them
on a const object, so let's just mark them const.
2021-09-14 20:03:27 +01:00
Andreas Kling
0d2c3f62d3 LibJS: Use move semantics more when creating Reference objects
Turns a bunch of FlyString copies into moves.
2021-09-11 20:38:45 +02:00
Andreas Kling
44221756ab LibJS: Drop "Record" suffix from all the *Environment record classes
"Records" in the spec are basically C++ classes, so let's drop this
mouthful of a suffix.
2021-07-01 12:28:57 +02:00
Andreas Kling
57214268dd LibJS: Make sure to always initialize Reference::m_base_value 2021-06-25 17:25:55 +02:00
Andreas Kling
7b28fa99ba LibJS: Rename Reference methods to match the spec
- get -> get_value (GetValue in the spec)
- put -> put_value (PutValue in the spec)

Also add spec links. :^)
2021-06-25 17:20:23 +02:00
Andreas Kling
bce7fdba81 LibJS: Bring Reference records a bit closer to the ECMAScript spec
Our Reference class now has the same fields as the spec:

- Base (a non-nullish value, an environment record, or `unresolvable`)
- Referenced Name (the name of the binding)
- Strict (whether the reference originated in strict mode code)
- ThisValue (if non-empty, the reference represents a `super` keyword)

The main difference from before is that we now resolve the environment
record that a reference interacts with. Previously we simply resolved
to either "local variable" or "global variable".

The associated abstract operations are still largely non-conforming,
since we don't yet implement proper variable bindings. But this patch
should at least fix a handful of test262 cases. :^)

There's one minor regression: some TypeError message strings get
a little worse due to doing a RequireObjectCoercible earlier in the
evaluation of MemberExpression.
2021-06-25 16:58:36 +02:00
Andreas Kling
8a3c9d9851 LibJS: Remove direct argument loading since it was buggy
The parser doesn't always track lexical scopes correctly, so let's not
rely on that for direct argument loading.

This reverts the LoadArguments bytecode instruction as well. We can
bring these things back when the parser can reliably tell us that
a given Identifier is indeed a function argument.
2021-06-22 22:20:17 +02:00
Andreas Kling
6e0e8a8242 LibJS: Teach Reference to access call frame arguments directly 2021-06-14 11:26:12 +02:00
Idan Horowitz
064ed8279e LibJS: Support deleting local variables with operator delete
To make this cleaner i also moved the logic into Reference::delete_.
2021-06-08 15:31:46 +01: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
e875513ff7 LibJS: Use empty value for Reference unresolvable state, not undefined
This fixes an issue where `undefined.foo = "bar"` would throw a
ReferenceError instead of a TypeError as undefined was also used for
truly unresolvable references (e.g. `foo() = "bar"`). I also made the
various error messages here a bit nicer, just "primitive value" is not
very helpful.
2021-04-02 22:24:30 +02:00
Andreas Kling
46e61d208b LibJS: Avoid unnecessary FlyString(String) churn in Reference ctors 2021-03-21 21:39:39 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Renamed from Libraries/LibJS/Runtime/Reference.h (Browse further)