Commit graph

126 commits

Author SHA1 Message Date
Shannon Booth
f87041bf3a LibGC+Everywhere: Factor out a LibGC from LibJS
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
2024-11-15 14:49:20 +01:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Andreas Kling
db790dda62 LibJS: Remove hand-rolled type information in JS AST in favor of RTTI 2021-01-01 19:34:07 +01:00
AnotherTest
b34b681811 LibJS: Track source positions all the way down to exceptions
This makes exceptions have a trace of source positions too, which could
probably be helpful in making fancier error tracebacks.
2020-12-29 00:58:43 +01:00
Andreas Kling
d617120499 LibJS: Parse "with" statements :^) 2020-11-28 17:16:48 +01:00
Linus Groh
39a1c9d827 LibJS: Implement 'new.target'
This adds a new MetaProperty AST node which will be used for
'new.target' and 'import.meta' meta properties. The parser now
distinguishes between "in function context" and "in arrow function
context" (which is required for this).
When encountering TokenType::New we will attempt to parse it as meta
property and resort to regular new expression parsing if that fails,
much like the parsing of labelled statements.
2020-11-02 22:40:59 +01:00
Linus Groh
9e80c67608 LibJS: Fix "use strict" directive false positives
By having the "is this a use strict directive?" logic in
parse_string_literal() we would apply it to *any* string literal, which
is incorrect and would lead to false positives - e.g.:

    "use strict" + 1
    `"use strict"`
    "\123"; ({"use strict": ...})

Relevant part from the spec which is now implemented properly:

[...] and where each ExpressionStatement in the sequence consists
entirely of a StringLiteral token [...]

I also got rid of UseStrictDirectiveState which is not needed anymore.

Fixes #3903.
2020-11-02 13:13:54 +01:00
Linus Groh
80bb62b9cc LibJS: Distinguish between statement and declaration
This separates matching/parsing of statements and declarations and
fixes a few edge cases where the parser would incorrectly accept a
declaration where only a statement is allowed - for example:

    if (foo) const a = 1;
    for (var bar;;) function b() {}
    while (baz) class c {}
2020-10-23 19:13:06 +02:00
Linus Groh
aa71dae03c LibJS: Implement logical assignment operators (&&=, ||=, ??=)
TC39 proposal, stage 4 as of 2020-07.
https://tc39.es/proposal-logical-assignment/
2020-10-05 17:57:26 +02:00
Matthew Olsson
6eb6752c4c LibJS: Strict mode is now handled by Functions and Programs, not Blocks
Since blocks can't be strict by themselves, it makes no sense for them
to store whether or not they are strict. Strict-ness is now stored in
the Program and FunctionNode ASTNodes. Fixes issue #3641
2020-10-04 10:46:12 +02:00
Linus Groh
fd32f00839 LibJS: Mark more ASTNode classes as final 2020-09-18 20:49:35 +02:00
Jack Karamanian
7533fd8b02 LibJS: Initial class implementation; allow super expressions in object
literal methods; add EnvrionmentRecord fields and methods to
LexicalEnvironment

Adding EnvrionmentRecord's fields and methods lets us throw an exception
when |this| is not initialized, which occurs when the super constructor
in a derived class has not yet been called, or when |this| has already
been initialized (the super constructor was already called).
2020-06-29 17:54:54 +02:00
Andreas Kling
25f2a29d84 LibJS: Pass GlobalObject& to AST node execute() functions
More work towards supporting multiple global objects.
2020-06-08 21:12:20 +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
Marcin Gasperowicz
2579d0bf55 LibJS: Hoist function declarations
This patch adds function declaration hoisting. The mechanism
is similar to var hoisting. Hoisted function declarations are to be put
before the hoisted var declarations, hence they have to be treated
separately.
2020-06-06 10:53:06 +02:00
Matthew Olsson
ab576e610c LibJS: Rewrite Parser.parse_object_expression()
This rewrite drastically increases the accuracy of object literals.
Additionally, an "assertIsSyntaxError" function has been added to
test-common.js to assist in testing syntax errors.
2020-06-01 13:11:21 +02:00
Jack Karamanian
c12125fa81 LibJS: Track whether ScriptFunctions and FunctionExpressions are arrow
functions
2020-05-30 10:33:24 +02:00
Matthew Olsson
03615a7872 LibJS: Parse labels in continue and break statements 2020-05-29 16:20:32 +02:00
Matthew Olsson
10bf4ba3dc LibJS: Parse labelled statements
All statements now have an optional label string that can be null.
2020-05-29 16:20:32 +02:00
Matthew Olsson
786722149b LibJS: Add strict mode
Adds the ability for a scope (either a function or the entire program)
to be in strict mode. Scopes default to non-strict mode.

There are two ways to determine the strict-ness of the JS engine:

1. In the parser, this can be accessed with the parser_state variable
   m_is_strict_mode boolean. If true, the Parser is currently parsing in
   strict mode. This is done so that the Parser can generate syntax
   errors at parse time, which is required in some cases.

2. With Interpreter.is_strict_mode(). This allows strict mode checking
   at runtime as opposed to compile time.

Additionally, in order to test this, a global isStrictMode() function
has been added to the JS ReplObject under the test-mode flag.
2020-05-28 17:18:42 +02:00
Emanuele Torre
d1bc1f5783
LibJS: Fix style inconsistencies in AST.h (#2403)
Our current configuration clang-format allows both of these styles:
------------------
    class A : B
        , C {
-----------------
    class A
        : B
        , C {
------------------

I was not able to find a setting of clang-format to only allow the
latter style (or disallow the first style), but let's at least be
consistent with the style within a file.
2020-05-26 19:52:03 +02:00
Linus Groh
07af2e6b2c LibJS: Implement basic for..in and for..of loops 2020-05-25 18:45:36 +02:00
Matthew Olsson
c35732c011 LibJS: Add object literal getter/setter shorthand
Adds support for the following syntax:

let foo = {
    get x() {
        // ...
    },
    set x(value) {
        // ...
    }
}
2020-05-22 10:59:05 +02:00
Linus Groh
d69ed91790 LibJS: Check AssignmentExpression LHS in parser
There are many cases which shouldn't even parse, like

null = ...
true = ...
false = ...
123 = ...
"foo" = ...

However this *is* valid syntax:

foo() = ...

So we still have to keep the current code doing a runtime check if the
LHS value is a resolvable reference. I believe this was declared valid
syntax to *in theory* allow functions returning references - though in
practice that isn't a thing.

Fixes #2204.
2020-05-13 01:15:29 +02:00
Matthew Olsson
b5f1df57ed LibJS: Add raw strings to tagged template literals
When calling a function with a tagged template, the first array that is
passed in now contains a "raw" property with the raw, escaped strings.
2020-05-07 23:05:55 +02:00
Matthew Olsson
107ca2e4ba LibJS: Add function call spreading
Adds support for the following syntax:

    myFunction(...x, ...[1, 2, 3], ...o.foo, ...'abcd')
2020-05-06 19:19:02 +02:00
Matthew Olsson
838390171c LibJS: Function.length respects default and rest parameters
"[Function.length is] the number of formal parameters. This number
excludes the rest parameter and only includes parameters before
the first one with a default value." - MDN
2020-05-06 17:40:56 +02:00
Linus Groh
4d20cf57db LibJS: Implement tagged template literals (foobar)
To make processing tagged template literals easier, template literals
will now add one empty StringLiteral before and after each template
expression *if* there's no other string - e.g.:

`${foo}` -> "", foo, ""
`test${foo}${bar}test` -> "test", foo, "", bar, "test"

This also matches the behaviour of many other parsers.
2020-05-06 14:49:53 +02:00
Linus Groh
72d2bd56ce LibJS: Implement modulo assignment operator (%=) 2020-05-05 11:12:27 +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
8bd9f7e50e LibJS: run clang-format on all the files 2020-05-05 09:15:16 +02:00
Linus Groh
454c1e6bbe LibJS: Implement rest parameters 2020-05-04 23:30:52 +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
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
Linus Groh
43c1fa9965 LibJS: Implement (no-op) debugger statement 2020-05-01 22:07:13 +02:00
mattco98
104969a9f5 LibJS: Add spreading in object literals
Supports spreading strings, arrays, and other objects within object
literals.
2020-04-28 20:37:21 +02:00
Andreas Kling
ee0bf55127 LibJS: Make AssignmentExpression assign through a Reference
Reference now has assign(Interpreter&, Value) which is used to write
transparently through a Reference into whatever location it refers to.
2020-04-28 15:07:08 +02:00
Andreas Kling
3c4a9e421f LibJS: Allow "delete someGlobalVariable"
This is solved by allowing Identifier nodes to produce a Reference with
the global object as base.
2020-04-28 15:07:08 +02:00
Andreas Kling
67b8e6fc5b LibJS: Add Reference class to represent a base.property reference
Expression nodes can now be asked to produce a Reference. We then use
this to implement the "delete" operator without downcasting the child
node to a MemberExpression manually.
2020-04-28 15:07:08 +02:00
mattco98
80fecc615a LibJS: Add spreading in array literals
Implement the syntax and behavor necessary to support array literals
such as [...[1, 2, 3]]. A type error is thrown if the target of the
spread operator does not evaluate to an array (though it should
eventually just check for an iterable).

Note that the spread token's name is TripleDot, since the '...' token is
used for two features: spread and rest. Calling it anything involving
'spread' or 'rest' would be a bit confusing.
2020-04-27 11:32:18 +02:00
Andreas Kling
f897c41092 LibJS: Implement basic support for the "delete" operator
It turns out "delete" is actually a unary op :)
This patch implements deletion of object properties, it doesn't yet
work for casually deleting properties from the global object.

When deleting a property from an object, we switch that object to
having a unique shape, no longer sharing shapes with others.
Once an object has a unique shape, it no longer needs to care about
shape transitions.
2020-04-26 15:51:07 +02:00
Linus Groh
746dd5b190 LibJS: Implement computed properties in object expressions 2020-04-23 23:56:04 +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