Commit graph

16 commits

Author SHA1 Message Date
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
8d490aba76 LibJS: Implement console.assert() 2021-04-18 18:28:17 +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
da177c6517 LibJS: Make Errors fully spec compliant
The previous handling of the name and message properties specifically
was breaking websites that created their own error types and relied on
the error prototype working correctly - not assuming an JS::Error this
object, that is.

The way it works now, and it is supposed to work, is:

- Error.prototype.name and Error.prototype.message just have initial
  string values and are no longer getters/setters
- When constructing an error with a message, we create a regular
  property on the newly created object, so a lookup of the message
  property will either get it from the object directly or go though the
  prototype chain
- Internal m_name/m_message properties are no longer needed and removed

This makes printing errors slightly more complicated, as we can no
longer rely on the (safe) internal properties, and cannot trust a
property lookup either - get_without_side_effects() is used to solve
this, it's not perfect but something we can revisit later.

I did some refactoring along the way, there was some really old stuff in
there - accessing vm.call_frame().arguments[0] is not something we (have
to) do anymore :^)

Fixes #6245.
2021-04-12 09:38:57 +02:00
Linus Groh
55d9f1cced LibJS: Log any exception, not just the ones with a JS::Error value
This was super confusing as we would check if the exception's value is a
JS::Error and not log it otherwise, even with m_should_log_exceptions
set.

As a result, things like DOM exceptions were invisible to us with
execution just silently stopping, for example.
2021-04-03 16:34:34 +02:00
Linus Groh
f418115f1b LibJS: Add initial support for Promises
Almost a year after first working on this, it's finally done: an
implementation of Promises for LibJS! :^)

The core functionality is working and closely following the spec [1].
I mostly took the pseudo code and transformed it into C++ - if you read
and understand it, you will know how the spec implements Promises; and
if you read the spec first, the code will look very familiar.

Implemented functions are:

- Promise() constructor
- Promise.prototype.then()
- Promise.prototype.catch()
- Promise.prototype.finally()
- Promise.resolve()
- Promise.reject()

For the tests I added a new function to test-js's global object,
runQueuedPromiseJobs(), which calls vm.run_queued_promise_jobs().
By design, queued jobs normally only run after the script was fully
executed, making it improssible to test handlers in individual test()
calls by default [2].

Subsequent commits include integrations into LibWeb and js(1) -
pretty-printing, running queued promise jobs when necessary.

This has an unusual amount of dbgln() statements, all hidden behind the
PROMISE_DEBUG flag - I'm leaving them in for now as they've been very
useful while debugging this, things can get quite complex with so many
asynchronously executed functions.

I've not extensively explored use of these APIs for promise-based
functionality in LibWeb (fetch(), Notification.requestPermission()
etc.), but we'll get there in due time.

[1]: https://tc39.es/ecma262/#sec-promise-objects
[2]: https://tc39.es/ecma262/#sec-jobs-and-job-queues
2021-04-02 10:47:40 +02:00
Linus Groh
0b799dd3b7 LibJS: VERIFY(!this_value.is_empty()) in VM::call_internal()
Just a sanity check, this must never happen. Manual invocations of
call() e.g. in LibWeb bindings must pass js_undefined() if no specific
this value is desired, which OrdinaryCallBindThis will then use as-is or
turn into the global this value in non-strict mode.
2021-03-26 22:59:47 +01:00
Andreas Kling
1603623772 LibJS: Move AST node stack from VM to Interpreter 2021-03-21 16:02:11 +01:00
Andreas Kling
9e6d0dd879 LibJS: Always synthesize "arguments" object when there's a callee
Instead of counting the number of call frames on the VM stack, we now
always fake the "arguments" object when the current call frame has
a callee value.

This fixes an issue with DOM event handlers in LibWeb not being able
to access "arguments" since they were called without an outer frame.
2021-03-17 21:54:52 +01:00
Linus Groh
8e84ca6b16 LibJS: Don't apply arguments object hack to global execution context
Checking for the existence of a call frame is not enough to check if
we're in a function call, as the global execution context is a regular
call frame as well.

Found by OSS-Fuzz, where simply accessing "arguments" in the global
scope would crash due to call_frame().callee being an empty value
(https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32115).
2021-03-16 18:48:25 +01:00
Andreas Kling
8062fc711c LibJS: Add arguments.callee to our hack arguments object
arguments.callee refers to the currently executing function.
2021-03-15 21:20:33 +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
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
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Renamed from Libraries/LibJS/Runtime/VM.cpp (Browse further)