Commit graph

58 commits

Author SHA1 Message Date
Andreas Kling
2bc5bc64fb LibJS: Remove a whole bunch of includes of <LibJS/Interpreter.h> 2020-09-27 20:26:58 +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
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
Andreas Kling
3143fea1eb LibJS: GlobalObject needs to mark the iterator prototypes
Otherwise they all disappear in the first garbage collection.
2020-09-08 15:37:39 +02:00
Andreas Kling
aaf6014ae1 LibJS: Simplify Cell::initialize()
Remove the Interpreter& argument and pass only GlobalObject&. We can
find everything we need via the global object anyway.
2020-07-23 17:31:08 +02:00
Matthew Olsson
c831fb17bf LibJS: Add StringIterator 2020-07-13 15:07:29 +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
ba641e97d9 LibJS: Clarify Object (base class) construction somewhat
Divide the Object constructor into three variants:

- The regular one (takes an Object& prototype)
- One for use by GlobalObject
- One for use by objects without a prototype (e.g ObjectPrototype)
2020-06-23 17:21:53 +02:00
Andreas Kling
06e29fac57 LibJS: Split more native object constructors into construct/initialize 2020-06-20 17:50:48 +02:00
Andreas Kling
64513f3c23 LibJS: Move native objects towards two-pass construction
To make sure that everything is set up correctly in objects before we
start adding properties to them, we split cell allocation into 3 steps:

1. Allocate a cell of appropriate size from the Heap
2. Call the C++ constructor on the cell
3. Call initialize() on the constructed object

The job of initialize() is to define all the initial properties.
Doing it in a second pass guarantees that the Object has a valid Shape
and can find its own GlobalObject.
2020-06-20 15:46:30 +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
Matthew Olsson
39576b2238 LibJS: Add JSON.stringify 2020-06-13 12:43:22 +02:00
Andreas Kling
ff8bb962b6 LibJS: Always keep a reference to the global object in Shape
We need to move towards supporting multiple global objects, which will
be a large refactoring. To keep it manageable, let's do it in steps,
starting with giving Object a way to find the GlobalObject it lives
inside by asking its Shape for it.
2020-06-08 12:15:58 +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
Matthew Olsson
dd08c992e8 LibJS: Simplify and normalize publicly-exposed Object functions
Previously, the Object class had many different types of functions for
each action. For example: get_by_index, get(PropertyName),
get(FlyString). This is a bit verbose, so these methods have been
shortened to simply use the PropertyName structure. The methods then
internally call _by_index if necessary. Note that the _by_index
have been made private to enforce this change.

Secondly, a clear distinction has been made between "putting" and
"defining" an object property. "Putting" should mean modifying a
(potentially) already existing property. This is akin to doing "a.b =
'foo'".

This implies two things about put operations:
    - They will search the prototype chain for setters and call them, if
      necessary.
    - If no property exists with a particular key, the put operation
      should create a new property with the default attributes
      (configurable, writable, and enumerable).

In contrast, "defining" a property should completely overwrite any
existing value without calling setters (if that property is
configurable, of course).

Thus, all of the many JS objects have had any "put" calls changed to
"define_property" calls. Additionally, "put_native_function" and
"put_native_property" have had their "put" replaced with "define".

Finally, "put_own_property" has been made private, as all necessary
functionality should be exposed with the put and define_property
methods.
2020-05-27 13:17:35 +02:00
Linus Groh
f06c12173c LibJS: Return early from parseFloat() if argument is a number
This saves us both a bit of time and accuracy, as Serenity's strtod()
still is a little bit off sometimes - and stringifying the result and
parsing it again just increases that offset.
2020-05-18 14:33:53 +02:00
Linus Groh
476094922b LibJS: Pass Interpreter& to Value::to_number() et al.
This patch is unfortunately rather large and might make some things feel
bloated, but it is necessary to fix a few flaws in LibJS, primarily
blindly coercing values to numbers without exception checks - i.e.

interpreter.argument(0).to_i32();  // can fail!!!

Some examples where the interpreter would actually crash:

var o = { toString: () => { throw Error() } };
+o;
o - 1;
"foo".charAt(o);
"bar".repeat(o);

To fix this, we now have the following...

to_double(Interpreter&)
to_i32()
to_i32(Interpreter&)
to_size_t()
to_size_t(Interpreter&)

...and a whole lot of exception checking.

There's intentionally no to_double(), use as_double() directly instead.

This way we still can use these convenient utility functions but don't
need to check for exceptions if we are sure the value already is a
number.

Fixes #2267.
2020-05-18 09:39:55 +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
Linus Groh
6f6b089aa0 LibJS: Add parseFloat() 2020-05-17 16:21:33 +02:00
Andreas Kling
c00ff4ba62 LibJS: Fix build (GlobalObject::add_constructor not visible in LibWeb) 2020-05-02 20:43:44 +02:00
Linus Groh
99be27b4a1 LibJS: Add "name" property to functions 2020-05-02 20:41:31 +02:00
Linus Groh
79b829637e LibJS: Implement most of the Reflect object 2020-05-01 16:54:01 +02:00
mattco98
23ec578a01 LibJS: Implement correct attributes for (almost) all properties
Added the ability to include a u8 attributes parameter with all of the
various put methods in the Object class. They can be omitted, in which
case it defaults to "Writable | Enumerable | Configurable", just like
before this commit.

All of the attribute values for each property were gathered from
SpiderMonkey in the Firefox console. Some properties (e.g. all of the
canvas element properties) have undefined property descriptors... not
quite sure what that means. Those were left as the default specified
above.
2020-04-28 09:29:50 +02:00
Linus Groh
7bd6b58b29 LibJS: Implement Number.isNaN()
Like the global isNaN() without the number coercion.
2020-04-26 20:36:59 +02:00
Linus Groh
c350f5ae67 LibJS: Implement Number.isFinite()
Like the global isFinite() without the number coercion.
2020-04-26 20:36:59 +02:00
Linus Groh
7540203ae8 LibJS: Add isFinite() 2020-04-23 11:03:42 +02:00
Linus Groh
8ff2881b1a LibJS: Let isNaN() with no argument return true, add tests 2020-04-23 11:03:42 +02:00
Andreas Kling
3072f9fd82 LibJS: Move the empty object shape from Interpreter to GlobalObject
The big remaining hurdle before a GlobalObject-agnostic Interpreter is
the fact that Interpreter owns and vends the GlobalObject :^)
2020-04-18 13:59:20 +02:00
Andreas Kling
fca08bd000 LibJS: Move builtin prototypes to the global object
This moves us towards being able to run JavaScript in different global
objects without allocating a separate GC heap.
2020-04-18 13:24:45 +02:00
Andreas Kling
30de1f610d LibJS: Use enumerator macro to mark all constructors in GlobalObject
We were forgetting to mark the String constructor! So this patch fixes
that and ensures we won't forget anyone in the future.
2020-04-18 11:02:05 +02:00
Andreas Kling
bc1ece7f37 LibJS+LibWeb: Pass prototype to Object constructor
Everyone who constructs an Object must now pass a prototype object when
applicable. There's still a fair amount of code that passes something
fetched from the Interpreter, but this brings us closer to being able
to detach prototypes from Interpreter eventually.
2020-04-18 11:00:55 +02:00
Andreas Kling
6f3ea75569 LibJS: Add String constructor :^) 2020-04-10 14:14:02 +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
Linus Groh
c06a6c67d5 LibJS: Add globalThis
We already have "global" as a way to access the global object in js(1)
(both REPL and script mode). This replaces it with "globalThis", which
is available in all environments, not just js.
2020-04-09 15:58:49 +02:00
Andreas Kling
f07f8d5a44 LibJS: Add "constructor" property to constructor prototypes 2020-04-08 11:08:07 +02:00
Linus Groh
f631f6a2e6 LibJS: Add Number() 2020-04-07 17:25:50 +02:00
Jack Karamanian
edae926cb0 LibJS: Add Boolean constructor object 2020-04-07 08:41:25 +02:00
Andreas Kling
e323246517 Meta: Add missing copyright headers 2020-04-06 11:09:01 +02:00
Andreas Kling
d155491122 LibJS: Add basic Array constructor
We only support Array() with 0 or 1 parameters so far.
2020-04-04 22:28:21 +02:00
Linus Groh
2944039d6b LibJS: Add Function() and Function.prototype 2020-04-04 15:58:49 +02:00
Linus Groh
cd3e2690eb LibJS: Set length property in Object::put_native_function() 2020-04-04 15:58:49 +02:00
Linus Groh
2636cac6e4 LibJS: Remove UndefinedLiteral, add undefined to global object
There is no such thing as a "undefined literal" in JS - undefined is
just a property on the global object with a value of undefined.
This is pretty similar to NaN.

var undefined = "foo"; is a perfectly fine AssignmentExpression :^)
2020-04-03 00:10:52 +02:00
Linus Groh
543c6e00db LibJS: Implement Infinity 2020-04-02 21:52:15 +02:00
Andreas Kling
cd1d369cdd LibJS: Add argument(i) and argument_count() to Interpreter
Add some convenience accessors for retrieving arguments from the
current call frame.
2020-04-01 22:38:59 +02:00
Linus Groh
a0da97cb5a LibJS: Add NaN to global object 2020-04-01 22:09:37 +02:00
Linus Groh
ee6472fef2 LibJS: Implement Error function/constructor 2020-04-01 20:47:37 +02:00
Linus Groh
d4e3688f4f LibJS: Start implementing Date :^)
This adds:

- A global Date object (with `length` property and `now` function)
- The Date constructor (no arguments yet)
- The Date prototype (with `get*` functions)
2020-03-30 14:11:54 +02:00