summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Interpreter.cpp
AgeCommit message (Collapse)Author
2021-09-12LibJS: Change Interpreter::create_with_existing_{global_object => realm}Linus Groh
We need both a GlobalObject and Realm now, but can get the former from the latter (once initialized). This also fixes JS execution in LibWeb, as we failed to set the Realm of the newly created Interpreter in this function.
2021-09-12LibJS: Set the callee context's realm in prepare_for_ordinary_call()Linus Groh
This includes making FunctionObject::realm() actually return a Realm, instead of a GlobalObject.
2021-09-12LibJS: Move the GlobalEnvironment from GlobalObject to RealmLinus Groh
This is where the spec wants to have it. Requires a couple of hacks as currently everything that needs a Realm actually has a GlobalObject, so we need to go via the Interpreter.
2021-09-12LibJS: Allocate a Realm next to GlobalObject in Interpreter::create()Linus Groh
Also pass a Realm reference to the Bytecode::Interpreter constructor, just like we pass the GlobalObject.
2021-08-10LibJS: Change ExecutionContext's arguments list to a MarkedValueListTimothy Flynn
The test262 tests under RegExp/property-escapes/generated will invoke Reflect.apply with up to 10,000 arguments at a time. In LibJS, when the call stack reached VM::call_internal, we transfer those arguments from a MarkedValueList to the execution context's arguments Vector. Because these types differ (MarkedValueList is a Vector<Value, 32>), the arguments are copied rather than moved. By changing the arguments vector to a MarkedValueList, we can properly move the passed arguments over. This shaves about 2 seconds off the following test262 test (from 15sec): RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js
2021-08-01LibJS: Remove unused header includesBrian Gianforcaro
2021-07-06LibJS: Remove the non-standard put helper and replace it's usagesIdan Horowitz
This removes all usages of the non-standard put helper method and replaces all of it's usages with the specification required alternative or with define_direct_property where appropriate.
2021-07-06LibJS: Improve function hoisting across blocksHendi
The parser now keeps track of a scope chain so that it can hoist function declarations to the closest function scope.
2021-07-01LibJS: Drop "Record" suffix from all the *Environment record classesAndreas Kling
"Records" in the spec are basically C++ classes, so let's drop this mouthful of a suffix.
2021-06-27LibJS: Rename ScriptFunction => OrdinaryFunctionObjectAndreas Kling
These are basically what the spec calls "ordinary function objects", so let's have the name reflect that. :^)
2021-06-24Userland: Replace VERIFY(is<T>) with verify_cast<T>Andreas Kling
Instead of doing a VERIFY(is<T>(x)) and *then* casting it to T, we can just do the cast right away with verify_cast<T>. :^)
2021-06-24LibJS: Rename CallFrame => ExecutionContextAndreas Kling
This struct represents what the ECMAScript specification calls an "execution context" so let's use the same terminology. :^)
2021-06-22LibJS: Begin implementing GlobalEnvironmentRecordAndreas Kling
These represent the outermost scope in the environment record hierarchy. The spec says they should be a "composite" of two things: - An ObjectEnvironmentRecord wrapping the global object - A DeclarativeEnvironmentRecord for other declarations It's not yet clear to me how this should work, so this patch only implements the first part, an object record wrapping the global object.
2021-06-22LibJS: Split the per-call-frame environment into lexical and variableAndreas Kling
To better follow the spec, we need to distinguish between the current execution context's lexical environment and variable environment. This patch moves us to having two record pointers, although both of them point at the same environment records for now.
2021-06-22LibJS: Bring function environment records closer to the specAndreas Kling
This patch adds FunctionEnvironmentRecord as a subclass of the existing DeclarativeEnvironmentRecord. Things that are specific to function environment records move into there, simplifying the base. Most of the abstract operations related to function environment records are rewritten to match the spec exactly. I also had to implement GetThisEnvironment() and GetSuperConstructor() to keep tests working after the changes, so that's nice as well. :^)
2021-06-21LibJS: Rename VM::current_scope() => current_environment_record()Andreas Kling
And rename some related functions that wrapped this as well.
2021-06-21LibJS: Rename virtuals in EnvironmentRecordAndreas Kling
This patch makes the following renames: - get_from_scope() => get_from_environment_record() - put_to_scope() => put_into_environment_record() - delete_from_scope() => delete_from_environment_record()
2021-06-21LibJS: Rename EnvironmentRecord::parent() => outer_environment()Andreas Kling
This name matches the spec (corresponds to the [[OuterEnv]] slot.)
2021-06-21LibJS: Rename Environment Records so they match the spec :^)Andreas Kling
This patch makes the following name changes: - ScopeObject => EnvironmentRecord - LexicalEnvironment => DeclarativeEnvironmentRecord - WithScope => ObjectEnvironmentRecord
2021-06-19LibJS: Restructure and fully implement BindingPatternsMatthew Olsson
2021-06-15LibJS: Add the FinalizationRegistry built-in objectIdan Horowitz
As well as the needed functionality in VM to enqueue and run cleanup jobs for the FinalizationRegistry instances.
2021-06-12LibJS: Store and maintain an "execution generation" counterIdan Horowitz
This counter is increased each time a synchronous execution sequence completes, and will allow us to emulate the abstract operations AddToKeptObjects & ClearKeptObjects efficiently.
2021-06-11LibJS: Use an enum class instead of 'bool is_generator'Ali Mohammad Pur
This avoid confusion in the order of the multiple boolean parameters that exist.
2021-06-11LibJS: Implement generator functions (only in bytecode mode)Ali Mohammad Pur
2021-06-10LibJS: Let the bytecode interpreter set the VM's last valueGunnar Beutner
2021-06-09LibJS: Only "var" declarations go in the global object at program levelAndreas Kling
"let" and "const" go in the lexical environment. This fixes one part of #4001 (Lexically declared variables are mixed up with global object properties)
2021-06-08LibJS: Return undefined from a with statement if no value was generatedIdan Horowitz
Co-authored-by: Linus Groh <mail@linusgroh.de>
2021-05-29LibJS: Implement destructuring assignments and function parametersAli Mohammad Pur
2021-05-13LibJS: Ensure function declarations don't leak outside function scopesLinus Groh
When using VM::set_variable() to put the created ScriptFunction onto a ScopeObject, we would previously unexpectedly reach the global object as set_variable() checks each traversed scope for an existing Variable with the given name - which would cause a leak of the inner function past the outer function (we even had a test expecting that behaviour!). Now we first declare functions (as DeclarationKind::Var) before setting them. This will need some more work to make hoisting across non-lexical scopes work, but it fixes this specific issue for now. Fixes #6766.
2021-04-24LibJS: Add VM::on_call_stack_emptied callbackLinus Groh
Instead of having to run queued promise jobs in LibWeb in various places, this allows us to consolidate that into one function - this is very close to how the spec describes it as well ("at some future point in time, when there is no running execution context and the execution context stack is empty, the implementation must [...]"). Eventually this will also be used to log unhandled exceptions, and possibly other actions that require JS execution to have ended.
2021-04-22Everything: Move to SPDX license identifiers in all files.Brian Gianforcaro
SPDX License Identifiers are a more compact / standardized way of representing file license information. See: https://spdx.dev/resources/use/#identifiers This was done with the `ambr` search and replace tool. ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
2021-04-13LibJS: Replace two more uses of unwind(ScopeType::None) with stop_unwind()Linus Groh
Same thing, but a lot more clear.
2021-04-02LibJS: Add initial support for PromisesLinus Groh
Almost a year after first working on this, it's finally done: an implementation of Promises for LibJS! :^) The core functionality is working and closely following the spec [1]. I mostly took the pseudo code and transformed it into C++ - if you read and understand it, you will know how the spec implements Promises; and if you read the spec first, the code will look very familiar. Implemented functions are: - Promise() constructor - Promise.prototype.then() - Promise.prototype.catch() - Promise.prototype.finally() - Promise.resolve() - Promise.reject() For the tests I added a new function to test-js's global object, runQueuedPromiseJobs(), which calls vm.run_queued_promise_jobs(). By design, queued jobs normally only run after the script was fully executed, making it improssible to test handlers in individual test() calls by default [2]. Subsequent commits include integrations into LibWeb and js(1) - pretty-printing, running queued promise jobs when necessary. This has an unusual amount of dbgln() statements, all hidden behind the PROMISE_DEBUG flag - I'm leaving them in for now as they've been very useful while debugging this, things can get quite complex with so many asynchronously executed functions. I've not extensively explored use of these APIs for promise-based functionality in LibWeb (fetch(), Notification.requestPermission() etc.), but we'll get there in due time. [1]: https://tc39.es/ecma262/#sec-promise-objects [2]: https://tc39.es/ecma262/#sec-jobs-and-job-queues
2021-03-21LibJS: Don't track executing AST nodes in a VectorAndreas Kling
Instead just link together the InterpreterNodeScopes in a linked list. This was surprisingly hot on CanvasCycle.
2021-03-21LibJS: Move AST node stack from VM to InterpreterAndreas Kling
2021-03-16LibJS: Implement non-value-producing statements properlyLinus Groh
For various statements the spec states: Return NormalCompletion(empty). In those cases we have been returning undefined so far, which is incorrect. In other cases it states: Return Completion(UpdateEmpty(stmtCompletion, undefined)). Which essentially means a statement is evaluated and its completion value returned if non-empty, and undefined otherwise. While not actually noticeable in normal scripts as the VM's "last value" can't be accessed from JS code directly (with the exception of eval(), see below), it provided an inconsistent experience in the REPL: > if (true) 42; 42 > if (true) { 42; } undefined This also fixes the case where eval() would return undefined if the last executed statement is not a value-producing one: eval("1;;;;;") eval("1;{}") eval("1;var a;") As a consequence of the changes outlined above, these now all correctly return 1. See https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation, "NOTE 2". Fixes #3609.
2021-03-16LibJS: Make Interpreter::run() a void functionLinus Groh
With one small exception, this is how we've been using this API already, and it makes sense: a Program is just a ScopeNode with any number of statements, which are executed one by one. There's no explicit return value at the end, only a completion value of the last value-producing statement, which we then access using VM::last_value() if needed (e.g. in the REPL).
2021-03-01LibJS: Keep track of current AST node inside the call stackJean-Baptiste Boric
2021-02-23Everywhere: Rename ASSERT => VERIFYAndreas Kling
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED) Since all of these checks are done in release builds as well, let's rename them to VERIFY to prevent confusion, as everyone is used to assertions being compiled out in release. We can introduce a new ASSERT macro that is specifically for debug checks, but I'm doing this wholesale conversion first since we've accumulated thousands of these already, and it's not immediately obvious which ones are suitable for ASSERT.
2021-02-10LibJS: Remove a whole bunch of unnecessary #includesAndreas Kling
2021-01-12Libraries: Move to Userland/Libraries/Andreas Kling