1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-19 23:45:10 +00:00
Commit graph

843 commits

Author SHA1 Message Date
Linus Groh
a2e1f1a872 LibJS: Implement exponentiation assignment operator (**=) 2020-05-05 11:12:27 +02:00
Linus Groh
3e754a15d4 LibJS: Implement bitwise assignment operators (&=, |=, ^=) 2020-05-05 11:12:27 +02:00
Linus Groh
8e4301dea6 LibJS: Add test for assignment operators 2020-05-05 11:12:27 +02:00
Emanuele Torre
e91ab0cb02 LibJS: Implement ConsoleClient
Now, you can optionally specify a ConsoleClient, to customise the
behaviour of the LibJS Console.

To customise the console, create a new ConsoleClient class that inherits
from JS::ConsoleClient and override all the abstract methods.

When Console::log() is called, if Console has a ConsoleClient,
ConsoleClient::log() is called instead.

These abstract methods are Value(void) functions: you can return a Value
which will be returned by the JavaScript function which calls that
method, in JavaScript.
2020-05-05 09:15:16 +02:00
Emanuele Torre
bc7ed4524e LibJS: Add some helpers and use them to re-implement Console functions
Also add const overloads for some getters.

Also const-qualify Interpreter::join_arguments().
2020-05-05 09:15:16 +02:00
Emanuele Torre
8bd9f7e50e LibJS: run clang-format on all the files 2020-05-05 09:15:16 +02:00
Emanuele Torre
30519c22f6 LibJS: Re-implement console functions as wrappers around Console methods
Console methods are now Value(void) functions.

JavaScript functions in the JavaScript ConsoleObject are now implemented
as simple wrappers around Console methods.

This will make it possible for LibJS users to easily override the
default behaviour of JS console functions (even their return value!)
once we add a way to override Console behaviour.
2020-05-05 09:15:16 +02:00
Emanuele Torre
73bead5ae9 LibJS: Move join_args() in Interpreter
It can be useful outside of Runtime/ConsoleObject.cpp.
join_args() => Interpreter::join_arguments()
2020-05-05 09:15:16 +02:00
Emanuele Torre
046f9cf115 LibJS: Remove ConsoleMessage from LibJS
We don't need to store the past messages in LibJS.
We'll implement a way to let LibJS users expand the vanilla Console.
2020-05-05 09:15:16 +02:00
Linus Groh
454c1e6bbe LibJS: Implement rest parameters 2020-05-04 23:30:52 +02:00
Linus Groh
d4bfcea570 LibJS: Add indentation to sections in SwitchCase::dump()
This now matches the output of

Program
  (Variables)
    ...
  (Children)
    ...

or

FunctionDeclaration 'foo'
  (Parameters)
    ...
  (Body)
    ...

etc.

Also don't print each consequent statement index, it doesn't add any
value.
2020-05-04 21:42:47 +02:00
mattco98
adb4accab3 LibJS: Add template literals
Adds fully functioning template literals. Because template literals
contain expressions, most of the work has to be done in the Lexer rather
than the Parser. And because of the complexity of template literals
(expressions, nesting, escapes, etc), the Lexer needs to have some
template-related state.

When entering a new template literal, a TemplateLiteralStart token is
emitted. When inside a literal, all text will be parsed up until a '${'
or '`' (or EOF, but that's a syntax error) is seen, and then a
TemplateLiteralExprStart token is emitted. At this point, the Lexer
proceeds as normal, however it keeps track of the number of opening
and closing curly braces it has seen in order to determine the close
of the expression. Once it finds a matching curly brace for the '${',
a TemplateLiteralExprEnd token is emitted and the state is updated
accordingly.

When the Lexer is inside of a template literal, but not an expression,
and sees a '`', this must be the closing grave: a TemplateLiteralEnd
token is emitted.

The state required to correctly parse template strings consists of a
vector (for nesting) of two pieces of information: whether or not we
are in a template expression (as opposed to a template string); and
the count of the number of unmatched open curly braces we have seen
(only applicable if the Lexer is currently in a template expression).

TODO: Add support for template literal newlines in the JS REPL (this will
cause a syntax error currently):

    > `foo
    > bar`
    'foo
    bar'
2020-05-04 16:46:31 +02:00
Linus Groh
32742709dc LibJS: Support empty statements
We already skipped random semicolons in Parser::parse_program(), but now
they are properly matched and parsed as empty statements - and thus
recognized as a valid body of an if / else / while / ... statement.
2020-05-03 12:57:48 +02:00
Linus Groh
25cf0da2fb LibJS: Set name of anonymous functions during assignment 2020-05-03 11:41:56 +02:00
Matthew Olsson
5e66f1900b LibJS: Add function default arguments
Adds the ability for function arguments to have default values. This
works for standard functions as well as arrow functions. Default values
are not printed in a <function>.toString() call, as nodes cannot print
their source string representation.
2020-05-03 00:44:57 +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
d007e8d00f LibJS: Set correct "length" of Object constructor 2020-05-02 20:41:31 +02:00
Linus Groh
85582953c6 LibJS: Minor formatting changes in Function.cpp 2020-05-02 20:41:31 +02:00
Linus Groh
ae05dc8abc LibJS: Name functions created by "Function" "anonymous"
...as it is supposed to be.
2020-05-02 20:41:31 +02:00
Emanuele Torre
be1a5bf3f7 LibJS: Add ConsoleMessage concept
A ConsoleMessage is a struct cointaining:
 * AK::String text;         represents the text of the message sent
                             to the console.
 * ConsoleMessageKind kind; represents the kind of JS `console` function
                             from which the message was sent.

Now, Javascript `console` functions only send a ConsoleMessage to the
Interpreter's Console instead of printing text directly to stdout.
The Console then stores the recived ConsoleMessage in
Console::m_messages; the Console does not print to stdout by default.

You can set Console::on_new_message to a void(ConsoleMessage&); this
function will get call everytime a new message is added to the Console's
messages and can be used, for example, to print ConsoleMessages to
stdout or to color the output based on the kind of ConsoleMessage.

In this patch, I also:
  * Re-implement all the previously implemented functions in the
     JavaScript ConsoleObject, as wrappers around Console functions
     that add new message to the Console.
  * Implement console.clear() like so:
    - m_messages get cleared;
    - a new_message with kind set ConsoleMessageKind::Clear gets added
       to m_messages, its text is an empty AK::String;
  * Give credit to linusg in Console.cpp since I used his
     console.trace() algorithm in Console::trace().

I think that having this abstration will help us in the implementation
of a browser console or a JS debugger. We could also add more MetaData
to ConsoleMessage, e.g. Object IDs of the arguments passed to console
functions in order to make hyperlinks, Timestamps, ecc.; which could be
interesting to see.

This will also help in implementing a `/bin/js` option to make, for
example, return a ConsoleMessageWrapper to console functions instead of
undefined. This will be useful to make tests for functions like
console.count() and console.countClear(). :^)
2020-05-02 11:41:35 +02:00
Emanuele Torre
e9c7d4524a LibJS: Implement ConsoleObject::count() as a Console::count() wrapper
Also implement ConsoleObject::count_clear() as a wrapper for
Console::count_clear()
2020-05-02 11:41:35 +02:00
Emanuele Torre
2e92c2e5e1 LibJS: Start implementing a Console class for the interpreter
The goal is to start factoring out core ConsoleObject functionality and
to make ConsoleObject only a JS wrapper around Console.
2020-05-02 11:41:35 +02:00
Linus Groh
43c1fa9965 LibJS: Implement (no-op) debugger statement 2020-05-01 22:07:13 +02:00
Linus Groh
79b829637e LibJS: Implement most of the Reflect object 2020-05-01 16:54:01 +02:00
Linus Groh
1ba2e6768d LibJS: Implement indexed access for StringObject 2020-05-01 16:54:01 +02:00
Linus Groh
a81bce8c2a LibJS: Make Array.length non-configurable
This was incorrect, it's only writable.
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
62671bea68 LibJS: Add Object::has_property()
Like Object::has_own_property() but going down the prototype chain.
2020-05-01 16:54:01 +02:00
Linus Groh
4cdd802927 LibJS: Return a bool from Object::put* to indicate success 2020-05-01 16:54:01 +02:00
Kesse Jones
6dbb5df81f LibJS: Add String.prototype.lastIndexOf 2020-05-01 16:50:37 +02:00
Emanuele Torre
46b79eaad9 LibJS: Implement console.countReset()
I chose to also make it print "<counter_name>: 0\n" when a counter gets
reset, similarly to how firefox behaves.
2020-05-01 13:02:01 +02:00
Emanuele Torre
8c60ba1e42 LibJS: Implement console.count() 2020-05-01 13:02:01 +02:00
Matthew Olsson
28ef654d13 LibJS: Add object literal method shorthand 2020-05-01 12:28:40 +02:00
mattco98
683a0696f3 LibJS: Add Object.{keys,values,entries}() 2020-04-30 09:53:16 +02:00
Linus Groh
fc34123a54 LibJS: Fix ConditionalExpression::dump()
Let's not print m_test three times :^)
2020-04-30 08:43:38 +02:00
Linus Groh
8614fb4092 LibJS: Enforce that ++/-- operand is an identifier or member expression 2020-04-30 08:41:31 +02:00
Linus Groh
624eaa32af LibJS: Add Parser::syntax_error() helper
Instead of having fprintf()s all over the place we can now use
syntax_error("message") or syntax_error("message", line, column).

This takes care of a consistent format, appending a newline and getting
the line number and column of the current token if the last two params
are omitted.
2020-04-30 08:41:31 +02:00
Linus Groh
8159f45f6e LibJS: Make String.prototype.slice() generic 2020-04-29 19:14:36 +02:00
Linus Groh
cfdb7b8806 LibJS: Make (most) String.prototype functions generic
I.e. they don't require the |this| value to be a string object and
"can be transferred to other kinds of objects for use as a method" as
the spec describes it.
2020-04-29 18:53:21 +02:00
Linus Groh
4bdb6daac5 LibJS: Handle non-string primitive values in Object::to_string() 2020-04-29 18:53:21 +02:00
Linus Groh
2c6e7dbd07 LibJS: Throw error in Object::to_string() if string conversion fails 2020-04-29 18:53:21 +02:00
mattco98
95abcc3722 LibJS: Implement correct object property ordering
This commit introduces a way to get an object's own properties in the
correct order. The "correct order" for JS object properties is first all
array-like index properties (numeric keys) sorted by insertion order,
followed by all string properties sorted by insertion order.

Objects also now print correctly in the repl! Before this commit:

courage ~/js-tests $ js
> ({ foo: 1, bar: 2, baz: 3 })
{ bar: 2, foo: 1, baz: 3 }

After:

courage ~/js-tests $ js
> ({ foo: 1, bar: 2, baz: 3 })
{ foo: 1, bar: 2, baz: 3 }
2020-04-29 18:47:03 +02:00
Kesse Jones
58f6f50de4 LibJS: Add String.prototype.slice 2020-04-29 18:35:18 +02:00
Andreas Kling
aaf35112a4 LibJS: Pass JS::Function around by reference more 2020-04-29 13:43:57 +02:00
Andreas Kling
a38658dc88 LibJS: Don't use Optional<Value> for bound |this| values
Just use a plain Value since it already has an empty state.
2020-04-29 12:41:58 +02:00
Andreas Kling
698652a548 LibJS: Make Value::as_string() return a PrimitiveString reference 2020-04-29 12:35:39 +02:00
Andreas Kling
75f246dde8 LibJS: Make StringObject::primitive_string() return a reference 2020-04-29 12:33:28 +02:00
Linus Groh
d4ec38097f LibJS: Return undefined in Array.prototype.{pop,shift} for empty values 2020-04-29 09:38:25 +02:00
mattco98
18cfb9218a LibJS: Set Array length attributes to "Configurable | Writable" 2020-04-29 09:02:29 +02:00