summaryrefslogtreecommitdiff
path: root/Libraries/LibJS/AST.cpp
AgeCommit message (Collapse)Author
2020-06-20LibJS: Pass GlobalObject& to Reference get/putAndreas Kling
2020-06-20LibJS: Make Value::to_object() take a GlobalObject&Andreas Kling
2020-06-20LibJS: Pass GlobalObject& when constructing an AccessorAndreas Kling
2020-06-20LibJS: Remove some more use of Interpreter::global_object()Andreas Kling
Let's do some more work towards supporting multiple global objects.
2020-06-11LibJS: Consolidate error messages into ErrorTypes.hMatthew Olsson
Now, exceptions can be thrown with interpreter.throw_exception<T>(ErrorType:TYPE, "format", "args", "here").
2020-06-08LibJS: Make more Interpreter functions take a GlobalObject&Andreas Kling
2020-06-08LibJS: Interpreter::this_value() => this_value(GlobalObject&)Andreas Kling
Once the Interpreter has no global object attached to it, we have to provide it everywhere.
2020-06-08LibJS: Pass GlobalObject& to AST node execute() functionsAndreas Kling
More work towards supporting multiple global objects.
2020-06-08LibJS: Add interpreter exception checksMatthew Olsson
2020-06-07LibJS: Add BigIntLinus Groh
2020-06-07LibJS: Lex and parse regex literals, add RegExp objectsMatthew Olsson
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-06LibJS: Add Proxy objectsMatthew Olsson
Includes all traps except the following: [[Call]], [[Construct]], [[OwnPropertyKeys]]. An important implication of this commit is that any call to any virtual Object method has the potential to throw an exception. These methods were not checked in this commit -- a future commit will have to protect these various method calls throughout the codebase.
2020-06-06LibJS: Distinguish between omitted descriptor attributes and false onesMatthew Olsson
When calling Object.defineProperty, there is now a difference between omitting a descriptor attribute and specifying that it is false. For example, "{}" and "{ configurable: false }" will have different attribute values.
2020-06-06LibJS: Hoist function declarationsMarcin Gasperowicz
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-03LibJS: Make typeof return undefined for undefined variablesMarcin Gasperowicz
This makes `typeof i_dont_exist` return `undefined` instead of throwing an error.
2020-06-01LibJS: Fix casting a value to ScriptFunction without checking it's oneSergey Bugaev
2020-05-30LibJS: Track whether ScriptFunctions and FunctionExpressions are arrowJack Karamanian
functions
2020-05-29LibJS: Integrate labels into the InterpreterMatthew Olsson
The interpreter now considers a statement or block's label when considering whether or not to break. All statements can be labelled.
2020-05-29LibJS: Throw in strict mode when assigning property to primitive valueLinus Groh
2020-05-28LibJS: Object index properties have descriptors; Handle sparse indicesMatthew Olsson
This patch adds an IndexedProperties object for storing indexed properties within an Object. This accomplishes two goals: indexed properties now have an associated descriptor, and objects now gracefully handle sparse properties. The IndexedProperties class is a wrapper around two other classes, one for simple indexed properties storage, and one for general indexed property storage. Simple indexed property storage is the common-case, and is simply a vector of properties which all have attributes of default_attributes (writable, enumerable, and configurable). General indexed property storage is for a collection of indexed properties where EITHER one or more properties have attributes other than default_attributes OR there is a property with a large index (in particular, large is '200' or higher). Indexed properties are now treated relatively the same as storage within the various Object methods. Additionally, there is a custom iterator class for IndexedProperties which makes iteration easy. The iterator skips empty values by default, but can be configured otherwise. Likewise, it evaluates getters by default, but can be set not to.
2020-05-27LibJS: Simplify and normalize publicly-exposed Object functionsMatthew Olsson
Previously, the Object class had many different types of functions for each action. For example: get_by_index, get(PropertyName), get(FlyString). This is a bit verbose, so these methods have been shortened to simply use the PropertyName structure. The methods then internally call _by_index if necessary. Note that the _by_index have been made private to enforce this change. Secondly, a clear distinction has been made between "putting" and "defining" an object property. "Putting" should mean modifying a (potentially) already existing property. This is akin to doing "a.b = 'foo'". This implies two things about put operations: - They will search the prototype chain for setters and call them, if necessary. - If no property exists with a particular key, the put operation should create a new property with the default attributes (configurable, writable, and enumerable). In contrast, "defining" a property should completely overwrite any existing value without calling setters (if that property is configurable, of course). Thus, all of the many JS objects have had any "put" calls changed to "define_property" calls. Additionally, "put_native_function" and "put_native_property" have had their "put" replaced with "define". Finally, "put_own_property" has been made private, as all necessary functionality should be exposed with the put and define_property methods.
2020-05-25LibJS: Implement basic for..in and for..of loopsLinus Groh
2020-05-24LibJS: Refactor AccessorLinus Groh
This changes Accessor's m_{getter,setter} from Value to Function* which seems like a better API to me - a getter/setter must either be a function or missing, and the creation of an accessor with other values must be prevented by the parser and Object.defineProperty() anyway. Also add Accessor::set_{getter,setter}() so we can reuse an already created accessor when evaluating an ObjectExpression with getter/setter shorthand syntax.
2020-05-22LibJS: Add object literal getter/setter shorthandMatthew Olsson
Adds support for the following syntax: let foo = { get x() { // ... }, set x(value) { // ... } }
2020-05-18LibJS: Rename to_{i32,size_t}() to as_{i32,size_t}() for clarityLinus Groh
As these parameter-less overloads don't change the value's type and just assume Type::Number, naming them as_i32() and as_size_t() is more appropriate.
2020-05-18LibJS: Pass Interpreter& to Value::to_number() et al.Linus Groh
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-18LibJS: Change Value::to_object(Heap& -> Interpreter&)Linus Groh
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-17LibJS: Add symbol objectsmattco98
This commit adds the following classes: SymbolObject, SymbolConstructor, SymbolPrototype, and Symbol. This commit does not introduce any new functionality to the Object class, so they cannot be used as property keys in objects.
2020-05-15LibJS: Add side-effect-free version of Value::to_string()Andreas Kling
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-08LibJS: Correct tiny issue with passing a String to String::formatAnotherTest
I'm not sure how this even _builds_
2020-05-08LibJS: Spec-compliant equality comparisonsMatthew Olsson
The ECMAScript spec defines multiple equality operations which are used all over the spec; this patch introduces them. Of course, the two primary equality operations are AbtractEquals ('==') and StrictEquals ('==='), which have been renamed to 'abstract_eq' and 'strict_eq' in this patch. In support of the two operations mentioned above, the following have also been added: SameValue, SameValueZero, and SameValueNonNumeric. These are important to have, because they are used elsewhere in the spec aside from the two primary equality comparisons.
2020-05-07LibJS: Limit scope of 'for' loop variablesYonatan Goldschmidt
This required 2 changes: 1. In the parser, create a new variable scope, so the variable is declared in it instead of the scope in which the 'for' is found. 2. On execute, push the variable into the newly created block. Existing code created an empty block (no variables, no arguments) which allows Interpreter::enter_scope() to skip the creation of a new environment, therefore when the variable initializer is executed, it sets the variable to the outer scope. By attaching the variable to the new block, the block gets a new environment. This is only needed for 'let' / 'const' declarations, since 'var' declarations are expected to leak. Fixes: #2103
2020-05-07LibJS: Add raw strings to tagged template literalsMatthew Olsson
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-06LibJS: Add function call spreadingMatthew Olsson
Adds support for the following syntax: myFunction(...x, ...[1, 2, 3], ...o.foo, ...'abcd')
2020-05-06LibJS: Function.length respects default and rest parametersMatthew Olsson
"[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-06LibJS: Implement tagged template literals (foo`bar`)Linus Groh
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-06LibJS: Add Value::{is, as}_function()Linus Groh
2020-05-05LibJS: Implement modulo assignment operator (%=)Linus Groh
2020-05-05LibJS: Implement exponentiation assignment operator (**=)Linus Groh
2020-05-05LibJS: Implement bitwise assignment operators (&=, |=, ^=)Linus Groh
2020-05-04LibJS: Implement rest parametersLinus Groh
2020-05-04LibJS: Add indentation to sections in SwitchCase::dump()Linus Groh
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-04LibJS: Add template literalsmattco98
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-03LibJS: Set name of anonymous functions during assignmentLinus Groh
2020-05-03LibJS: Add function default argumentsMatthew Olsson
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-01LibJS: Implement (no-op) debugger statementLinus Groh
2020-05-01LibJS: Implement most of the Reflect objectLinus Groh
2020-04-30LibJS: Fix ConditionalExpression::dump()Linus Groh
Let's not print m_test three times :^)
2020-04-29LibJS: Implement correct object property orderingmattco98
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-29LibJS: Make Value::as_string() return a PrimitiveString referenceAndreas Kling