Commit graph

58 commits

Author SHA1 Message Date
Timothy Flynn
5fe0d3352d LibJS: Implement the Temporal.Duration constructor
This also includes a stubbed Temporal.Duration.prototype.

Until we have re-implemented Temporal.PlainDate/ZonedDateTime, some of
Temporal.Duration.compare (and its invoked AOs) are left unimplemented.
2024-11-20 19:04:30 -05:00
Timothy Flynn
f7517c5b8d LibJS: Remove our existing Temporal implementation
Our Temporal implementation is woefully out of date. The spec has been
so vastly rewritten that it is unfortunately not practical to update our
implementation in-place. Even just removing Temporal objects that were
removed from the spec, or updating any of the simpler remaining objects,
has proven to be a mess in previous attempts.

So, this removes our Temporal implementation. AOs used by other specs
are left intact.
2024-11-20 19:04:30 -05:00
Shannon Booth
f87041bf3a LibGC+Everywhere: Factor out a LibGC from LibJS
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
2024-11-15 14:49:20 +01:00
Shannon Booth
c2988a7dd5 LibJS: Don't directly teach the heap about the javascript VM or Realm
Instead, smuggle it in as a `void*` private data and let Javascript
aware code cast out that pointer to a VM&.

In order to make this split, rename JS::Cell to JS::CellImpl. Once we
have a LibGC, this will become GC::Cell. CellImpl then has no specific
knowledge of the VM& and Realm&. That knowledge is instead put into
JS::Cell, which inherits from CellImpl. JS::Cell is responsible for
JavaScript's realm initialization, as well as converting of the void*
private data to what it knows should be the VM&.
2024-11-14 15:38:45 +01:00
Shannon Booth
0bf2a8362a LibJS: Make Value inherit from a NanBoxedValue
NanBoxedValue is intended to be a GC-allocatable type which is not
specific to javascript, towards the effort of factoring out the GC
implementation from LibJS.
2024-11-14 15:38:45 +01:00
rmg-x
ea20545853 LibJS: Add support for Float16Array
Implements TC39 stage three proposal for Float16Arrays:
https://tc39.es/proposal-float16array
2024-11-10 14:48:20 -07:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Lenny Maiorani
765936ebae
Everywhere: Switch from (void) to [[maybe_unused]] (#4473)
Problem:
- `(void)` simply casts the expression to void. This is understood to
  indicate that it is ignored, but this is really a compiler trick to
  get the compiler to not generate a warning.

Solution:
- Use the `[[maybe_unused]]` attribute to indicate the value is unused.

Note:
- Functions taking a `(void)` argument list have also been changed to
  `()` because this is not needed and shows up in the same grep
  command.
2020-12-21 00:09:48 +01:00
Andreas Kling
48d2545572 LibJS: Get rid of Argument and ArgumentVector
This was used for a feature where you could pass a vector of arguments
to enter_scope(). Since that way of passing arguments was not GC-aware
(as vectors use C++ heap storage), let's avoid using it and make sure
everything that needs to stay alive is either on the stack or in traced
storage instead.
2020-12-08 18:28:18 +01:00
Linus Groh
a70aacd7c3 LibJS: Add Float{32,64}Array 2020-12-05 23:52:17 +01:00
Linus Groh
32571dfa53 LibJS: Add ArrayBuffer 2020-12-02 23:49:00 +01:00
Linus Groh
7fb299fe46 LibJS: Clean up TypedArray constructors and prototypes
The current implementation is not entirely correct yet. Two classes have
been added:
- TypedArrayConstructor, which the various typed array constructors now
  inherit from. Calling or constructing this class (from JS, that is)
  directly is not possible, we might want to move this abstract class
  functionality to NativeFunction at a later point.
- TypedArrayPrototype, which the various typed array prototypes now have
  as their own prototype. This will be the place where most of the
  functionality is being shared.

Relevant parts from the spec:

22.2.1 The %TypedArray% Intrinsic Object
The %TypedArray% intrinsic object:
- is a constructor function object that all of the TypedArray
  constructor objects inherit from.
- along with its corresponding prototype object, provides common
  properties that are inherited by all TypedArray constructors and their
  instances.

22.2.2 Properties of the %TypedArray% Intrinsic Object
The %TypedArray% intrinsic object:
- has a [[Prototype]] internal slot whose value is %Function.prototype%.

22.2.2.3 %TypedArray%.prototype
The initial value of %TypedArray%.prototype is the %TypedArray%
prototype object.

22.2.6 Properties of the TypedArray Constructors
Each TypedArray constructor:
- has a [[Prototype]] internal slot whose value is %TypedArray%.

22.2.6.2 TypedArray.prototype
The initial value of TypedArray.prototype is the corresponding
TypedArray prototype intrinsic object (22.2.7).

22.2.7 Properties of the TypedArray Prototype Objects
Each TypedArray prototype object:
- has a [[Prototype]] internal slot whose value is %TypedArray.prototype%.

22.2.7.2 TypedArray.prototype.constructor
The initial value of a TypedArray.prototype.constructor is the
corresponding %TypedArray% intrinsic object.
2020-12-02 12:52:31 +01:00
Andreas Kling
3565d3c60c LibJS: Add six typed arrays (signed and unsigned 8/16/32-bit)
This patch adds six of the standard type arrays and tries to share as
much code as possible:

- Uint8Array
- Uint16Array
- Uint32Array
- Int8Array
- Int16Array
- Int32Array
2020-12-01 21:05:25 +01:00
Linus Groh
48c19cdb06 LibJS: Remove ProxyPrototype
Proxy is an "exotic object" and doesn't have its own prototype. Use the
regular object prototype instead, but most stuff is happening on the
target object anyway. :^)
2020-12-01 09:54:37 +01:00
Andreas Kling
c3fe9b4df8 LibJS: Add a scope object abstraction
Both GlobalObject and LexicalEnvironment now inherit from ScopeObject,
and the VM's call frames point to a ScopeObject chain rather than just
a LexicalEnvironment chain.

This gives us much more flexibility to implement things like "with",
and also unifies some of the code paths that previously required
special handling of the global object.

There's a bunch of more cleanup that can be done in the wake of this
change, and there might be some oversights in the handling of the
"super" keyword, but this generally seems like a good architectural
improvement. :^)
2020-11-28 17:16:48 +01:00
Linus Groh
ee66eaa1b0 LibJS: Make RegExp.prototype.flags spec-compliant
This should be using the individual flag boolean properties rather than
the [[OriginalFlags]] internal slot.
Use an enumerator macro here for brevity, this will be useful for other
things as well. :^)
2020-11-28 01:20:11 +01:00
Andreas Kling
48f13b7c3f LibJS: Split Heap into per-cell-size allocators
Instead of keeping all the HeapBlocks in one big list, we now split it
into two levels:

- Heap has a set of Allocators, each with a specific cell size.
- Allocators have two lists of blocks, "full" and "usable".

Allocating a new cell no longer has to scan the entire set of blocks,
but instead just needs to find the right allocator and then pop a cell
from its freelist. If all the blocks in the allocator are full, a new
block will be created.

Blocks are moved from the "full" to "usable" list after sweeping has
determined that they are not completely empty and not completely full.

There are certainly many ways we can improve on this. This patch is
mostly about getting the new allocator architecture in place. :^)
2020-10-06 18:50:47 +02:00
Andreas Kling
e4bda2e1e7 LibJS: Move Console from Interpreter to GlobalObject
Each JS global object has its own "console", so it makes more sense to
store it in GlobalObject.

We'll need some smartness later to bundle up console messages from all
the different frames that make up a page later, but this works for now.
2020-09-29 21:15:06 +02:00
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
Ben Wiederhake
08f9bc26a6 Meta+LibHTTP through LibWeb: Make clang-format-10 clean 2020-09-25 21:18:17 +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
Nico Weber
b9ce56aee6 LibWeb: Make btoa() and atob() correctly handle values between 128 and 255
btoa() takes a byte string, so it must decode the UTF-8 argument into
a Vector<u8> before calling encode_base64.

Likewise, in atob() decode_base64 returns a byte string, so that needs
to be converted to UTF-8.

With this, `btoa(String.fromCharCode(255))` is '/w==' as it should
be, and `atob(btoa(String.fromCharCode(255))) == String.fromCharCode(255)`
remains true.
2020-07-22 19:22:00 +02:00
Matthew Olsson
c831fb17bf LibJS: Add StringIterator 2020-07-13 15:07:29 +02:00
Matthew Olsson
c485c86015 LibJS: Use macros to enumerate well-known symbols
Not only is this a much nicer api (can't pass a typo'd string into the
get_well_known_symbol function), it is also a bit more performant since
there are no hashmap lookups.
2020-07-11 18:54:13 +02:00
Matthew Olsson
2ea85355fe LibJS: Start implementing iterable framework, add ArrayIterator
With the addition of symbol keys, work can now be done on starting to
implement the well-known symbol functionality. The most important of
these well-known symbols is by far Symbol.iterator.

This patch adds IteratorPrototype, as well as ArrayIterator and
ArrayIteratorPrototype. In the future, sometime after StringIterator has
also been added, this will allow us to use Symbol.iterator directly in
for..of loops, enabling the use of custom iterator objects. Also makes
adding iterator support to native objects much easier (as will have to
be done for Map and Set, when they get added).
2020-07-11 18:54:13 +02:00
Andreas Kling
0166a1fa74 LibJS: Make NativeProperty a plain Cell instead of an Object
This removes the need for NativeProperty objects to have a prototype,
which just made things confusing.
2020-06-23 17:56:57 +02:00
Andreas Kling
e4add19915 LibJS: Pass GlobalObject& to native functions and property accessors
More work towards supporting multiple global objects. Native C++ code
now get a GlobalObject& and don't have to ask the Interpreter for it.

I've added macros for declaring and defining native callbacks since
this was pretty tedious and this makes it easier next time we want to
change any of these signatures.
2020-06-20 15:45:07 +02:00
Linus Groh
0ff9d7e189 LibJS: Add BigInt 2020-06-07 19:29:40 +02:00
Matthew Olsson
61ac1d3ffa LibJS: Lex and parse regex literals, add RegExp objects
This adds regex parsing/lexing, as well as a relatively empty
RegExpObject. The purpose of this patch is to allow the engine to not
get hung up on parsing regexes. This will aid in finding new syntax
errors (say, from google or twitter) without having to replace all of
their regexes first!
2020-06-07 19:06:55 +02:00
Matthew Olsson
39ad42defd LibJS: Add Proxy objects
Includes all traps except the following: [[Call]], [[Construct]],
[[OwnPropertyKeys]].

An important implication of this commit is that any call to any virtual
Object method has the potential to throw an exception. These methods
were not checked in this commit -- a future commit will have to protect
these various method calls throughout the codebase.
2020-06-06 22:13:01 +02:00
FalseHonesty
941b028ca3 LibJS: Create JS to HTML markup generator
The new JS::MarkupGenerator class can convert both a JS source string
and a JS Runtime Value into properly formatted HTML using the new
LibWeb System Palette css color values.

It makes more sense for this JS -> HTML process to occur in LibJS
so that it can be used elsewhere, namely Markdown code block syntax
highlighting. It also means the Browser can worry less about LibJS
implementation details.
2020-05-26 10:17:50 +02:00
Matthew Olsson
45dfa094e9 LibJS: Add getter/setter support
This patch adds a GetterSetterPair object. Values can now store pointers
to objects of this type. These objects are created when using
Object.defineProperty and providing an accessor descriptor.
2020-05-21 22:56:18 +02:00
mattco98
4ced126704 LibJS: Add symbol objects
This commit adds the following classes: SymbolObject, SymbolConstructor,
SymbolPrototype, and Symbol. This commit does not introduce any
new functionality to the Object class, so they cannot be used as
property keys in objects.
2020-05-17 18:05:15 +02:00
Andreas Kling
67b8e6fc5b LibJS: Add Reference class to represent a base.property reference
Expression nodes can now be asked to produce a Reference. We then use
this to implement the "delete" operator without downcasting the child
node to a MemberExpression manually.
2020-04-28 15:07:08 +02:00
Andreas Kling
627fd6374b LibJS: Add Uint8ClampedArray :^)
This is a special kind of byte array that clamps its values to 0...255
It will be used for HTML ImageData objects.

I made Object::put_by_index() and get_by_index() virtual for this.
We'll probably need to make non-numeric property name lookups virtual
as well, but this solves my current problem well enough.
2020-04-21 23:47:39 +02:00
Jack Karamanian
1fa0c7304d LibJS: Implement Function.prototype.bind() 2020-04-21 12:23:07 +02:00
Andreas Kling
f7a1696087 LibJS: Add MarkedValueList and use it for argument passing
A MarkedValueList is basically a Vector<JS::Value> that registers with
the Heap and makes sure that the stored values don't get GC'd.

Before this change, we were unsafely keeping Vector<JS::Value> in some
places, which is out-of-reach for the live reference finding logic
since Vector puts its elements on the heap by default.

We now pass all the JavaScript tests even when running with "js -g",
which does a GC on every heap allocation.
2020-04-19 17:34:33 +02:00
Andreas Kling
2a9e29fbb8 LibJS: Add DeferGC, a RAII way to prevent GC temporarily 2020-04-19 12:09:32 +02:00
Andreas Kling
ed80952cb6 LibJS: Introduce LexicalEnvironment
This patch replaces the old variable lookup logic with a new one based
on lexical environments.

This brings us closer to the way JavaScript is actually specced, and
also gives us some basic support for closures.

The interpreter's call stack frames now have a pointer to the lexical
environment for that frame. Each lexical environment can have a chain
of parent environments.

Before calling a Function, we first ask it to create_environment().
This gives us a new LexicalEnvironment for that function, which has the
function's lexical parent's environment as its parent. This allows
inner functions to access variables in their outer function:

    function foo() { <-- LexicalEnvironment A
        var x = 1;
        function() { <-- LexicalEnvironment B (parent: A)
            console.log(x);
        }
    }

If we return the result of a function expression from a function, that
new function object will keep a reference to its parent environment,
which is how we get closures. :^)

I'm pretty sure I didn't get everything right here, but it's a pretty
good start. This is quite a bit slower than before, but also correcter!
2020-04-15 22:07:20 +02:00
Andreas Kling
cb0dfd8f72 LibJS: Use enumerator macros for boilerplate code around native types 2020-04-10 14:06:52 +02:00
Andreas Kling
58ab76269c LibJS: Add all the Error subclasses
This patch adds instance, constructor and prototype classes for:

    - EvalError
    - InternalError
    - RangeError
    - ReferenceError
    - SyntaxError
    - TypeError
    - URIError

Enumerator macros are used to reduce the amount of typing. :^)
2020-04-10 13:09:35 +02:00
Emanuele Torre
38dfd04633 LibJS: rename JS::DeclarationType => JS::DeclarationKind
Many other parsers call it with this name.

Also Type can be confusing in this context since the DeclarationType is
not the type (number, string, etc.) of the variables that are being
declared by the VariableDeclaration.
2020-04-08 14:50:14 +02:00
Andreas Kling
f07f8d5a44 LibJS: Add "constructor" property to constructor prototypes 2020-04-08 11:08:07 +02:00
Andreas Kling
a502ba73dc LibJS: Correctly forward declare "Argument" as a struct 2020-04-04 10:46:00 +02:00
Andreas Kling
5e6e1fd482 LibJS: Start implementing object shapes
This patch adds JS::Shape, which implements a transition tree for our
Object class. Object property keys, prototypes and attributes are now
stored in a Shape, and each Object has a Shape.

When adding a property to an Object, we make a transition from the old
Shape to a new Shape. If we've made the same exact transition in the
past (with another Object), we reuse the same transition and both
objects may now share a Shape.

This will become the foundation of inline caching and other engine
optimizations in the future. :^)
2020-04-02 19:32:21 +02:00
Andreas Kling
aee4c1f583 LibJS: Add GlobalObject to the forwarding header 2020-04-01 21:05:35 +02:00
Andreas Kling
faddf3a1db LibJS: Implement "throw"
You can now throw an expression to the nearest catcher! :^)

To support throwing arbitrary values, I added an Exception class that
sits as a wrapper around whatever is thrown. In the future it will be
a logical place to store a call stack.
2020-03-24 22:21:58 +01:00
Andreas Kling
343e224aa8 LibJS: Implement basic exception throwing
You can now throw exceptions by calling Interpreter::throw_exception().
Anyone who calls ASTNode::execute() needs to check afterwards if the
Interpreter now has an exception(), and if so, stop what they're doing
and simply return.

When catching an exception, we'll first execute the CatchClause node
if present. After that, we'll execute the finalizer block if present.

This is unlikely to be completely correct, but it's a start! :^)
2020-03-24 16:14:10 +01:00
Andreas Kling
fbb9e1b715 LibJS: Implement "else" parsing
We can now handle scripts with if/else in LibJS. Most of the changes
are about fixing IfStatement to store the consequent and alternate node
as Statements.

Interpreter now also runs Statements, rather than running ScopeNodes.
2020-03-23 16:52:58 +01:00