summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
AgeCommit message (Collapse)Author
2021-04-04WindowServer+LibGUI: Rename WindowType::MenuApplet => AppletAndreas Kling
2021-04-03LibJS: Log any exception, not just the ones with a JS::Error valueLinus Groh
This was super confusing as we would check if the exception's value is a JS::Error and not log it otherwise, even with m_should_log_exceptions set. As a result, things like DOM exceptions were invisible to us with execution just silently stopping, for example.
2021-04-03LibJS: Keep RegExp.exec() results in correct orderLinus Groh
By using regex::AllFlags::SkipTrimEmptyMatches we get a null string for unmatched capture groups, which we then turn into an undefined entry in the result array instead of putting all matches first and appending undefined for the remaining number of capture groups - e.g. for /foo(ba((r)|(z)))/.exec("foobaz") we now return ["foobaz", "baz", "z", undefined, "z"] and not [ ["foobaz", "baz", "z", "z", undefined] Fixes part of #6042. Also happens to fix selecting an element by ID using jQuery's $("#foo").
2021-04-03LibJS: ArrayBuffer.prototype.sliceJamie Mansfield
Implements the aforementioned native Javascript function, following the specification's [1] implementation. [1] https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
2021-04-02LibJS: Use empty value for Reference unresolvable state, not undefinedLinus Groh
This fixes an issue where `undefined.foo = "bar"` would throw a ReferenceError instead of a TypeError as undefined was also used for truly unresolvable references (e.g. `foo() = "bar"`). I also made the various error messages here a bit nicer, just "primitive value" is not very helpful.
2021-04-02LibJS: Move 'typeof' string functionality from AST to ValueLinus Groh
We should be able to get the 'typeof' string for any value directly, so this is now a standalone Value::typeof() method instead of being part of UnaryExpression::execute().
2021-04-02LibJS: Implement most of String.prototype.replaceTimothy Flynn
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-30LibJS: Fix two issues with array (length > INT32_MAX)Andreas Kling
1. Allow Value(size_t) and use it for array length properties. If an array length can't fit in an Int32 value, we shouldn't go out of or way to force it into one. Instead, for values above INT32_MAX, we simply store them as Double values. 2. Switch to generic indexed property storage for large arrays. Previously we would always allocate array storage eagerly when the length property was set. This meant that "a.length = 0x80000000" would trivially DOS the engine on 32-bit since we don't have that much VM. We now switch to generic storage when changing the length moves us over the 4M entry mark. Fixes #5986.
2021-03-26LibJS: VERIFY(!this_value.is_empty()) in VM::call_internal()Linus Groh
Just a sanity check, this must never happen. Manual invocations of call() e.g. in LibWeb bindings must pass js_undefined() if no specific this value is desired, which OrdinaryCallBindThis will then use as-is or turn into the global this value in non-strict mode.
2021-03-25LibJS: Use Utf8View for string prefix checksIdan Horowitz
This commit replaces the usage of String::starts_with with Utf8View::starts_with, which first decodes the utf8 encoded string, and as such can take things like overlong encoded sequences into account (which could otherwise cause the prefix check to be inconsistent with the following code points check).
2021-03-23LibJS: Don't static_cast<double>() various Date getter valuesLinus Groh
Since we have Value::Type::Int32 now, let's use the Value(i32) constructor here directly by not casting these i32 values to doubles. The Value(double) would also figure out that these can be stored as integers, but needs to do extra work which is not needed here. :^)
2021-03-23LibJS: Remove as_size_t()Linus Groh
Just like to_size_t() - which was already removed in f369229 - this is non-standard, use to_length() instead. One remaining use was removed, and I'm glad it's gone. :^)
2021-03-23LibJS: Simplify positive/negative zero checksOleg Sikorskiy
Because both zeroes have unique and distinct bit representations, we can bit_cast value to u64 and check if it's one of them.
2021-03-22LibJS Date: Added "Invalid Date".Petróczi Zoltán
Setting an invalid value on a Date object now makes it invalid. Setting it again but with correct values makes it valid again.
2021-03-22LibJS Date: Added toUTCString()Petróczi Zoltán
toGMTString() is deprecated but is kept for compatibility's sake, but because HTTP Dates are always expressed in GMT, it should be safe to call toUTCString() in toGMTString().
2021-03-22LibJS: *Actually* check for negative zero in JS::Value(double)Andreas Kling
As @nico pointed out, 0.0 == -0.0 in C++, even though they are not bitwise identical. Use the same trick as Value::is_negative_zero() to really check for it. This allows JS::Value(0.0) to correctly become an Int32-backed 0 value.
2021-03-21LibJS: Don't try to store negative zero as an Int32 JS::ValueAndreas Kling
2021-03-21LibJS: Flatten Value::to_numeric()Andreas Kling
The basic idea here is to inline to_primitive() to get rid of the function call overhead.
2021-03-21LibJS: Add fast path for add() with two numeric JS::ValuesAndreas Kling
2021-03-21LibJS: Only call GlobalObject::vm() once in add()Andreas Kling
2021-03-21LibJS: Split Value::Type::Number into Int32 and DoubleAndreas Kling
We now store 32-bit integers as 32-bit integers directly which avoids having to convert them from doubles when they're only used as 32-bit integers anyway. :^) This patch feels a bit incomplete and there's a lot of opportunities to take advantage of this information. We'll have to find and exploit them eventually.
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: Avoid unnecessary FlyString(String) churn in Reference ctorsAndreas Kling
2021-03-21LibJS: Always inline Cell::vm() and Cell::heap()Andreas Kling
2021-03-21LibJS: Move AST node stack from VM to InterpreterAndreas Kling
2021-03-21LibJS: Don't punish large arrays with generic indexed property storageAndreas Kling
This patch rethinks the way indexed property storage works: Instead of having a cut-off point at 200 elements where we always move to generic property storage, we now allow arrays to stay in simple mode as long as we don't create a gap/hole larger than 200 elements. We also simplify generic storage to only have a hash map (for now) instead of juggling both a vector and a hash map. This is mostly fine since the vast majority of arrays get to stay simple now. This is a huge speedup on anything that uses basic JS arrays with more than 200 elements in them. :^)
2021-03-21LibJS: Append first sparse element to packed elements in take_first()Linus Groh
Otherwise we continuously lose the first sparse element (at index SPARSE_ARRAY_THRESHOLD) without noticing, as we overwrite all indices with the value at index+1. Fixes #5884.
2021-03-19LibJS: Add fast_is<T> for StringObject and GlobalObjectAndreas Kling
Both of these are quite hot in profiles.
2021-03-19LibJS: Add Date methods: setHours, setMinutes, setSeconds, setMillisecondstuqqu
2021-03-19LibJS: Support month and day arguments of Date.setFullYeartuqqu
2021-03-17LibJS: Always synthesize "arguments" object when there's a calleeAndreas Kling
Instead of counting the number of call frames on the VM stack, we now always fake the "arguments" object when the current call frame has a callee value. This fixes an issue with DOM event handlers in LibWeb not being able to access "arguments" since they were called without an outer frame.
2021-03-17LibJS: eval(x) should return x without evaluation if x is not a stringAndreas Kling
2021-03-17LibJS: Rename GlobalObject::initialize() => initialize_global_object()Andreas Kling
This function was shadowing Object::initialize() which cannot be called on global objects and has a different set of parameters.
2021-03-16LibJS: Replace global_object.global_object() with just global_objectLinus Groh
That's just silly...
2021-03-16LibJS: Only set receiver value fallback once in Object::get()Linus Groh
2021-03-16LibJS: Throw RangeError on BigInt exponentiation with negative exponentLinus Groh
https://tc39.es/ecma262/#sec-numeric-types-bigint-exponentiate
2021-03-16LibJS: Throw RangeError on BigInt division/modulo by zeroLinus Groh
https://tc39.es/ecma262/#sec-numeric-types-bigint-divide https://tc39.es/ecma262/#sec-numeric-types-bigint-remainder
2021-03-16LibJS: Don't apply arguments object hack to global execution contextLinus Groh
Checking for the existence of a call frame is not enough to check if we're in a function call, as the global execution context is a regular call frame as well. Found by OSS-Fuzz, where simply accessing "arguments" in the global scope would crash due to call_frame().callee being an empty value (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32115).
2021-03-15LibJS: Throw SyntaxError in eval() when parser has error(s)Linus Groh
2021-03-15LibJS: Make eval() return the last value from the executed statementAndreas Kling
This is kinda awkward but since the statement we're executing is actually a JS::Program, we have to get the result via VM::last_value().
2021-03-15LibJS: Add arguments.callee to our hack arguments objectAndreas Kling
arguments.callee refers to the currently executing function.
2021-03-15LibJS: Add Date.prototype.toGMTString()Andreas Kling
2021-03-15LibJS: Partial support for Date.prototype.setFullYear()Andreas Kling
2021-03-15LibJS: Add naive implementation of eval() :^)Andreas Kling
This parses and executes a code string in the caller's lexical scope.
2021-03-14LibJS: Change non-ScriptFunction source string to "[native code]"Linus Groh
https://tc39.es/ecma262/#sec-function.prototype.tostring - this is how the spec wants us to do it. :^) Also change the function name behaviour to only provide a name for NativeFunctions, which matches other engines - presumably to not expose Proxy objects, and to prevent "function bound foo() { [native code] }".
2021-03-14LibJS: Don't try to derive function source from ProxyObjectLinus Groh
There are three JS::Function types that are not ScriptFunction: NativeFunction, BoundFunction and ProxyObject. We were only checking for the first two when determining whether to reconstruct the function's source code, which was leading to a bad cast to ScriptFunction. Since only ScriptFunction has the [[SourceText]] internal slot, I simply swapped the branches here. Fixes #5775.
2021-03-14LibJS: Fix some issues in RegExp.prototype[@@match]Linus Groh
- We were not passing the to_string()'d argument to the exec function but the original argument - We were leaking an empty value in two cases, which almost certainly will crash something down the line - We were not checking for exceptions after to_string() and get(), which both may throw. If the getter is an accessor, it'll assert upon being called with the VM already storing an exception.
2021-03-14LibJS: Fix String.prototype.match() for non-string argumentLinus Groh
This is supposed to pass the to_string()'d argument to @@match, not the this value.
2021-03-14LibJS: Fix flags check in regexp_create()Linus Groh
We need to check for undefined, not empty - otherwise it will literally use "undefined" as the flags, which will fail (Invalid RegExp flag 'n').