Commit graph

199 commits

Author SHA1 Message Date
Evan Smal
3226ce3d83 LibJS: Remove some usage of DeprecatedString usage from Lexer
This changes the filename member from DeprecatedString to String. Parser
has also been updated to meet the updated Lexer interface.
2023-01-26 20:25:25 +00:00
Evan Smal
cfa6b4d815 LibJS: Remove DeprecatedString usage from Token 2023-01-26 20:25:25 +00:00
Evan Smal
93674e4383 LibJS: Remove DeprecatedString usage from SourceCode
This change also requires updates to some users of the SourceCode
interface since it no longer use DeprecatedString.
2023-01-26 20:25:25 +00:00
davidot
bff038411a LibJS: Add using declaration support in for and for of loops
The using declarations have kind of special behavior in for loops so
this is seperated.
2023-01-23 09:56:50 +00:00
davidot
541637e15a LibJS: Add using declaration support, RAII like operation in js
In this patch only top level and not the more complicated for loop using
statements are supported. Also, as noted in the latest meeting of tc39
async parts of the spec are not stage 3 thus not included.
2023-01-23 09:56:50 +00:00
Timothy Flynn
f3db548a3d AK+Everywhere: Rename FlyString to DeprecatedFlyString
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
2023-01-09 23:00:24 +00:00
davidot
2bbea62176 LibJS: Don't update names of resulting functions in object expression
The only cases where the name should be set is if the function comes
from a direct anonymous function expression.
2022-12-14 15:27:08 +00:00
Andreas Kling
9721da2e6a LibJS: Call shrink_to_fit() on various Vectors created during parse
Vectors that stick around in the AST were wasting a fair bit of memory
due to the growth padding we keep by default. This patch goes after some
of these vectors with the shrink_to_fit() stick to reduce waste.

Since the AST can stay around for a long time, it is worth making an
effort to shrink it down when we have a chance.
2022-12-08 23:36:17 +00:00
Andreas Kling
b894acd6b2 LibJS: Make one compact allocation for CallExpression and its Arguments
Instead of CallExpression storing its arguments in a Vector<Argument>,
we now custom-allocate the memory slot for CallExpression (and its
subclass NewExpression) so that it fits both CallExpression and its list
of Arguments in one allocation.

This reduces memory usage on twitter.com/awesomekling by 8.8 MiB :^)
2022-12-08 23:36:17 +00:00
Linus Groh
57dc179b1f Everywhere: Rename to_{string => deprecated_string}() where applicable
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.

One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
2022-12-06 08:54:33 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
davidot
d218a68296 LibJS: Allow CallExpressions as lhs of assignments in most cases
Although not quite like the spec says the web reality is that a lhs
target of CallExpression should not give a SyntaxError but only a
ReferenceError once executed.
2022-11-30 08:05:37 +01:00
davidot
2c26ee89ac LibJS: Remove m_first_invalid_property_range from ObjectExpression
This was state only used by the parser to output an error with
appropriate location. This shrinks the size of ObjectExpression from
120 bytes down to just 56. This saves roughly 2.5 MiB when loading
twitter.
2022-11-27 12:31:37 +01:00
davidot
3acbd96851 LibJS: Remove is_use_strict_directive for all StringLiterals
This value was only used in the parser so no need to have this in every
string literal in the ast.
2022-11-27 12:31:37 +01:00
Andreas Kling
d16fab5815 LibJS: Avoid unnecessary SourceRange construction in parse_program()
This takes `test-js` runtime from 4.3 sec to 4.1 sec on my machine.
2022-11-24 16:06:20 +00:00
Andreas Kling
835d7aac96 LibJS: Make FunctionNode::Parameter be a standalone FunctionParameter
This will allow us to forward declare it and avoid including AST.h in a
number of places.
2022-11-23 16:05:59 +00:00
Andreas Kling
e0916dbb35 LibJS: Move {Import,Export}Entry out of {Import,Export}Statement
By making these be standalone instead of nested structs, we can forward
declare them. This will allow us to stop including AST.h in some places.
2022-11-23 16:05:59 +00:00
Andreas Kling
76f438eb3e LibJS: Remove unused "lexical argument index" metadata from Identifier
This shrinks Identifier by 16 bytes. :^)
2022-11-22 21:13:35 +01:00
Andreas Kling
b0b022507b LibJS: Reduce AST memory usage by shrink-wrapping source range info
Before this change, each AST node had a 64-byte SourceRange member.
This SourceRange had the following layout:

    filename:       StringView (16 bytes)
    start:          Position (24 bytes)
    end:            Position (24 bytes)

The Position structs have { line, column, offset }, all members size_t.

To reduce memory consumption, AST nodes now only store the following:

    source_code:    NonnullRefPtr<SourceCode> (8 bytes)
    start_offset:   u32 (4 bytes)
    end_offset:     u32 (4 bytes)

SourceCode is a new ref-counted data structure that keeps the filename
and original parsed source code in a single location, and all AST nodes
have a pointer to it.

The start_offset and end_offset can be turned into (line, column) when
necessary by calling SourceCode::range_from_offsets(). This will walk
the source code string and compute line/column numbers on the fly, so
it's not necessarily fast, but it should be rare since this information
is primarily used for diagnostics and exception stack traces.

With this, ASTNode shrinks from 80 bytes to 32 bytes. This gives us a
~23% reduction in memory usage when loading twitter.com/awesomekling
(330 MiB before, 253 MiB after!) :^)
2022-11-22 21:13:35 +01:00
davidot
73fcbbb0ee LibJS: Give the undeclared private identifier error more precedence
Before this could give the `must be followed by in` error before the
undeclared private identifier error. Fixing the `in` error would not
have resolved the other error so this order makes the errors more
actionable.
2022-11-17 16:05:20 +00:00
davidot
16ac43c9d4 LibJS: Make sure private identifier is valid in optional chain
If we don't check that a private identifier is valid this can break the
assumption that we have a private environment when evaluation the
private identifier. Also an unknown private identifier this should
be a SyntaxError.
2022-11-17 16:05:20 +00:00
davidot
5ca6e8dca8 LibJS: No longer hoist if parent scope has a function with the same name 2022-11-17 16:05:20 +00:00
davidot
67865306d3 LibJS: Fix that functions in module did not look for var declarations 2022-11-15 12:00:36 +00:00
davidot
9f661d20f7 LibJS: Allow anonymous functions as default exports
This requires a special case with names as the default function is
supposed to have a unique name ("*default*" in our case) but when
checked should have name "default".
2022-09-02 02:07:37 +01:00
davidot
faf1430ce4 LibJS: Allow exporting any imported bindings 2022-09-02 02:07:37 +01:00
davidot
3b1c3e574f LibJS: Handle empty named export
This is an export which looks like `export {} from "module"`, and
although it doesn't have any real export entries it should still add
"module" to the required modules to load.
2022-09-02 02:07:37 +01:00
davidot
f75c51b097 LibJS: Allow full ModuleExportName in namespace
This means we should accept a string after 'export * as '.
2022-09-02 02:07:37 +01:00
davidot
fce2b33758 LibJS: Allow BigInts as destructuring property names
These are simply treated as their numerical value which means that above
2^32 - 1 they are strings.
2022-08-24 23:27:17 +01:00
davidot
ae349ec6a8 LibJS: Use a synthetic constructor if class with parent doesn't have one
We already did this but it called the @@iterator method of
%Array.prototype% visible to the user for example by overriding that
method. This should not be visible so we use a special version of
SuperCall now.
2022-08-20 23:53:55 +01:00
davidot
e5adc51e27 LibJS: Allow invalid string in tagged template literals
Since tagged template literals can inspect the raw string it is not a
syntax error to have invalid escapes. However the cooked value should be
`undefined`.
We accomplish this by tracking whether parse_string_literal
fails and then using a NullLiteral (since UndefinedLiteral is not a
thing) and finally converting null in tagged template execution to
undefined.
2022-08-17 23:56:24 +01:00
Ali Mohammad Pur
f4b26b0cea LibJS: Hook up the 'v' (unicodeSets) RegExp flag 2022-07-20 21:25:59 +01:00
sin-ack
3f3f45580a Everywhere: Add sv suffix to strings relying on StringView(char const*)
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).

No functional changes.
2022-07-12 23:11:35 +02:00
Daniel Bertalan
ebac8abc04 LibJS: Explicitly instantiate Parser::parse_function_node
Due to macOS visibility rules, this function did not end up being
exported from liblagom-js.dylib, causing LagomWeb to fail to link.
2022-07-04 21:46:02 +02:00
Linus Groh
5a26a547db LibJS: Update a couple of outdated spec comments
These are editorial changes in the ECMA-262 spec.

See:
- https://github.com/tc39/ecma262/commit/e080a7f
- https://github.com/tc39/ecma262/commit/c5a9094
- https://github.com/tc39/ecma262/commit/5091520
- https://github.com/tc39/ecma262/commit/1c6564b
- https://github.com/tc39/ecma262/commit/e06c80c
2022-05-01 22:47:38 +02:00
Luke Wilde
34f902fb52 LibJS: Add missing steps and spec comments to PerformEval
While adding spec comments to PerformEval, I noticed we were missing
multiple steps.

Namely, these were:
- Checking if the host will allow us to compile the string
  (allowing LibWeb to perform CSP for eval)
- The parser's initial state depending on the environment around us
  on direct eval:
   - Allowing new.target via eval in functions
   - Allowing super calls and super properties via eval in classes
   - Disallowing the use of the arguments object in class field
     initializers at eval's parse time
- Setting ScriptOrModule of eval's execution context

The spec allows us to apply the additional parsing steps in any order.
The method I have gone with is passing in a struct to the parser's
constructor, which overrides the parser's initial state to (dis)allow
the things stated above from the get-go.
2022-04-11 21:23:36 +01:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Idan Horowitz
7ebb421ee9 LibJS: Implement the object literal __proto__ property key special case 2022-03-06 01:38:25 +02:00
davidot
2c6183da1e LibJS: Allow methods in classes named 'async'
Also add tests for all static, setter and getter cases.
2022-02-18 13:47:47 +00:00
davidot
65bebb5241 LibJS: Allow CallExpression as left hand side of for-of/for-in loops
Although this will fail with a ReferenceError it should pass the parser
and only fail if actually assigned to.
2022-02-18 13:47:47 +00:00
Anonymous
602190f66f LibJS: Fix mixing of logical and coalescing operators
The same expression is not allowed to contain both the
logical && and || operators, and the coalescing ?? operator.

This patch changes how "forbidden" tokens are handled, using a
finite set instead of an Vector. This supports much more efficient
merging of the forbidden tokens when propagating forward, and
allowing the return of forbidden tokens to parent contexts.
2022-02-16 11:18:41 +00:00
Anonymous
f55d7bf6f3 LibJS: Fix cases where we incorrectly allowed 'in' in for loops
We needed to propagate the forbidden token set to all parsing functions
that can call back into parse_expression.
2022-02-15 10:31:41 +00:00
Andreas Kling
50a446a5d1 LibJS: Make more use of Token::flystring_value()
This patch makes check_identifier_name_for_assignment_validity()
take a FlyString instead of a StringView. We then exploit this by
passing FlyString in more places via flystring_value().

This gives a ~1% speedup when parsing the largest Discord JS file.
2022-02-13 14:44:36 +01:00
Andreas Kling
0cb0979990 LibJS: Add Token::flystring_value() to produce FlyString directly
When parsing identifiers, we ultimately want to sink the token string
into a FlyString anyway, and since Token may have a FlyString already
inside it, this allows us to bypass the costly FlyString(StringView).

This gives a ~3% speedup when parsing the largest Discord JS file.
2022-02-13 14:44:36 +01:00
Andreas Kling
1a3fa2d88b LibJS: Make Parser::ScopePusher::has_declaration() take FlyString
Everyone who calls this already has a FlyString, so we were doing *way*
more work by pessimizing it to a StringView.

This gives a ~2% speedup when parsing the largest Discord JS file.
2022-02-13 14:44:36 +01:00
davidot
4136cbdb09 LibJS: Convert ScopeNode declaration functions to ThrowCompletionOr
This removes a number of vm.exception() checks which are now caught
directly by TRY. Make use of these checks in
{Global, Eval}DeclarationInstantiation and while we're here add spec
comments.
2022-02-08 09:12:42 +00:00
Linus Groh
6f20f49b21 Everywhere: Rename JS::PropertyKey variables from property_{name => key}
PropertyKey used to be called PropertyName, but got renamed. Let's
update all the variables of this type as well.
2022-02-06 22:02:45 +00:00
davidot
e0e4ead2c8 LibJS: Follow the spec with storing im- and export entries
Because we can have arbitrary in- and export names with strings we can
have '*' and '' which means using '*' as an indicating namespace imports
failed / behaved incorrectly for string imports '*'.
We now use more specific types to indicate these special states instead
of these 'magic' string values.

Do note that 'default' is not actually a magic string value but one
specified by the spec. And you can in fact export the default value by
doing: `export { 1 as default }`.
2022-01-30 17:40:20 +00:00
davidot
99edf5b25a LibJS: Track whether a program has a top level await statement 2022-01-22 01:21:18 +00:00
davidot
aca427fc8c LibJS: Make parsing import and export entries follow the spec
The big changes are:
- Allow strings as Module{Export, Import}Name
- Properly track declarations in default export statements

However, the spec is a little strange in that it allows function and
class declarations without a name in default export statements.
This is quite hard to fully implement without rewriting more of the
parser so for now this behavior is emulated by faking things with
function and class expressions. See the comments in
parse_export_statement for details on the hacks and where it goes wrong.
2022-01-22 01:21:18 +00:00
Linus Groh
531d1ac734 LibJS: Capture source text of FunctionNode and ClassExpression 2022-01-19 20:33:08 +00:00