Commit graph

94 commits

Author SHA1 Message Date
AnotherTest
3bc3f36cfe LibLine: Handle unicode correctly
This commit also fixes a problem with us throwing out data that was
inserted while a command was running.
2020-05-18 11:31:43 +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
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
4e0ed34d7e js: Throw a regular SyntaxError for errors from the parser 2020-05-15 09:53:52 +02:00
Linus Groh
00b61a212f LibJS: Remove syntax errors from lexer
Giving the lexer the ability to generate errors adds unnecessary
complexity - also it only calls its syntax_error() function in one place
anyway ("unterminated string literal"). But since the lexer *also* emits
tokens like Eof or UnterminatedStringLiteral, it should be up to the
consumer of these tokens to decide what to do.

Also remove the option to not print errors to stderr as that's not
relevant anymore.
2020-05-15 09:53:52 +02:00
AnotherTest
c40fd3a902 LibLine: Support RGB colors
This also patches Userland/js.
2020-05-10 10:23:05 +02:00
Andreas Kling
5c12f3fef0 js: Tighten up ReplConsoleClient::trace() a little bit
Remove a bunch of unnecessary String copying.
2020-05-05 11:49:14 +02:00
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
Emanuele Torre
73a7a589c2 js: Customise the behaviour of JS::Console with ReplConsoleClient
This also makes our JavaScript tests not fail.
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
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
ce0bed0482 js: Ignore property attributes for completion
Only being able to complete enumerable properties is annoying,
especially since we updated everything to use the correct attributes.

Most standard built-in objects are *not* enumerable.
2020-05-02 19:21:50 +02:00
Emanuele Torre
e861af2a5c js: Print ConsoleMessages and color the output based on their kind :^) 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
Andreas Kling
b2b30567ab js: Turn on live syntax highlighting by default 2020-04-30 22:37:50 +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
Andreas Kling
698652a548 LibJS: Make Value::as_string() return a PrimitiveString reference 2020-04-29 12:35:39 +02:00
AnotherTest
9473733d7a LibLine: Handle initialize() internally
This patch makes initialize() transparent to the users, but exposes it
publicly, as the users might need a copy of the default termios (i.e.
Shell)
2020-04-28 23:29:07 +02:00
AnotherTest
7ecf29f206 LibLine: Ignore interrupts unless actively editing
It does not make much sense to receive an interrupt and process it
*much later*.
Also patches Userland/js to only create exceptions while some code is
actually running.
2020-04-28 23:29:07 +02:00
Linus Groh
9540174b40 js: Follow Serenity C++ naming conventions 2020-04-26 18:09:22 +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
a832ab0f4e js: Interrupt running script or REPL evaluation when receiving SIGINT 2020-04-24 19:43:34 +02:00
Linus Groh
95b51e857d LibJS: Add TokenType::TemplateLiteral
This is required for template literals - we're not quite there yet, but at
least the parser can now tell us when this token is encountered -
currently this yields "Unexpected token Invalid". Not really helpful.

The character is a "backtick", but as we already have
TokenType::{StringLiteral,RegexLiteral} this seemed like a fitting name.

This also enables syntax highlighting for template literals in the js
REPL and LibGUI's JSSyntaxHighlighter.
2020-04-24 11:18:57 +02:00
AnotherTest
cb3cf589ed LibLine: Allow suggestions to have trailing trivia strings
These strings would be applied when inserted into the buffer, but are
not shown as part of the suggestion.

This commit also patches up Userland/js and Shell to use this
functionality
2020-04-19 17:21:55 +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
6833004a45 js: Tweak the live syntax highlighting colors a bit 2020-04-16 16:37:32 +02:00
Andreas Kling
64f5185bae js: Tweak colorization of printed values a bit 2020-04-15 10:11:48 +02:00
Brian Gianforcaro
d74ad81402 js/LibJS: Move test functions to pure javascript.
The addition of assert functions to Userland/js
was done before we had load(..) implemented. Now
that it exists, it seems like the right move the
test helper functions to pure javascript instead
of poluting js with random global functions.
2020-04-14 12:55:31 +02:00
Linus Groh
8e08d111da js: Output text using printf() and return undefined in help() 2020-04-13 23:12:17 +02:00
Linus Groh
0040d6bf2d js: Add assertNotReached() function in test mode 2020-04-13 16:28:50 +02:00
Stephan Unverwerth
984c290ec0 LibJS: Do not execute scripts with parse errors
This adds missing checks in several LibJS consumers.
2020-04-13 10:42:25 +02:00
Brian Gianforcaro
50b6b6ef86 js: Make load() available when running with --test-mode
The work I did to add assert as a native function in js
was a step in the wrong direction. Now that js supports
load() it makes sense to just move assert and anything
we want to add to the test harness into pure javascript.
2020-04-13 10:31:06 +02:00
Linus Groh
6d5d668585 js: Coerce assert() argument to boolean
It's JavaScript after all :^)
2020-04-13 00:47:53 +02:00
Linus Groh
31d0dbe2a0 js: Stylize TokenType::{Throw,Switch,Case} 2020-04-11 17:15:40 +02:00
AnotherTest
2fdce695d6 LibLine: Display suggestions and cycle between them
With extra color (tm)
This commit also patches the users of LibLine to properly use the new
API
2020-04-11 17:15:19 +02:00
AnotherTest
70da0e3fb5 Userland: Add primitive autocomplete to the JS repl
This patch adds primitive support for autocompletion in the JS repl,
it only supports completing global names and properties on variables :^)
2020-04-11 14:29:25 +02:00
AnotherTest
586aa3b1de Userland: Install LibLine's signal handlers in the JS repl 2020-04-11 14:29:25 +02:00
AnotherTest
6545a74743 JS repl: Fix indentation when a line starts with '})]' 2020-04-10 00:58:59 +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
Linus Groh
755b206618 LibJS: Handle empty values in Value::to_string() 2020-04-08 18:51:34 +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
Andreas Kling
90ba0145f6 LibJS: Add a number-indexed property storage to all Objects
Objects can have both named and indexed properties. Previously we kept
all property names as strings. This patch separates named and indexed
properties and splits them between Object::m_storage and m_elements.

This allows us to do much faster array-style access using numeric
indices. It also makes the Array class much less special, since all
Objects now have number-indexed storage. :^)
2020-04-06 18:09:26 +02:00
AnotherTest
d077637fd6 JS Repl: Add live syntax highlighting
This patchset adds live syntax highlighting to the js repl.
It is turned off by default and can be enabled via the -s flag.
2020-04-05 16:11:13 +02:00
Brian Gianforcaro
4233c8662b js: Add a new --test-mode option, which exposes an assert() function.
Introduce a central assert implementation so that the LibJS test suite
can take advantage of one implementation instead of copy/pasting the
same function into every test case file.
2020-04-05 15:28:45 +02:00
Linus Groh
79539378c6 js: Add lines to history 2020-04-05 01:54:38 +02:00
Andreas Kling
2db8716a6f LibJS: Don't return the "last computed value" from Interpreter::run()
Only return whatever a "return" statment told us to return.
The last computed value is now available in Interpreter::last_value()
instead, where the REPL can pick it up.
2020-04-04 23:45:13 +02:00
Linus Groh
cd3e2690eb LibJS: Set length property in Object::put_native_function() 2020-04-04 15:58:49 +02:00
Andreas Kling
faac43597a LibJS: Add js_string(Interpreter&, String) 2020-04-04 12:58:05 +02:00