Commit graph

218 commits

Author SHA1 Message Date
Luke Wilde
f4be95af69 LibJS: Don't discard ThrowCompletionOr<void> from declaration iteration 2023-02-27 23:57:08 +00:00
Hendiadyoin1
de514f29ad LibJS: Align codegen AwaitExpressions to YieldExpressions
We use generators in bytecode to approximate async functions, but the
code generated by AwaitExpressions did not have the value processing
paths that Yield requires, eg the `generator.throw()` path, which is
used by AsyncFunctionDriverWrapper to signal Promise rejections.
2023-02-26 19:40:09 +01:00
Hendiadyoin1
088dc1b24b LibJS: Simplify Generator::perform_needed_unwinds
This does not need to cater to the needs of `break` and `continue
anymore, which allows us to simplify it a bit.
2023-02-26 19:40:09 +01:00
Hendiadyoin1
d65488b80c LibJS: Generate unwind chains for continue in Bytecode
This works similar to `break`
The `try-finally-continue` still do not pass with this, likely because
of binding issues.
2023-02-26 19:40:09 +01:00
Hendiadyoin1
f5376cb282 LibJS: Generate unwind chains for break in Bytecode
This uses a newly added instruction `ScheduleJump`
This instruction tells the finally proceeding it, that instead of
jumping to it's next block it should jump to the designated block.
2023-02-26 19:40:09 +01:00
Andreas Kling
bd5d8e9d35 LibJS: Make RefPtr and NonnullRefPtr usage const-correct
This mainly affected the AST, which is now const throughout.
2023-02-21 00:54:04 +01:00
MacDue
63b11030f0 Everywhere: Use ReadonlySpan<T> instead of Span<T const> 2023-02-08 19:15:45 +00:00
Timothy Flynn
f3db548a3d AK+Everywhere: Rename FlyString to DeprecatedFlyString
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
2023-01-09 23:00:24 +00:00
Ben Wiederhake
6fd478b6ce Everywhere: Remove unused includes of AK/Format.h
These instances were detected by searching for files that include
AK/Format.h, but don't match the regex:

\\b(CheckedFormatString|critical_dmesgln|dbgln|dbgln_if|dmesgln|FormatBu
ilder|__FormatIfSupported|FormatIfSupported|FormatParser|FormatString|Fo
rmattable|Formatter|__format_value|HasFormatter|max_format_arguments|out
|outln|set_debug_enabled|StandardFormatter|TypeErasedFormatParams|TypeEr
asedParameter|VariadicFormatParams|v_critical_dmesgln|vdbgln|vdmesgln|vf
ormat|vout|warn|warnln|warnln_if)\\b

(Without the linebreaks.)

This regex is pessimistic, so there might be more files that don't
actually use any formatting functions.

Observe that this revealed that Userland/Libraries/LibC/signal.cpp is
missing an include.

In theory, one might use LibCPP to detect things like this
automatically, but let's do this one step after another.
2023-01-02 20:27:20 -05:00
Luke Wilde
4db2efaecb LibJS/Bytecode: Implement yield* 2022-12-10 00:21:10 +00:00
Luke Wilde
758a4cb1a6 LibJS/Bytecode: Implement var/lexical binding destructuring in for/of 2022-12-10 00:21:10 +00:00
Andreas Kling
b894acd6b2 LibJS: Make one compact allocation for CallExpression and its Arguments
Instead of CallExpression storing its arguments in a Vector<Argument>,
we now custom-allocate the memory slot for CallExpression (and its
subclass NewExpression) so that it fits both CallExpression and its list
of Arguments in one allocation.

This reduces memory usage on twitter.com/awesomekling by 8.8 MiB :^)
2022-12-08 23:36:17 +00:00
Hendiadyoin1
fcc3348bc8 LibJS: Intercept returns through finally blocks in Bytecode
This is still not perfect, as we now actually crash in the
`try-finally-continue` tests, while we now succeed all
`try-catch-finally-*` tests.

Note that we do not yet go through the finally block when exiting the
unwind context through a break or continue.
2022-12-06 16:09:24 +03:30
Hendiadyoin1
133faa0acc LibJS: Remove FinishUnwind instruction
This is essentially a LeaveUnwind+Jump, so lets just do that, that will
make it easier to optimize it, or see unwind state transitions
2022-12-06 16:09:24 +03:30
Hendiadyoin1
fc332be2e5 LibJS: Leave unwind contexts on enter of finally blocks in Bytecode
Before we were doing so while exiting the catch-block, but not when
exiting the try-block.
This now centralizes the responsibility to exit the unwind context to
the finalizer, ignoring return/break/continue.
This makes it easier to handle the return case in a future commit.
2022-12-06 16:09:24 +03:30
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Luke Wilde
5bc3371226 LibJS: Perform received abrupt generator completions in the generator
Previously, throw and return completions would not be executed inside
the generator. This is incorrect, as throw and return need to perform
unwinds which can potentially execute more code inside the generator,
such as finally blocks.

This is done by also passing the completion type alongside the passed
in value. The continuation block will immediately extract and type and
value and perform the appropriate operation for the given type.

For normal completions, this is continuing as normal.
For throw completions, it will perform `throw <value>`.
For return completions, it will perform `return <value>`, which is a
`Yield return` in this case due to being inside a generator.

This also refactors GeneratorObject to properly send across the
completion type and value to the generator inside of trying to operate
on the completions itself.

This is a prerequisite for yield*, as it performs special iterator
operations when receiving a throw/return completion and does not
complete the generator like the regular yield would.

There's still more work to be done to make GeneratorObject::execute
be closer to the spec. It's mostly a restructuring of the existing
GeneratorObject::next_impl.
2022-11-26 12:55:59 +01:00
Luke Wilde
b914680f0c LibJS/Bytecode: Make yield by itself yield undefined 2022-11-26 12:55:59 +01:00
Andreas Kling
178f0b9971 LibJS: Support non-base-10 BigInt literals in bytecode VM
Fixes 39 tests in test262 and a handful in test-js. :^)
2022-10-19 19:58:15 +02:00
Andreas Kling
29935fe943 LibJS: Support for (x in obj) iteration in bytecode VM
We were mistakenly treating these as `for (x of obj)`. By reorganizing
the code a little bit, we actually support both kinds of iteration with
less duplication. :^)

Fixes 17 tests in test262.
2022-10-19 19:03:57 +02:00
Hendiadyoin1
490c097bc4 LibJS: Forward a string aproximation of the CallExpression to Call Ops
This gives us better debug output when analysing calls to `undefined`
and also fixes multiple test-js cases expecting an
`(evaluated from $Expression)` in the error message.

This also refactors out the generation of that string, to avoid code
duplication with the AST interpreter.
2022-10-17 01:36:41 +02:00
Hendiadyoin1
89408d5f64 LibJS: Handle argument spreading in the bytecode vm 2022-10-01 00:04:02 +01:00
Hendiadyoin1
ae52ae8f9f LibJS: Add support for SpreadExpressions in array literals for bytecode
For this it adds another opcode `Append $lhs` which appends the
accumulator to the Array in $lhs, optionally spreading it.
2022-10-01 00:04:02 +01:00
Hendiadyoin1
4235b2020f LibJS: Switch to array-calls in the bytecode vm
This will make it easier to implement spreading arguments.
2022-10-01 00:04:02 +01:00
Hendiadyoin1
ab763a56f6 LibJS: Allow SpreadExpressions to generate bytecode 2022-10-01 00:04:02 +01:00
Hendiadyoin1
21ae882cfd LibJS: Implement SuperCall for the Bytecode-VM 2022-08-31 15:22:36 +01:00
Luke Wilde
fe2efbb2fc LibJS/Bytecode: Implement initializers for array binding patterns 2022-07-18 09:00:21 +01:00
Luke Wilde
0151dc562a LibJS/Bytecode: Implement destructuring assignment 2022-07-18 09:00:21 +01:00
Luke Wilde
f99f5d740e LibJS/Bytecode: Evaluate LHS of assignment before RHS
We had the same issue with the AST interpreter, see issue #3689.
2022-07-18 09:00:21 +01:00
Luke Wilde
896c477107 LibJS/Bytecode: Don't begin breakable scope before variable scope in for
This is no longer required, since the variable scope is ended after
switching to the end block, which means that LeaveLexicalEnvironment
will always be generated instead of depending on the unwind mechanism
to handle it for us.
2022-07-18 09:00:21 +01:00
Luke Wilde
3a48c7fdaf LibJS/Bytecode: Check for lexical bindings only in current scope
BlockDeclarationInstantiation takes as input the new lexical
environment that was created and checks if there is a binding for the
current name only in this new scope.

This allows shadowing lexical variables and prevents us crashing due to
an already initialized lexical variable in this case:
```js
let x = 1;
{
    let x = 1;
}
```
2022-07-18 09:00:21 +01:00
Luke Wilde
c55a4c7f30 LibJS/Bytecode: Create global variables before setting them
This allows them to be accessed before assignment, and also prevents
throwing in strict mode as we are trying to set a non-existent
variable.
2022-07-18 09:00:21 +01:00
Luke Wilde
c153d1779e LibJS/Bytecode: End the for variable scope at the start of its end block
If the for loop's body is not block terminated, we will generate a Jump
to the end block which will block terminate the body. Then, we ended
the lexical variable scope if needed. However, since the body is now
block terminated, the "LeaveLexicalEnvironment" instruction that is
generated by end_variable_scope is now dropped on the floor.

This fixes this by moving it to the beginning of the end block.
2022-06-30 15:59:55 +01:00
Luke Wilde
bc08d39754 LibJS/Bytecode: Make for, do/while and while always switch to end block
Previously we only did this if the body block was not terminated.
If it was, all future codegen would happen in this block terminated
body block until another switch occurred, dropping all generated
instructions in this time on the floor.
2022-06-30 18:35:18 +04:30
Luke Wilde
125a71d36d LibJS/Bytecode: Define named functions as a variable inside their scope
This allows you to recurse into a named function that is stored in a
variable. For example, this would previously print "wrong" instead of
"right":
```js
function g() { console.log("wrong") }
f = function g(i) { if (i !== 1) g(1); else console.log("right"); }
f()
```
2022-06-13 07:13:03 +04:30
Luke Wilde
77f88d00e0 LibJS/Bytecode: Make return; return undefined
Previously it would return whatever was in the accumulator.
2022-06-13 07:13:03 +04:30
Luke Wilde
482a827346 LibJS/Bytecode: Make typeof return "undefined" on unresolvable IDs
Previously it would throw instead of returning "undefined" for
`typeof Identifier` if Identifier does not exist.
2022-06-13 07:13:03 +04:30
Luke Wilde
c0fadfb9b7 LibJS/Bytecode: Implement break/continue labels
This is done by keeping track of all the labels that apply to a given
break/continue scope alongside their bytecode target. When a
break/continue with a label is generated, we scan from the most inner
scope to the most outer scope looking for the label, performing any
necessary unwinds on the way. Once the label is found, it is then
jumped to.
2022-06-13 07:13:03 +04:30
Linus Groh
9f3f3b0864 LibJS: Remove implicit wrapping/unwrapping of completion records
This is an editorial change in the ECMA-262 spec, with similar changes
in some proposals.

See:
- https://github.com/tc39/ecma262/commit/7575f74
- https://github.com/tc39/proposal-array-grouping/commit/df899eb
- https://github.com/tc39/proposal-shadowrealm/commit/9eb5a12
- https://github.com/tc39/proposal-shadowrealm/commit/c81f527
2022-05-03 01:09:29 +02:00
Ali Mohammad Pur
4b5a9bab34 LibJS: Actually generate a lexical env for SwitchStatement in BC
We had code for this in ScopeNode, but that function was never called
for a SwitchStatement.
This fixes a bunch of scoping tests for switch.
2022-04-05 11:46:48 +02:00
Ali Mohammad Pur
0e1943937c LibJS: Use InitializeOrSet to initialize function declarations in BC
A function may be redefined, in which case the existing binding is
expected to be reused.
2022-04-05 11:46:48 +02:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Ali Mohammad Pur
7ea095feb0 LibJS: Don't assume that for-in/of target is a variable on LHS::Assign
e.g. `for ([foo.bar] in ...)` is actually a binding pattern.
2022-03-31 18:11:08 +02:00
Ali Mohammad Pur
56c0fdc1c4 LibJS: Implement codegen for MemberExpression binding patterns 2022-03-31 18:11:08 +02:00
Ali Mohammad Pur
007ffcd763 LibJS: Implement bytecode generation for all ObjectExpression properties 2022-03-31 18:11:08 +02:00
Luke Wilde
7cc53b7ef1 LibJS/Bytecode: Implement the delete unary expression
`delete` has to operate directly on Reference Records, so this
introduces a new set of operations called DeleteByValue, DeleteVariable
and DeleteById. They operate similarly to their Get counterparts,
except they end in creating a (temporary) Reference and calling delete_
on it.
2022-03-28 14:05:33 +02:00
Luke Wilde
88901182b8 LibJS: Generate update Jump in for/in/of only if block is not terminated
The body of for/in/of can contain an unconditional block terminator
(e.g. return, throw), so we have to check for that before generating
the Jump to the loop update block.
2022-03-28 14:05:33 +02:00
Luke Wilde
eac5534ce4 LibJS/Bytecode: Add support for new.target 2022-03-19 22:01:52 +01:00
Ali Mohammad Pur
8f7021faf7 LibJS: Implement bytecode generation for For-In/Of statements
This also implements the rather interesting behaviour that #12772 relies
on, so this fixes that bug in BC mode (the AST interp remains affected).
2022-03-19 12:51:29 +01:00
Luke Wilde
db1236b336 LibJS/Bytecode: Fix typo in object binding an entry with no alias
In object binding, we would attempt to get NonnullRefPtr<Identifier>
from alias on the alias.has<Empty>() code path. In this case, we need
to get it from name instead.
2022-03-15 11:57:51 +03:30