Commit graph

42 commits

Author SHA1 Message Date
Andreas Kling
c8270dbe2e LibJS: Rename ScriptFunction => OrdinaryFunctionObject
These are basically what the spec calls "ordinary function objects",
so let's have the name reflect that. :^)
2021-06-27 22:36:04 +02:00
Andreas Kling
9683b10aec LibJS: Make sure this in the global environment is the global object
Fixes regressed with 0f9038b732.
2021-06-26 17:06:36 +02:00
Anonymous
2822da8c8f LibJS: Correct behaviour of direct vs. indirect eval
eval only has direct access to the local scope when accessed through
the name eval. This includes locals named eval, because of course it
does.
2021-06-23 09:38:33 +01:00
Andreas Kling
1f8b6ac3c3 LibJS: Begin implementing GlobalEnvironmentRecord
These represent the outermost scope in the environment record
hierarchy. The spec says they should be a "composite" of two things:

- An ObjectEnvironmentRecord wrapping the global object
- A DeclarativeEnvironmentRecord for other declarations

It's not yet clear to me how this should work, so this patch only
implements the first part, an object record wrapping the global object.
2021-06-22 18:44:53 +02:00
Andreas Kling
1d20380859 LibJS: Split the per-call-frame environment into lexical and variable
To better follow the spec, we need to distinguish between the current
execution context's lexical environment and variable environment.

This patch moves us to having two record pointers, although both of
them point at the same environment records for now.
2021-06-22 18:44:53 +02:00
Andreas Kling
aabd82d508 LibJS: Bring function environment records closer to the spec
This patch adds FunctionEnvironmentRecord as a subclass of the existing
DeclarativeEnvironmentRecord. Things that are specific to function
environment records move into there, simplifying the base.

Most of the abstract operations related to function environment records
are rewritten to match the spec exactly. I also had to implement
GetThisEnvironment() and GetSuperConstructor() to keep tests working
after the changes, so that's nice as well. :^)
2021-06-22 18:44:53 +02:00
Andreas Kling
d407f247b7 LibJS: Rename virtuals in EnvironmentRecord
This patch makes the following renames:

- get_from_scope() => get_from_environment_record()
- put_to_scope() => put_into_environment_record()
- delete_from_scope() => delete_from_environment_record()
2021-06-21 23:49:50 +02:00
Andreas Kling
6c6dbcfc36 LibJS: Rename Environment Records so they match the spec :^)
This patch makes the following name changes:

- ScopeObject => EnvironmentRecord
- LexicalEnvironment => DeclarativeEnvironmentRecord
- WithScope => ObjectEnvironmentRecord
2021-06-21 23:49:50 +02:00
Matthew Olsson
22b17219ff LibJS: Add the remaining generator objects
- %GeneratorFunction%
- %GeneratorFunction.prototype%
- %GeneratorFunction.prototype.prototype%
- %Generator%.prototype
2021-06-19 00:04:57 +01:00
Idan Horowitz
de9fa6622a LibJS: Add the FinalizationRegistry built-in object
As well as the needed functionality in VM to enqueue and run cleanup
jobs for the FinalizationRegistry instances.
2021-06-15 23:59:21 +01:00
Idan Horowitz
e4d267d4fb LibJS: Add the DataView built-in object 2021-06-14 01:45:04 +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
322c8a3995 LibJS: Add the MapIterator built-in and the key/values/entries methods
While this implementation should be complete it is based on HashMap's
iterator, which currently follows bucket-order instead of the required
insertion order. This can be simply fixed by replacing the underlying
HashMap member in Map with an enhanced one that maintains a linked
list in insertion order.
2021-06-13 00:33:18 +01:00
Idan Horowitz
a96ac8bd56 LibJS: Add the Map built-in object 2021-06-13 00:33:18 +01:00
Idan Horowitz
7eba63a8a3 LibJS: Add the WeakRef built-in object 2021-06-12 18:39:23 +01:00
Idan Horowitz
39554f3787 LibJS: Add the WeakMap built-in object 2021-06-12 10:44:28 +01:00
Linus Groh
1d7514d51e LibJS: Hide gc() dbgln() behind #ifdef __serenity__
This spams to stdout when using Lagom, and is therefore included in
test-js output. Don't need that.
2021-06-12 01:09:45 +01:00
Linus Groh
cbd7437d40 LibJS: Implement AggregateError 2021-06-11 18:49:50 +01:00
Linus Groh
ad3242bab7 LibJS: Rename JS_ENUMERATE_{ERROR_SUBCLASSES => NATIVE_ERRORS}
The fact that they *are* subclasses is an implementation detail and
should not be highlighted. The spec calls these NativeErrors, so let's
use that.
Also added a comment explaining *why* they inherit from Error - I was
about to change that :^)
2021-06-11 18:49:50 +01:00
Idan Horowitz
8b6beac5ce LibJS: Add the WeakSet built-in object 2021-06-09 21:52:25 +01:00
Idan Horowitz
2a3090d292 LibJS: Add the SetIterator built-in and Set.prototype.{values, entries}
While this implementation should be complete it is based on HashTable's
iterator, which currently follows bucket-order instead of the required
insertion order. This can be simply fixed by replacing the underlying
HashTable member in Set with an enhanced one that maintains a linked
list in insertion order.
2021-06-09 11:48:04 +01:00
Idan Horowitz
670be04c81 LibJS: Add the Set built-in object 2021-06-09 11:48:04 +01:00
Idan Horowitz
064ed8279e LibJS: Support deleting local variables with operator delete
To make this cleaner i also moved the logic into Reference::delete_.
2021-06-08 15:31:46 +01:00
Idan Horowitz
af58779def LibJS: Return undefined from a with statement if no value was generated
Co-authored-by: Linus Groh <mail@linusgroh.de>
2021-06-08 15:31:46 +01:00
Idan Horowitz
bbf75d0bea LibJS: Trim initial whitespace in parseFloat 2021-06-06 01:34:22 +01:00
Idan Horowitz
bda32e9440 LibJS: Parse digits with parse_ascii_base36_digit in parseInt
This was accidentally replaced with parse_ascii_hex_digit in
bc8d16ad28 which caused radices above
16 (hex) to fail.
2021-06-06 01:34:22 +01:00
Idan Horowitz
26a0dbdd9e LibJS: Set the length property of parseInt to 2
The method takes 2 arguments
2021-06-06 01:34:22 +01:00
Idan Horowitz
442ef63008 LibJS: Add the global escape() & unescape() methods 2021-06-05 18:55:08 +01:00
Max Wipfli
bc8d16ad28 Everywhere: Replace ctype.h to avoid narrowing conversions
This replaces ctype.h with CharacterType.h everywhere I could find
issues with narrowing conversions. While using it will probably make
sense almost everywhere in the future, the most critical places should
have been addressed.
2021-06-03 13:31:46 +02:00
Andreas Kling
12a42edd13 Everywhere: codepoint => code point 2021-06-01 10:01:11 +02:00
Linus Groh
7b1ba4bd5c LibJS: Fallback to undefined if last value in eval() is empty
For something like eval(""), the VM's 'last value' is an empty value,
which we must not leak.

Fixes #6643.
2021-04-25 22:52:19 +02:00
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
Idan Horowitz
ba77b40808 LibJS: Implement the encode/decodeURI(Component) family of functions
These are generally useful and in particular needed for twitter.com
2021-04-14 13:30:10 +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
Andreas Kling
60e630d5a0 LibJS: eval(x) should return x without evaluation if x is not a string 2021-03-17 20:57:29 +01:00
Andreas Kling
d792200a55 LibJS: Rename GlobalObject::initialize() => initialize_global_object()
This function was shadowing Object::initialize() which cannot be called
on global objects and has a different set of parameters.
2021-03-17 16:53:35 +01:00
Linus Groh
d6239b691f LibJS: Throw SyntaxError in eval() when parser has error(s) 2021-03-15 22:43:27 +01:00
Andreas Kling
45e6b5e601 LibJS: Make eval() return the last value from the executed statement
This is kinda awkward but since the statement we're executing is
actually a JS::Program, we have to get the result via VM::last_value().
2021-03-15 21:43:40 +01:00
Andreas Kling
4da3e5d91f LibJS: Add naive implementation of eval() :^)
This parses and executes a code string in the caller's lexical scope.
2021-03-15 21:20:33 +01:00
Andreas Kling
7df3b95126 LibJS: GlobalObject must mark builtin prototypes
Failing to mark them leads to use-after-free since the GlobalObject
cached prototypes are used for new NumberObject, StringObject, etc.

Found by oss-fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30319
2021-02-05 14:53:16 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Renamed from Libraries/LibJS/Runtime/GlobalObject.cpp (Browse further)