Commit graph

54 commits

Author SHA1 Message Date
Linus Groh
ccdfa2320c LibJS: Replace GlobalObject with VM in Iterator AOs [Part 7/19] 2022-08-23 13:58:30 +01:00
Linus Groh
a022e548b8 LibJS: Replace GlobalObject with VM in Value AOs [Part 4/19]
This is where the fun begins. :^)
2022-08-23 13:58:30 +01:00
Linus Groh
999da617c5 LibJS: Remove GlobalObject from VM::this_value()
This is a continuation of the previous six commits.

The global object is only needed to return it if the execution context
stack is empty, but that doesn't seem like a useful thing to allow in
the first place - if you're not currently executing JS, and the
execution context stack is empty, there is no this value to retrieve.
2022-08-23 13:58:30 +01:00
Linus Groh
f3117d46dc LibJS: Remove GlobalObject from VM::throw_completion()
This is a continuation of the previous five commits.

A first big step into the direction of no longer having to pass a realm
(or currently, a global object) trough layers upon layers of AOs!
Unlike the create() APIs we can safely assume that this is only ever
called when a running execution context and therefore current realm
exists. If not, you can always manually allocate the Error and put it in
a Completion :^)

In the spec, throw exceptions implicitly use the current realm's
intrinsics as well: https://tc39.es/ecma262/#sec-throw-an-exception
2022-08-23 13:58:30 +01:00
Linus Groh
b99cc7d050 LibJS+LibWeb: Replace GlobalObject with Realm in create() functions
This is a continuation of the previous two commits.

As allocating a JS cell already primarily involves a realm instead of a
global object, and we'll need to pass one to the allocate() function
itself eventually (it's bridged via the global object right now), the
create() functions need to receive a realm as well.
The plan is for this to be the highest-level function that actually
receives a realm and passes it around, AOs on an even higher level will
use the "current realm" concept via VM::current_realm() as that's what
the spec assumes; passing around realms (or global objects, for that
matter) on higher AO levels is pointless and unlike for allocating
individual objects, which may happen outside of regular JS execution, we
don't need control over the specific realm that is being used there.
2022-08-23 13:58:30 +01:00
Linus Groh
5dd5896588 LibJS+LibWeb: Replace GlobalObject with Realm in initialize() functions
This is a continuation of the previous commit.

Calling initialize() is the first thing that's done after allocating a
cell on the JS heap - and in the common case of allocating an object,
that's where properties are assigned and intrinsics occasionally
accessed.
Since those are supposed to live on the realm eventually, this is
another step into that direction.
2022-08-23 13:58:30 +01:00
Linus Groh
ecd163bdf1 LibJS+LibWeb: Replace GlobalObject with Realm in object constructors
No functional changes - we can still very easily get to the global
object via `Realm::global_object()`. This is in preparation of moving
the intrinsics to the realm and no longer having to pass a global
object when allocating any object.
In a few (now, and many more in subsequent commits) places we get a
realm using `GlobalObject::associated_realm()`, this is intended to be
temporary. For example, create() functions will later receive the same
treatment and are passed a realm instead of a global object.
2022-08-23 13:58:30 +01:00
Lenny Maiorani
d00b79568f Libraries: Use default constructors/destructors in LibJS
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules

"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
2022-03-16 16:19:40 +00:00
Timothy Flynn
59ca435172 LibJS: Use new construct AO overload where easily applicable 2022-01-25 22:09:13 +00:00
mjz19910
1ef633472b Everywhere: Convert VM::call() to JS::call() 2022-01-23 15:24:45 +00:00
Linus Groh
09a11fa6ea LibJS: Implement proper Iterator records
Instead of using plain objects as Iterator records, causes confusion
about the object itself actually being its [[Iterator]] slot, and
requires non-standard type conversion shenanigans fpr the [[NextValue]]
and [[Done]] internal slots,  implement a proper Iterator record struct
and use it throughout.

Also annotate the remaining Iterator AOs with spec comments while we're
here.
2022-01-09 22:02:43 +01:00
Idan Horowitz
36aef8ee95 LibJS: Convert ArrayConstructor functions to ThrowCompletionOr 2021-10-23 02:49:41 +03:00
Idan Horowitz
e26d9f419b LibJS: Remove vm.construct and it's usages 2021-10-23 02:49:41 +03:00
Idan Horowitz
db5df26841 LibJS: Convert Array AOs to ThrowCompletionOr 2021-10-22 15:07:04 +03:00
Linus Groh
5832de62fe LibJS: Convert NativeFunction::{call,construct}() to ThrowCompletionOr
Both at the same time because many of them call construct() in call()
and I'm not keen on adding a bunch of temporary plumbing to turn
exceptions into throw completions.
Also changes the return value of construct() to Object* instead of Value
as it always needs to return an object; allowing an arbitrary Value is a
massive foot gun.
2021-10-21 09:02:23 +01:00
Timothy Flynn
ec54a7b5b0 LibJS: Implement IteratorClose with Completions and align to the spec 2021-10-21 00:26:45 +01:00
Timothy Flynn
7b4814f74c LibJS: Convert IteratorValue AO to ThrowCompletionOr 2021-10-21 00:26:45 +01:00
Timothy Flynn
8be1caa05d LibJS: Convert IteratorStep AO to ThrowCompletionOr 2021-10-21 00:26:45 +01:00
Timothy Flynn
860a37640b LibJS: Convert GetIterator AO to ThrowCompletionOr 2021-10-21 00:26:45 +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
20163c0584 LibJS: Add ThrowCompletionOr versions of the JS native function macros
The old versions were renamed to JS_DECLARE_OLD_NATIVE_FUNCTION and
JS_DEFINE_OLD_NATIVE_FUNCTION, and will be eventually removed once all
native functions were converted to the new format.
2021-10-20 12:27:19 +01:00
Idan Horowitz
56e769e4ba LibJS: Replace usages of JS_{DECLARE, DEFINE}_NATIVE_GETTER
These macros are equivalent to JS_{DECLARE, DEFINE}_NATIVE_FUNCTION and
were only sometimes used, so let's just get rid of them altogether.
2021-10-20 12:27:19 +01:00
Idan Horowitz
cc94bba5c0 LibJS: Convert to_u32() to ThrowCompletionOr 2021-10-18 08:01:38 +03:00
Linus Groh
52976bfac6 LibJS: Convert to_object() to ThrowCompletionOr 2021-10-13 09:55:10 +01:00
Linus Groh
364dd42fc8 LibJS: Convert create_data_property_or_throw() to ThrowCompletionOr 2021-10-03 20:14:03 +01:00
Linus Groh
1d45541278 LibJS: Convert Object::set() 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
Idan Horowitz
5f80d8245d LibJS: Close iterator on throw completion in Array.from
This regressed in #10190
2021-09-24 02:28:17 +03:00
Idan Horowitz
99bc429f3f LibJS: Add missing exception checks to {Array, TypedArray}.from() 2021-09-24 02:28:17 +03:00
Idan Horowitz
ee825d6d9e LibJS: Convert get_method to ThrowCompletionOr 2021-09-23 23:59:13 +03:00
Idan Horowitz
ab594e5f2f LibJS: Convert Value::invoke and VM::call to ThrowCompletionOr 2021-09-23 23:59:13 +03:00
Idan Horowitz
1db7e096e2 LibJS: Switch is_array to ThrowCompletionOr 2021-09-23 23:59:13 +03:00
Idan Horowitz
e90e4ac1e2 LibJS: Convert length_of_array_like to ThrowCompletionOr 2021-09-21 23:28:38 +03: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
Idan Horowitz
8d01d43f5e LibJS: Replace the boolean argument of Object::set with an enum class
This is more serenity-esque and also makes pointing out missing
exception checks during reviews much easier.
2021-07-16 17:50:01 +01:00
Idan Horowitz
eeb4c1eec9 LibJS: Reorder and add missing name & length properties to Built-ins
The specification dicatates that each built-in will have a length and
name property. (defined in that order)
2021-07-08 01:45:15 +01:00
Idan Horowitz
a6b8291a9b LibJS: Add define_direct_property and remove the define_property helper
This removes all usages of the non-standard define_property helper
method and replaces all it's usages with the specification required
alternative or with define_direct_property where appropriate.
2021-07-06 14:20:30 +01:00
Linus Groh
09bd5f8772 LibJS: Rewrite most of Object for spec compliance :^)
This is a huge patch, I know. In hindsight this perhaps could've been
done slightly more incremental, but I started and then fixed everything
until it worked, and here we are. I tried splitting of some completely
unrelated changes into separate commits, however. Anyway.

This is a rewrite of most of Object, and by extension large parts of
Array, Proxy, Reflect, String, TypedArray, and some other things.

What we already had worked fine for about 90% of things, but getting the
last 10% right proved to be increasingly difficult with the current code
that sort of grew organically and is only very loosely based on the
spec - this became especially obvious when we started fixing a large
number of test262 failures.

Key changes include:

- 1:1 matching function names and parameters of all object-related
  functions, to avoid ambiguity. Previously we had things like put(),
  which the spec doesn't have - as a result it wasn't always clear which
  need to be used.
- Better separation between object abstract operations and internal
  methods - the former are always the same, the latter can be overridden
  (and are therefore virtual). The internal methods (i.e. [[Foo]] in the
  spec) are now prefixed with 'internal_' for clarity - again, it was
  previously not always clear which AO a certain method represents,
  get() could've been both Get and [[Get]] (I don't know which one it
  was closer to right now).
  Note that some of the old names have been kept until all code relying
  on them is updated, but they are now simple wrappers around the
  closest matching standard abstract operation.
- Simplifications of the storage layer: functions that write values to
  storage are now prefixed with 'storage_' to make their purpose clear,
  and as they are not part of the spec they should not contain any steps
  specified by it. Much functionality is now covered by the layers above
  it and was removed (e.g. handling of accessors, attribute checks).
- PropertyAttributes has been greatly simplified, and is being replaced
  by PropertyDescriptor - a concept similar to the current
  implementation, but more aligned with the actual spec. See the commit
  message of the previous commit where it was introduced for details.
- As a bonus, and since I had to look at the spec a whole lot anyway, I
  introduced more inline comments with the exact steps from the spec -
  this makes it super easy to verify correctness.
- East-const all the things.

As a result of all of this, things are much more correct but a bit
slower now. Retaining speed wasn't a consideration at all, I have done
no profiling of the new code - there might be low hanging fruits, which
we can then harvest separately.

Special thanks to Idan for helping me with this by tracking down bugs,
updating everything outside of LibJS to work with these changes (LibWeb,
Spreadsheet, HackStudio), as well as providing countless patches to fix
regressions I introduced - there still are very few (we got it down to
5), but we also get many new passing test262 tests in return. :^)

Co-authored-by: Idan Horowitz <idan.horowitz@gmail.com>
2021-07-04 22:07:36 +01:00
Idan Horowitz
e480d69130 LibJS: Bring ArrayCreate and ArrayConstructor closer to spec
Specifically, this now explicitly takes the length, adds missing
exceptions checks to calls with user-supplied lengths, takes and uses
the prototype argument, and fixes some spec non-conformance in
ArrayConstructor and its native functions around the use of ArrayCreate
2021-07-04 00:51:43 +01:00
Idan Horowitz
5f09d78b9d LibJS: Bring the Array constructor slightly closer to the specification
Specifically, we now cast to a u32 instead of an i32, as well as use
the validity check required by the specification. The current
constructor is still quite far from the specification, as we directly
set the indexed properties' length instead of going through the Array's
overriden DefineOwnProperty. (and as a result the checks imposed by the
ArraySetLength abstract operation)
2021-06-30 12:35:24 +01:00
Idan Horowitz
1d94d7a367 LibJS: Make Array.of(...items) generic
As well as bring it generally closer to the specification.
2021-06-29 16:03:21 +01:00
Idan Horowitz
581f20e6f2 LibJS: Accept FlyStrings in the NativeFunction constructors
This makes the implicit run-time assertion in PropertyName::to_string()
into an explicit compile-time requirement, removes a wasteful FlyString
-> PropertyName -> FlyString construction from NativeFunction::create()
and allows setting the function name to a null string for anonymous
native functions.
2021-06-28 08:55:14 +01:00
Andreas Kling
ba9d5c4d54 LibJS: Rename Function => FunctionObject 2021-06-27 22:36:04 +02:00
Linus Groh
f4867572b7 LibJS: Change PropertyName(Symbol*) => PropertyName(Symbol&)
Requires a bunch of find-and-replace updates across LibJS, but
constructing a PropertyName from a nullptr Symbol* should not be
possible - let's enforce this at the compiler level instead of using
VERIFY() (and already dereference Symbol pointers at the call site).
2021-06-25 22:01:23 +01:00
Idan Horowitz
9127d83927 LibJS: Rename Value::{is_integer => is_integral_number}
The implementation matches the specification, so lets match the name
as well. :^)
2021-06-16 12:57:55 +01:00
Linus Groh
7327a28ccc LibJS: Add ECMA-262 section/title/URL comments almost everywhere
As mentioned on Discord earlier, we'll add these to all new functions
going forward - this is the backfill. Reasons:

- It makes you look at the spec, implementing based on MDN or V8
  behavior is a no-go
- It makes finding the various functions that are non-compliant easier,
  in the future everything should either have such a comment or, if it's
  not from the spec at all, a comment explaining why that is the case
- It makes it easier to check whether a certain abstract operation is
  implemented in LibJS, not all of them use the same name as the spec.
  E.g. RejectPromise() is Promise::reject()
- It makes it easier to reason about vm.arguments(), e.g. when the
  function has a rest parameter
- It makes it easier to see whether a certain function is from a
  proposal or Annex B

Also:

- Add arguments to all functions and abstract operations that already
  had a comment
- Fix some outdated section numbers
- Replace some ecma-international.org URLs with tc39.es
2021-06-13 00:33:28 +01:00
Idan Horowitz
a1f5357ad3 LibJS: Expose Symbol.species properties as getters
As required by the specification.
2021-06-12 00:44:15 +01:00
Linus Groh
83be39c91a LibJS: Handle Proxy with Array target in IsArray() abstract operation
This was missing from Value::is_array(), which is equivalent to the
spec's IsArray() abstract operation - it treats a Proxy value with an
Array target object as being an Array.
It can throw, so needs both the global object and an exception check
now.
2021-06-08 23:53:13 +02:00
Idan Horowitz
aefb7995f1 LibJS: Add the Symbol.species getter to the appropriate built-ins 2021-06-08 09:09:51 +01:00
Linus Groh
ebdeed087c Everywhere: Use linusg@serenityos.org for my copyright headers 2021-04-22 22:51:19 +02:00