Commit graph

56 commits

Author SHA1 Message Date
Linus Groh
eb72ba2466 LibJS: Remove is_nan() check in as_size_t() and fix to_size_t()
We need to call as_double() on the freshly converted number, not the
value itself.
2020-05-18 11:39:11 +02:00
Linus Groh
36996bd720 LibJS: Rename to_{i32,size_t}() to as_{i32,size_t}() for clarity
As these parameter-less overloads don't change the value's type and
just assume Type::Number, naming them as_i32() and as_size_t() is more
appropriate.
2020-05-18 10:21:51 +02:00
Linus Groh
56502b0e84 LibJS: Check for exception after converting object to string primitive 2020-05-18 09:39:55 +02:00
Linus Groh
4569e88bea LibJS: Throw TypeError when coercing symbol to number 2020-05-18 09:39:55 +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
Linus Groh
1a1394f7a2 LibJS: Change Value::to_object(Heap& -> Interpreter&)
Passing a Heap& to it only to then call interpreter() on that is weird.
Let's just give it the Interpreter& directly, like some of the other
to_something() functions.
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
Andreas Kling
c6ddbd1f3e LibJS: Add side-effect-free version of Value::to_string()
There are now two API's on Value:

- Value::to_string(Interpreter&) -- may throw.
- Value::to_string_without_side_effects() -- will never throw.

These are some pretty big sweeping changes, so it's possible that I did
some part the wrong way. We'll work it out as we go. :^)

Fixes #2123.
2020-05-15 13:50:42 +02:00
Linus Groh
de42ddfd93 LibJS: Trim whitespace from string before coercing to number 2020-05-13 09:36:20 +02:00
Linus Groh
0c14ee035c LibJS: Make string to number coercion work for doubles 2020-05-13 09:36:20 +02:00
Linus Groh
063228c02e LibJS: Handle empty values in operator<<()
Otherwise something like dbg() << Value(); chokes on
ASSERT_NOT_REACHED() in Value::to_string()
2020-05-13 01:14:22 +02:00
Matthew Olsson
532d4bc0ab LibJS: Spec-compliant equality comparisons
The ECMAScript spec defines multiple equality operations which are used
all over the spec; this patch introduces them. Of course, the two
primary equality operations are AbtractEquals ('==') and StrictEquals
('==='), which have been renamed to 'abstract_eq' and 'strict_eq' in
this patch.

In support of the two operations mentioned above, the following have
also been added: SameValue, SameValueZero, and SameValueNonNumeric.
These are important to have, because they are used elsewhere in the spec
aside from the two primary equality comparisons.
2020-05-08 09:49:20 +02:00
Linus Groh
eea62dd365 LibJS: Add Value::{is, as}_function() 2020-05-06 14:49:53 +02:00
Linus Groh
79b829637e LibJS: Implement most of the Reflect object 2020-05-01 16:54:01 +02:00
Linus Groh
65dbe17dd7 LibJS: Add Value::to_size_t() 2020-05-01 16:54:01 +02:00
Linus Groh
2c6e7dbd07 LibJS: Throw error in Object::to_string() if string conversion fails 2020-04-29 18:53:21 +02:00
Andreas Kling
698652a548 LibJS: Make Value::as_string() return a PrimitiveString reference 2020-04-29 12:35:39 +02:00
Linus Groh
da0ab16f01 LibJS: Don't handle arrays separately in Value::to_number()
Now that Array.prototype.join() is producing the correct results we
can remove the separate code path for arrays in Value::to_number()
and treat them like all other objects - using to_primitive() with
number as the preferred type and then calling to_number() on the
result.

This is how the spec descibes it.

This also means we don't crash anymore when trying to coerce
[<empty>] to a number - it now does the following:

[<empty>] - to string - "" - to number - 0
[<empty>, <empty>] - to string - "," - to number - NaN
2020-04-29 01:30:59 +02:00
Andreas Kling
35aea2e454 LibJS: Stop using Optional<Value> in favor of Value's empty state
JS::Value already has the empty state ({} or Value() gives you one.)
Use this instead of wrapping Value in Optional in some places.
I've also added Value::value_or(Value) so you can easily provide a
fallback value when one is not present.
2020-04-25 18:45:22 +02:00
Linus Groh
402ba20c36 LibJS: Fix left shift operator
Typo causing it to compute lhs << lhs, not lhs << rhs as expected.
2020-04-23 23:48:27 +02:00
Linus Groh
11728b7db5 LibJS: Implement 'in' operator 2020-04-23 19:38:13 +02:00
Linus Groh
396ecfa2d7 LibJS: Implement bitwise unsigned right shift operator (>>>) 2020-04-23 19:38:13 +02:00
Linus Groh
502d1f5165 LibJS: Implement bitwise right shift operator (>>) 2020-04-23 19:38:13 +02:00
Linus Groh
f0e7404480 LibJS: Implement bitwise left shift operator (<<) 2020-04-23 19:38:13 +02:00
Andreas Kling
2a15323029 LibJS: Pass prototype to BooleanObject constructor 2020-04-18 10:28:22 +02:00
Andreas Kling
298c606200 LibJS: Pass prototype to StringObject constructor 2020-04-18 10:28:22 +02:00
Andreas Kling
cf702a13b9 LibJS: Pass prototype to NumberObject constructor 2020-04-18 10:28:22 +02:00
Andreas Kling
fa30355194 LibJS: Adding two values should convert them to primitives first 2020-04-15 09:48:25 +02:00
Andreas Kling
63499c2c9f LibJS: Pass the Interpreter& to binary/logical/unary helpers 2020-04-15 09:28:41 +02:00
Linus Groh
97de93eed1 LibJS: Add js_negative_infinity()
Value(-js_infinity().as_double()) is kind of awkward.
2020-04-12 14:39:38 +02:00
Linus Groh
f226746394 LibJS: Handle Infinity in Value::to_number() 2020-04-12 14:39:38 +02:00
Andreas Kling
ff33c5b286 LibJS: Let's show a few more decimals when stringifying numeric values
I'm not sure what the correct behavior is supposed to be, but at least
this makes printing numbers show some more interesting detail for now.
2020-04-12 10:59:29 +02:00
Andreas Kling
e5da1cc566 LibJS: Throw real TypeError, ReferenceError, etc objects
Instead of just throwing Error objects with a name string, we now throw
the real Error subclass types. :^)
2020-04-10 13:09:35 +02:00
Andreas Kling
2ffa054574 LibJS: Add Value::to_double() for convenience 2020-04-08 17:19:46 +02:00
Jack Karamanian
edae926cb0 LibJS: Add Boolean constructor object 2020-04-07 08:41:25 +02:00
Jack Karamanian
57bd194e5a LibJS: Return false for NaN numbers in Value::to_boolean() 2020-04-07 08:41:25 +02:00
Andreas Kling
4fe14aab3b LibJS: Inline JS::Value()
I had this out of line for debugging reasons. Put it back inline.
2020-04-06 20:30:36 +02:00
Andreas Kling
bdffc9e7fb LibJS: Support array holes, encoded as empty JS::Value
This patch adds a new kind of JS::Value, the empty value.
It's what you get when you do JSValue() (or most commonly, {} in C++.)

An empty Value signifies the absence of a value, and should never be
visible to JavaScript itself. As of right now, it's used for array
holes and as a return value when an exception has been thrown and we
just want to unwind.

This patch is a bit of a mess as I had to fix a whole bunch of code
that was relying on JSValue() being undefined, etc.
2020-04-06 20:27:44 +02:00
Linus Groh
0403845d3e LibJS: Implement exponentiation (** operator) 2020-04-05 15:32:06 +02:00
Brian Gianforcaro
b8cef3a2d3 LibJS: Add support for floating point modulous
This change implements floating point mod based on the algorithm
used in LibM's fmod() implementation. To avoid taking a dependency
on LibM from LibJS I reimplemented the formula in LibJS.

I've incuded some of the example MDM test cases as well.
This surfaced and issue handling NaN which I've fixed as well.
2020-04-05 10:38:13 +02:00
Brian Gianforcaro
41bfff1abe LibJS: Correctness fixes for bitwise_or, address FIXME's in test. 2020-04-05 10:37:02 +02:00
Andreas Kling
3a026a1ede LibJS: Add NumberObject and make to_object() on number values create it 2020-04-04 23:13:13 +02:00
Andreas Kling
644ff1bbfd LibJS: Add basic support for modulo (%) in binary expressions 2020-04-04 21:17:34 +02:00
Linus Groh
543c6e00db LibJS: Implement Infinity 2020-04-02 21:52:15 +02:00
Linus Groh
a62230770b LibJS: Implement unary plus / minus 2020-04-02 19:55:45 +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
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
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
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