1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-19 02:55:07 +00:00
Commit graph

969 commits

Author SHA1 Message Date
Andreas Kling
340a115dfe LibJS: Make native function/property callbacks take VM, not Interpreter
More work on decoupling the general runtime from Interpreter. The goal
is becoming clearer. Interpreter should be one possible way to execute
code inside a VM. In the future we might have other ways :^)
2020-09-27 20:26:58 +02:00
Andreas Kling
1ff9d33131 LibJS: Make Function::call() not require an Interpreter&
This makes a difference inside ScriptFunction::call(), which will now
instantiate a temporary Interpreter if one is not attached to the VM.
2020-09-27 20:26:58 +02:00
Andreas Kling
be31805e8b LibJS: Move scope stack from VM back to Interpreter
Okay, my vision here is improving. Interpreter should be a thing that
executes an AST. The scope stack is irrelevant to the VM proper,
so we can move that to the Interpreter. Same with execute_statement().
2020-09-27 20:26:58 +02:00
Andreas Kling
6861c619c6 LibJS: Move most of Interpreter into VM
This patch moves the exception state, call stack and scope stack from
Interpreter to VM. I'm doing this to help myself discover what the
split between Interpreter and VM should be, by shuffling things around
and seeing what falls where.

With these changes, we no longer have a persistent lexical environment
for the current global object on the Interpreter's call stack. Instead,
we push/pop that environment on Interpreter::run() enter/exit.
Since it should only be used to find the global "this", and not for
variable storage (that goes directly into the global object instead!),
I had to insert some short-circuiting when walking the environment
parent chain during variable lookup.

Note that this is a "stepping stone" commit, not a final design.
2020-09-27 20:26:58 +02:00
Andreas Kling
111d63c676 LibJS: Remove two unused Interpreter member functions 2020-09-26 21:23:14 +02:00
Linus Groh
7d83665635 LibJS+LibGUI+js: Handle UnterminatedRegexLiteral in syntax highlighters 2020-09-25 23:58:42 +02:00
Ben Wiederhake
08f9bc26a6 Meta+LibHTTP through LibWeb: Make clang-format-10 clean 2020-09-25 21:18:17 +02:00
Andreas Kling
69bbf0285b LibJS: Let the VM cache an empty ("") PrimitiveString
Empty string is extremely common and we can avoid a lot of heap churn
by simply caching one in the VM. Primitive strings are immutable anyway
so there is no observable behavior change outside of fewer collections.
2020-09-22 20:10:20 +02:00
Andreas Kling
d1b58ee9ad LibJS: Move well-known symbols to the VM
No need to instantiate unique symbols for each Interpreter; they can
be VM-global. This reduces the memory cost and startup time anyway.
2020-09-22 20:10:20 +02:00
Andreas Kling
676cb87a8f LibJS: Use VM::exception() instead of Interpreter::exception() a bunch
There's a lot more of these things to fix. We'll also want to move from
passing Interpreter& around to VM& instead wherever that is enough.
2020-09-22 20:10:20 +02:00
Andreas Kling
d74bb87d46 LibJS: Add a way to get from a Cell to the VM 2020-09-22 20:10:20 +02:00
Andreas Kling
4a8bfcdd1c LibJS: Move the current exception from Interpreter to VM
This will allow us to throw exceptions even when there is no active
interpreter in the VM.
2020-09-22 20:10:20 +02:00
Andreas Kling
5b6ccbb918 LibJS: VM::interpreter() should just assert when no active interpreter
I accidentally committed some code here to force a crash, but this
should just assert.
2020-09-21 14:42:26 +02:00
Andreas Kling
c8baf29d82 LibJS: Assert if garbage collection is restarted while ongoing
We can't GC while we're already in GC. Assert if this happens.
2020-09-21 14:35:19 +02:00
Andreas Kling
df3ff76815 LibJS: Rename InterpreterScope => InterpreterExecutionScope
To make it a little clearer what this is for. (This is an RAII helper
class for adding and removing an Interpreter to a VM's list of the
currently active (executing code) Interpreters.)
2020-09-21 14:35:12 +02:00
Andreas Kling
fbe2907510 LibJS: GC should gather roots from all active interpreters
If we are in a nested execution context, we shouldn't only mark things
used by the active interpreter.
2020-09-21 14:34:40 +02:00
Andreas Kling
1c43442be4 LibJS+Clients: Add JS::VM object, separate Heap from Interpreter
Taking a big step towards a world of multiple global object, this patch
adds a new JS::VM object that houses the JS::Heap.

This means that the Heap moves out of Interpreter, and the same Heap
can now be used by multiple Interpreters, and can also outlive them.

The VM keeps a stack of Interpreter pointers. We push/pop on this
stack when entering/exiting execution with a given Interpreter.
This allows us to make this change without disturbing too much of
the existing code.

There is still a 1-to-1 relationship between Interpreter and the
global object. This will change in the future.

Ultimately, the goal here is to make Interpreter a transient object
that only needs to exist while you execute some code. Getting there
will take a lot more work though. :^)

Note that in LibWeb, the global JS::VM is called main_thread_vm(),
to distinguish it from future worker VM's.
2020-09-20 19:24:44 +02:00
Andreas Kling
976e55e942 LibJS: Remove some unnecessary indirection in Object constructors 2020-09-20 19:18:05 +02:00
Andreas Kling
668e73df8a LibJS: Make Interpreter::in_strict_mode() work outside of scope
This one is a little weird. I don't know why it's okay for this
function to assume that there is a current scope on the scope stack
when it can be called during global object initialization etc.

For now, just make it say "we are in strict mode" when there is no
currently active scope.
2020-09-20 19:16:34 +02:00
Andreas Kling
893df28e80 LibJS: Don't allocate property table during GC marking phase
Shape was allocating property tables inside visit_children(), which
could cause garbage collection to happen. It's not very good to start
a new garbage collection while you are in the middle of one already.
2020-09-20 19:11:49 +02:00
Andreas Kling
4036ff9d91 LibJS: Remove unused argument in NativeFunction constructor 2020-09-20 19:11:11 +02:00
Linus Groh
c0e4353bde LibJS: Handle getter exception in JSONObject::serialize_json_property()
In the case of an exception in a property getter function we would not
return early, and a subsequent attempt to call the replacer function
would crash the interpreter due to call_internal() asserting.

Fixes #3548.
2020-09-19 14:17:22 +02:00
AnotherTest
21f513fe0f LibJS: Do not revisit already visited values in update_function_name()
Fixes #3471, adds a test.
2020-09-19 00:33:56 +02:00
Linus Groh
a9f5b0339d LibJS: Simplify toEval() implementation 2020-09-18 20:49:35 +02:00
Linus Groh
5fd87ccd16 LibJS: Add FIXMEs for parsing increment operators with function LHS/RHS
The parser considers it a syntax error at the moment, other engines
throw a ReferenceError during runtime for ++foo(), --foo(), foo()++ and
foo()--, so I assume the spec defines this.
2020-09-18 20:49:35 +02:00
Linus Groh
fd32f00839 LibJS: Mark more ASTNode classes as final 2020-09-18 20:49:35 +02:00
Linus Groh
568d53c9b1 LibJS: Check validity of computed_property_name() result before using it
This fixes two cases obj[expr] and obj[expr]() (MemberExpression and
CallExpression respectively) when expr throws an exception and results
in an empty value, causing a crash by passing the invalid PropertyName
created by computed_property_name() to Object::get() without checking it
first.

Fixes #3459.
2020-09-12 11:29:39 +02:00
Linus Groh
75dac35d0e LibJS: Stop unwinding and reset exception for TryStatement finalizer
This fixes two issues with running a TryStatement finalizer:

- Temporarily store and clear the exception, if any, so we can run the
  finalizer block statement without it getting in our way, which could
  have unexpected side effects otherwise (and will likely return early
  somewhere).
- Stop unwinding so more than one child node of the finalizer
  BlockStatement is executed if an exception has been thrown previously
  (which would have called unwind(ScopeType::Try)). Re-throwing as
  described above ensures we still unwind after the finalizer, if
  necessary.

Also add some tests specifically for try/catch/finally blocks, we
didn't have any!
2020-09-12 09:31:16 +02:00
Linus Groh
ec43f73b74 LibJS: Extract most of Interpreter's run() into execute_statement()
Interpreter::run() was so far being used both as the "public API entry
point" for running a JS::Program as well as internally to execute
JS::Statement|s of all kinds - this is now more distinctly separated.
A program as returned by the parser is still going through run(), which
is responsible for creating the initial global call frame, but all other
statements are executed via execute_statement() directly.

Fixes #3437, a regression introduced by adding ASSERT(!exception()) to
run() without considering the effects that would have on internal usage.
2020-09-12 09:31:16 +02:00
Ben Wiederhake
5d3c437cce LibJS: Fix start position of multi-line tokens
This broke in case of unterminated regular expressions, causing goofy location
numbers, and 'source_location_hint' to eat up all memory:

Unexpected token UnterminatedRegexLiteral. Expected statement (line: 2, column: 4294967292)
2020-09-12 00:13:29 +02:00
Andreas Kling
d830c107ce LibJS: Deal with a FIXME in Shape::ensure_property_table()
Prevent GC while messing with the shape transition chain.
2020-09-09 21:34:02 +02:00
Andreas Kling
d467a0ffef LibJS: ArrayIterator needs to mark the array it's iterating 2020-09-08 16:20:34 +02:00
Andreas Kling
3143fea1eb LibJS: GlobalObject needs to mark the iterator prototypes
Otherwise they all disappear in the first garbage collection.
2020-09-08 15:37:39 +02:00
Andreas Kling
b32c0c8181 LibJS: Convert two suspicious Vector<Value> to MarkedValueList 2020-09-08 14:16:59 +02:00
Andreas Kling
d85eed585c LibJS: get_iterator_values() should pass Value to callback (not Value&)
Value& implies that the callback is expected/able to modify the value,
which is not the case.
2020-09-08 14:15:13 +02:00
AnotherTest
699e1fdc07 LibJS: Eliminate some (unnecessary) Vector copies 2020-09-08 13:43:03 +02:00
AnotherTest
8d9c5a8e70 LibJS: Make MarkedValueList inherit from Vector<Value>
This makes the nicer vector API available to MVL without extra wrapper
functions.
2020-09-08 13:43:03 +02:00
AnotherTest
9a00699983 LibJS: Format IndexedProperties.cpp 2020-09-08 13:43:03 +02:00
Linus Groh
55c4866370 LibJS: Add tests for issue #3382 2020-09-01 21:35:59 +02:00
Linus Groh
b27d90db1f LibJS: Actually change size in generic storage's set_array_like_size()
Looks like an oversight to me - we were not actually setting a new value
for m_array_size, which would cause arrays created with generic storage
to report a .length of 0.
2020-09-01 21:35:59 +02:00
Linus Groh
ae9d64e544 LibJS: Let set_array_like_size() switch to generic storage if necessary
This is already considered in put()/insert()/append_all() but not
set_array_like_size(), which crashed the interpreter with an assertion
when creating an array with more than SPARSE_ARRAY_THRESHOLD (200)
initial elements as the simple storage was being resized beyond its
limit.

Fixes #3382.
2020-09-01 21:35:59 +02:00
Ben Wiederhake
db422fa499 LibJS: Avoid unnecessary lambda
Especially when it's evaluated immediately and unconditionally.
2020-08-30 10:31:04 +02:00
Ben Wiederhake
d8e22fedc3 Libraries: Unbreak building with extra debug macros 2020-08-30 09:43:49 +02:00
AnotherTest
a2113909c3 LibJS: Do not consider un-labeled Block scopes as breakable 2020-08-28 20:19:56 +02:00
AnotherTest
8e89233bba LibJS: Demonstrate weird behaviour with 'break' 2020-08-28 20:19:56 +02:00
Ben Wiederhake
9f7ec33180 Meta: Force semi-colon after MAKE_AK_NONXXXABLE()
Before, we had about these occurrence counts:
COPY: 13 without, 33 with
MOVE: 12 without, 28 with

Clearly, 'with' was the preferred way. However, this introduced double-semicolons
all over the place, and caused some warnings to trigger.

This patch *forces* the usage of a semi-colon when calling the macro,
by removing the semi-colon within the macro. (And thus also gets rid
of the double-semicolon.)
2020-08-27 10:12:04 +02:00
Nico Weber
2c1b84b3e1 LibJS: Add some more tests, mostly around leap years 2020-08-26 08:52:07 +02:00
AnotherTest
394e4c04cd LibJS: Add a helper for calling JS::Function's with arguments
The fact that a `MarkedValueList` had to be created was just annoying,
so here's an alternative.
This patchset also removes some (now) unneeded MarkedValueList.h includes.
2020-08-26 08:45:01 +02:00
Nico Weber
e4dac38127 JS Tests: Disable the one failing test when running test-js in Serenity 2020-08-25 21:23:10 +02:00
Linus Groh
9ea6ef4ed1 LibJS: Make Interpreter::throw_exception() a void function
The motivation for this change is twofold:

- Returning a JS::Value is misleading as one would expect it to carry
  some meaningful information, like maybe the error object that's being
  created, but in fact it is always empty. Supposedly to serve as a
  shortcut for the common case of "throw and return empty value", but
  that's just leading us to my second point.
- Inconsistent usage / coding style: as of this commit there are 114
  uses of throw_exception() discarding its return value and 55 uses
  directly returning the call result (in LibJS, not counting LibWeb);
  with the first style often having a more explicit empty value (or
  nullptr in some cases) return anyway.
  One more line to always make the return value obvious is should be
  worth it.

So now it's basically always these steps, which is already being used in
the majority of cases (as outlined above):

- Throw an exception. This mutates interpreter state by updating
  m_exception and unwinding, but doesn't return anything.
- Let the caller explicitly return an empty value, nullptr or anything
  else itself.
2020-08-25 18:30:31 +02:00