Age | Commit message (Collapse) | Author |
|
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.
|
|
Adds support for the following syntax:
myFunction(...x, ...[1, 2, 3], ...o.foo, ...'abcd')
|
|
"[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
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
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'
|
|
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.
|
|
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.
|
|
|
|
Supports spreading strings, arrays, and other objects within object
literals.
|
|
Reference now has assign(Interpreter&, Value) which is used to write
transparently through a Reference into whatever location it refers to.
|
|
This is solved by allowing Identifier nodes to produce a Reference with
the global object as base.
|
|
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.
|
|
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.
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"var" declarations are hoisted to the nearest function scope, while
"let" and "const" are hoisted to the nearest block scope.
This is done by the parser, which keeps two scope stacks, one stack
for the current var scope and one for the current let/const scope.
When the interpreter enters a scope, we walk all of the declarations
and insert them into the variable environment.
We don't support the temporal dead zone for let/const yet.
|
|
|
|
|
|
Many other parsers call it with this name.
Also Type can be confusing in this context since the DeclarationType is
not the type (number, string, etc.) of the variables that are being
declared by the VariableDeclaration.
|
|
This patch only adds the AST node, the parser doesn't create them yet.
|
|
Now that we have two separate storages for Object properties depending
on what kind of index they have, it's nice to have an abstraction that
still allows us to say "here's a property name".
We use PropertyName to always choose the optimal storage path directly
while interpreting the AST. :^)
|
|
|
|
|
|
We were allowing this dangerous kind of thing:
RefPtr<Base> base;
RefPtr<Derived> derived = base;
This patch changes the {Nonnull,}RefPtr constructors so this is no
longer possible.
To downcast one of these pointers, there is now static_ptr_cast<T>:
RefPtr<Derived> derived = static_ptr_cast<Derived>(base);
Fixing this exposed a ton of cowboy-downcasts in various places,
which we're now forced to fix. :^)
|
|
|
|
This patch adds support in the parser and interpreter for this:
var a = 1, b = 2, c = a + b;
VariableDeclaration is now a sequence of VariableDeclarators. :^)
|
|
This is just here to make the AST class hierarchy more spec-like.
|
|
|
|
This name matches other parsers.
|
|
|
|
|
|
There is no such thing as a "undefined literal" in JS - undefined is
just a property on the global object with a value of undefined.
This is pretty similar to NaN.
var undefined = "foo"; is a perfectly fine AssignmentExpression :^)
|
|
|
|
This avoids executing the LHS of the object expression twice when doing
a call on the result of an object expression.
|
|
The "break" keyword now unwinds to the nearest ScopeType::Breakable.
There's no support for break labels yet, but we'll get there too.
|
|
|
|
This operator walks the prototype chain of the RHS value and looks for
a "prototype" property with the same value as the prototype of the LHS.
This is pretty cool. :^)
|