1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-10 01:27:35 +00:00
Commit graph

3395 commits

Author SHA1 Message Date
Linus Groh
9555ca99a0 LibJS: Remove unnecessary value_or() from get()
Object::get() never returns an empty value anymore, as per the spec, so
having a value_or() fallback is no longer needed.
2021-07-05 00:03:25 +02:00
Linus Groh
57f7e6e775 LibJS: Remove two unnecessary 'vm.argument(0).value_or(js_undefined())'
VM::argument() never returns an empty value.
2021-07-05 00:03:25 +02: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
Linus Groh
777a93918f LibJS: Handle invalid and symbol PropertyName in its AK::Formatter
This would previously crash as we used to_string() without checking the
type first. Circumvent that by handling invalid and numeric ones
separately and then using to_string_or_symbol().
2021-07-04 22:07:36 +01:00
Linus Groh
c81001f920 LibJS: Add Value::operator==()
This is needed for MarkedValueList::contains_slow() to work.
2021-07-04 22:07:36 +01:00
Linus Groh
bb1a98d809 LibJS: Add new PropertyDescriptor class and related abstract operations
This is an implementation of 'The Property Descriptor Specification
Type' and related abstract operations, namely:

- IsAccessorDescriptor
- IsDataDescriptor
- IsGenericDescriptor
- FromPropertyDescriptor
- ToPropertyDescriptor
- CompletePropertyDescriptor

It works with Optional<T> to enable omitting certain fields, which will
eventually replace the Attribute::Has{Getter,Setter,Configurable,
Enumerable,Writable} bit flags, which are awkward to work with - being
able to use an initializer list with any of the possible attributes is
much more convenient.

Parts of the current PropertyAttributes implementation as well as the
much simpler PropertyDescriptor struct in Object.h will eventually be
replaced with this and completely go away.

Property storage will still use the PropertyAttributes bit flags, this
is for the layers above.

Note that this is currently guarded behind an #if 0 as if conflicts with
the existing PropertyDescriptor struct, but it's known to compile and
work just fine - I simply want to have this in a separate commit, the
primary object rewrite commit will be large enough as is.
2021-07-04 22:07:36 +01:00
Linus Groh
a3c8ebd709 LibJS: VERIFY() that property name is valid in Value::get{,_method}() 2021-07-04 22:07:36 +01:00
Idan Horowitz
301c1a3a58 Everywhere: Fix incorrect usages of AK::Checked
Specifically, explicitly specify the checked type, use the resulting
value instead of doing the same calculation twice, and break down
calculations to discrete operations to ensure no intermediary overflows
are missed.
2021-07-04 20:08:28 +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
5ee1ae37b2 LibJS: Add the IteratorStep abstract iterator operation
As well as add 2 missing exception checks in the IteratorComplete and
IteratorValue abstract iterator operations.
2021-07-04 00:51:43 +01:00
Andreas Kling
e8430cf0d3 LibJS: Don't allow delete super.property
This should throw a ReferenceError, since `delete` is not allowed
on super references.
2021-07-03 01:30:30 +02:00
Andreas Kling
1270df257b LibJS: Bring the super keyword in line with the spec
This patch implements spec-compliant runtime semantics for the following
constructs:

- super.property
- super[property]

The MakeSuperPropertyReference AO is added to support this. :^)
2021-07-03 01:12:12 +02:00
Andreas Kling
fd43d1e205 LibJS: Improve ResolveBinding + add GetIdentifierReference
ResolveBinding now matches the spec, while the non-conforming parts
are moved to GetIdentifierReference.

Implementing this properly requires variable bindings.
2021-07-02 22:22:21 +02:00
Andreas Kling
5ce9305c5f LibJS: Implement the PrepareForOrdinaryCall abstract operation
This is used by VM::call_internal() and VM::construct() which roughly
map to function objects' [[Call]] and [[Construct]] slots in the spec.

Reorganizing this code revealed something weird: NativeFunction gets
its strictness by checking VM::in_strict_mode(). In other words,
it inherits the strict flag from the caller context. This is quite
weird, but many test-js tests rely on it, so let's preserve it until
we can think of something nicer.
2021-07-02 21:44:08 +02:00
Idan Horowitz
f8f3ff65fe LibJS: Bring %TypedArray%.prototype.set slightly closer to spec
Specifically, instead of using the internal {get, put}_by_index methods
we now use the GetValueFromBuffer and SetValueInBuffer abstract
operations, as required by the specification.

While i was here i also replaced a couple custom detached array buffer
error messages with the existing ErrorType::DetachedArrayBuffer.
2021-07-02 15:53:51 +01:00
Ali Mohammad Pur
62ca81fdcc LibJS: Implement the %TypedArray%.set() function 2021-07-02 04:53:01 +04:30
Andreas Kling
a4897ed7b2 LibJS: Throw on failed PutValue into an environment reference
This should really be handled at a different layer of the stack, but
this allows us to make progress on the Object rewrite without breaking
strict mode assignment tests.
2021-07-02 00:32:23 +02:00
Andreas Kling
80170887db LibJS: Make Environment::put_into_environment() return a success bool
This code is non-conforming and will eventually get cleaned out once
we implement proper variable bindings. However, this will aid us in
improving other parts of the code right now.
2021-07-02 00:26:31 +02:00
Andreas Kling
57db058652 LibJS: Make ResolveBinding() produce strict References in strict mode 2021-07-02 00:25:52 +02:00
Idan Horowitz
648b4c7d74 LibJS: Bring JSON.parse slightly closer to the specification
This PR does not fix the main issue with our current implementation:
The specification requires that we first check the JSON string for
validity with an ECMA-404 compliant parser, and then evaluate it as if
it was javascript code, of which we do neither at the moment.
2021-07-01 14:14:41 +01:00
Andreas Kling
0fa141d058 LibJS: Move Binding struct into the DeclarativeEnvironment class
Nobody on the outside needs to access this.
2021-07-01 12:31:39 +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
Idan Horowitz
8d50cf492e LibJS: Bring JSON.stringify closer to the specification 2021-07-01 11:44:37 +02:00
Idan Horowitz
e37f96ccfe LibJS: Stop coercing this to object in Function's Symbol.hasInstance 2021-07-01 11:35:16 +02:00
Idan Horowitz
6ef56f79bd LibJS: Stop coercing Date.prototype[Symbol.toPrimitive] hint to string 2021-07-01 09:55:50 +01:00
Idan Horowitz
7a1a91d7f2 LibJS: Check for DataView in ArrayBuffer.isView() 2021-07-01 09:20:00 +01:00
Idan Horowitz
dfed8f61cb LibJS: Use the GetFunctionRealm abstract-op in ArraySpeciesCreate 2021-06-30 18:41:32 +01:00
Idan Horowitz
c254e4cf10 LibJS: Get the prototype of a new String from the constructor's realm 2021-06-30 18:41:32 +01:00
Idan Horowitz
5606332ed7 LibJS: Add a [[Realm]] getter to FunctionObject and use it where needed
Defined by https://tc39.es/ecma262/#sec-ordinaryfunctioncreate step #17
and by https://tc39.es/ecma262/#sec-createbuiltinfunction step #6.
2021-06-30 18:41:32 +01:00
Idan Horowitz
38b8fa8f3e LibJS: Ensure shift values in left_shift are modded by 32
This is equivalent to 58d6a2d0192b7860ecb2edb4aa5d36b389213a15 but for
the left shift operation.
2021-06-30 19:06:01 +02:00
davidot
7a3b057a20 LibJS: Add String.prototype.split using the @@split methods on object 2021-06-30 16:08:00 +01:00
davidot
36668893a6 LibJS: Add String.prototype.indexOf position argument 2021-06-30 16:08:00 +01:00
Idan Horowitz
7d055dd039 LibJS: Optimize & Bring String.prototype.repeat closer to the spec
Specifically, we immediately return an empty string when `this` is an
empty string, instead of wasting time in a loop doing nothing N times.
2021-06-30 14:01:25 +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
davidot
fc9cc74555 LibJS: Handle the different realms case in ArraySpeciesCreate 2021-06-29 23:34:06 +01:00
Idan Horowitz
3cfe1a8914 LibJS: Support the radix argument in BigInt.prototype.toString 2021-06-29 16:55:54 +01:00
Idan Horowitz
005d75656e LibCrypto: Replace from_base{2,8,10,16}() & to_base10 with from_base(N)
This allows us to support parsing and serializing BigIntegers to and
from any base N (such that 2 <= N <= 36).
2021-06-29 16:55:54 +01:00
Idan Horowitz
12e66de410 LibJS: Check the target function of a bound function in is_constructor
This is not exactly compliant with the specification, but our current
bound function implementation isn't either, so its not currently
possible to implement it the way the specification requires.
2021-06-29 16:03:21 +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
Leon Albrecht
57b7f4ec5b
LibJS: Mark FunctionObject::is_ordinary_function() as override 2021-06-28 19:25:35 +02:00
Andreas Kling
2d4eb40f59 LibJS: Add the CreateMappedArgumentsObject abstract operation
This patch adds a new ArgumentsObject class to represent what the spec
calls "Arguments Exotic Objects"

These are constructed by the new CreateMappedArgumentsObject when the
`arguments` identifier is resolved in a callee context.

The implementation is incomplete and doesn't yet support mapping of
the parameter variables to the indexed properties of `arguments`.
2021-06-28 16:52:20 +02:00
Idan Horowitz
8eb48039c9 LibJS: Bring Reflect.construct() closer to the specification
This includes checking that the target is a constructor, not just a
function, as well as switching the order of the list creation and
argument validation to match the specification, to ensure correct
exception throwing order.
2021-06-28 14:22:35 +01:00
Idan Horowitz
596324ae9c LibJS: Rewrite String.raw() closer to the specification
This includes not throwing a custom exception and using the
length_of_array_like abstract operation where required.
2021-06-28 13:27:13 +01:00
Andreas Kling
d1ffeaf66d LibJS: Use CreateUnmappedArgumentsObject for non-simple parameter lists
This patch implements the IsSimpleParameterList static semantics for
ordinary function objects.

We now also create an unmapped arguments object for callee contexts
with non-simple parameter lists, instead of only doing it in strict
mode. Covered by test262.
2021-06-28 12:18:58 +02:00
Idan Horowitz
e2e695bc9f LibJS: Add and use the %ThrowTypeError% intrinsic 2021-06-28 08:55:14 +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
Idan Horowitz
a939ffc617 LibJS: Handle values close to -0.5 correctly in Math.round(x)
This is done by just using the built-in ceiling and subtracting from
the result if its in the 0.5 range.
2021-06-28 01:19:11 +01:00
Andreas Kling
9eed7444de LibJS: Implement the CreateUnmappedArgumentsObject abstract operation 2021-06-28 02:00:46 +02:00
Andreas Kling
cd53d046b2 LibJS: Fix typo "sweeped" => "swept" everywhere 2021-06-27 22:40:49 +02:00
Andreas Kling
1bd52ce789 LibJS: Stop qualifying AK::Function
Now that JS function objects are JS::FunctionObject, we can stop
qualifying AK::Function and just say "Function" everywhere. Nice. :^)
2021-06-27 22:40:49 +02:00