Commit graph

1458 commits

Author SHA1 Message Date
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
99aab4470a LibJS: Object::put() shouldn't create own properties on prototype chain
Unless there is a setter present on the prototype chain, put() should
only set own properties on the object itself.

Fixes #1588.
2020-04-02 21:36:14 +02:00
Linus Groh
a62230770b LibJS: Implement unary plus / minus 2020-04-02 19:55:45 +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
fbb16073d1 LibJS: Make JS::Cell non-copyable and non-movable
Also make the JS::Cell default constructor protected to provove a
compilation error if you tried to allocate a plain cell.
2020-04-02 15:24:50 +02:00
Andreas Kling
c683665ca9 LibJS: Fix bad cast in Interpreter::run()
We were casting to BlockStatement when we should cast to ScopeNode.
2020-04-02 09:56:13 +02:00
Jack Karamanian
bb15b37228 LibJS: Evaluate CallExpression arguments before pushing a CallFrame 2020-04-02 08:50:28 +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
Andreas Kling
1549c5c48b LibJS: Make Value::as_object() return Object&
Let's move towards using references over pointers in LibJS as well.
I had originally steered away from it because that's how I've seen
things done in other engines. But this is not the other engines. :^)
2020-04-01 22:18:47 +02:00
Linus Groh
a0da97cb5a LibJS: Add NaN to global object 2020-04-01 22:09:37 +02:00
Andreas Kling
9d5d0261e1 LibJS: Add Interpreter::create<GlobalObjectType>()
Force Interpreter construction to go via a create() helper that takes
the global object type as a template parameter.
2020-04-01 21:05:35 +02:00
Andreas Kling
aee4c1f583 LibJS: Add GlobalObject to the forwarding header 2020-04-01 21:05:35 +02:00
Linus Groh
ee6472fef2 LibJS: Implement Error function/constructor 2020-04-01 20:47:37 +02:00
Linus Groh
849e2c77e4 LibJS: Implement constructor/non-constructor function calls
This adds Function::construct() for constructor function calls via `new`
keyword. NativeFunction doesn't have constructor behaviour by default,
ScriptFunction simply calls call() in construct()
2020-04-01 20:18:36 +02:00
Andreas Kling
d062d7baa7 LibWeb+LibJS: Move DOM Window object to dedicated classes
LibWeb now creates a WindowObject which inherits from GlobalObject.
Allocation of the global object is moved out of the Interpreter ctor
to allow for specialized construction.

The existing Window interfaces are moved to WindowObject with their
implementation code in the new Window class.
2020-04-01 18:57:00 +02:00
Andreas Kling
cd9379dca9 LibJS: Reorganize computing of |this| for CallExpressions
This avoids executing the LHS of the object expression twice when doing
a call on the result of an object expression.
2020-04-01 18:57:00 +02:00
Linus Groh
632231cc0c js: Implement print function for Date objects 2020-03-31 21:19:21 +02:00
Andreas Kling
a8dc6501de LibJS: Use "%d" to stringify numeric values that are whole integers
This unbreaks a bunch of the JS tests since they were now printing all
the numbers as "1.000000" instead of "1".
2020-03-31 19:06:10 +02:00
Linus Groh
3fcea71538 LibJS: Implement Date.prototype.to{Date,Time}String() 2020-03-30 21:43:35 +02:00
Linus Groh
dc9b1226ac LibJS: Implement Date.prototype.toString() 2020-03-30 20:36:18 +02:00
Jack Karamanian
098f1cd0ca LibJS: Add support for arrow functions 2020-03-30 15:41:36 +02:00
Jack Karamanian
f90da71d28 LibJS: Add Parser save_state() and load_state() functions
These functions allow us to try to parse ambiguous expressions (such as
arrow function arguments in parentheses), and
rewind the state of the Parser if an expression candidate failed to
parse.
2020-03-30 15:41:36 +02:00
Linus Groh
fb0401871c LibJS: Throw TypeError when calling non-function object
We now have "undefined is not a function" :^)
2020-03-30 14:43:58 +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
Andreas Kling
a1c718e387 LibJS: Use some macro magic to avoid duplicating all the token types 2020-03-30 13:11:07 +02:00
Linus Groh
0a94661c14 LibJS: Implement String.prototype.startsWith() 2020-03-29 19:37:16 +02:00
Linus Groh
402fd5a3a3 LibJS: Add tests for Math constants 2020-03-29 17:35:08 +02:00
Linus Groh
03c3530d86 LibJS: Add constant properties to MathObject 2020-03-29 17:35:08 +02:00
Linus Groh
c698cc899d LibJS: Add tests for value to number conversion 2020-03-29 16:45:11 +02:00
Linus Groh
bad0556a59 LibJS: Handle empty strings and arrays in Value::to_number()
- An empty string is converted to 0
 - An empty array is converted to 0
 - An array with one item is converted to that item's numeric value
 - An array with more than one item is converted to NaN
2020-03-29 16:45:11 +02:00
Andreas Kling
2d3634d5f5 LibJS: Implement Math.abs() 2020-03-29 15:03:58 +02:00
Andreas Kling
2285f84596 LibJS: Implement basic execution of "switch" statements
The "break" keyword now unwinds to the nearest ScopeType::Breakable.
There's no support for break labels yet, but we'll get there too.
2020-03-29 15:03:58 +02:00
Andreas Kling
1923051c5b LibJS: Lexer and parser support for "switch" statements 2020-03-29 15:03:58 +02:00
Andreas Kling
f95a119627 LibJS: Implement Object.getOwnPropertyNames() 2020-03-29 01:26:57 +01:00
Andreas Kling
62d5f79388 LibJS+LibWeb: Function calls should always go through Interpreter
This ensures that we set up a call frame with |this| and arguments.
2020-03-29 00:45:53 +01:00
Andreas Kling
30440134cb LibJS+LibWeb: Move native properties to separate getters/setters
This was a bit cumbersome now, but it gets us closer to a format suited
for code generation.
2020-03-29 00:37:33 +01:00
Andreas Kling
56936b97d0 LibJS+LibWeb: Move native JS functions into dedicated member functions
Instead of implementing every native function as a lambda function,
use static member functions instead.

This makes it easier to navigate the code + backtraces look nicer. :^)
2020-03-28 23:10:37 +01:00
Andreas Kling
7c4e53f31e LibJS: Rework how native functions are called to improve |this| value
Native functions now only get the Interpreter& as an argument. They can
then extract |this| along with any indexed arguments it wants from it.

This forces functions that want |this| to actually deal with calling
interpreter.this_value().to_object(), and dealing with the possibility
of a non-object |this|.

This is still not great but let's keep massaging it forward.
2020-03-28 22:51:09 +01:00
Linus Groh
c209ea1985 LibJS: Implement Array.prototype.{shift,pop} 2020-03-28 22:18:11 +01:00
Andreas Kling
82ca7ae1f8 LibJS: Oops, "instanceof" was backwards!
Fix the "instanceof" operator to check if the constructor's prototype
property occurs anywhere in the prototype chain of the instance object.

This patch also adds Object.setPrototypeOf() to make it possible to
create a test for this bug.

Thanks to DexesTTP for pointing this out! :^)
2020-03-28 19:48:12 +01:00
Andreas Kling
14047ca432 LibJS: Add a global "Object" constructor
This patch adds an "Object" constructor to the global object. The only
function it implements so far is Object.getPrototypeOf().
2020-03-28 17:23:54 +01:00
Andreas Kling
a3d92b1210 LibJS: Implement the "instanceof" operator
This operator walks the prototype chain of the RHS value and looks for
a "prototype" property with the same value as the prototype of the LHS.

This is pretty cool. :^)
2020-03-28 16:56:54 +01:00
Andreas Kling
37fe16a99c LibJS: Add Function.prototype and make "new" Objects delegate to it 2020-03-28 16:40:36 +01:00
Andreas Kling
0593ce406b LibJS: Implement basic support for the "new" keyword
NewExpression mostly piggybacks on the existing CallExpression. The big
difference is that "new" creates a new Object and passes it as |this|
to the callee.
2020-03-28 16:33:52 +01:00
Andreas Kling
fecbef4ffe LibJS: Make it possible to reference the "this" value in JavaScript 2020-03-28 16:33:04 +01:00
Andreas Kling
14de45296e LibJS: Fix broken parsing of !o.a
Unary expressions parsing now respects precedence and associativity of
operators. This patch also makes `typeof` left-associative which was
an oversight.

Thanks to Conrad for helping me work this out. :^)
2020-03-28 11:51:44 +01:00
Andreas Kling
0cbbf6f5eb LibJS: Add a tiny little test for the ReferenceError exception 2020-03-28 10:27:48 +01:00
Andreas Kling
0d2fb306af LibJS: Check for exceptions in a lot more places 2020-03-27 15:36:00 +01:00
Andreas Kling
6a5cd32205 LibJS: The global isNaN() should coerce to number before testing NaN
For stricter NaN checking, we'll have to implement Number.isNaN().
2020-03-27 12:59:41 +01:00