This Pull Request fixes a small error in the documentation of `Context::register_global_function()` method, and a few clippy errors we were getting in the tests.
This is an experiment that tries to migrate the codebase from eager `Error` objects to lazy ones.
In short words, this redefines `JsResult = Result<JsValue, JsError>`, where `JsError` is a brand new type that stores only the essential part of an error type, and only transforms those errors to `JsObject`s on demand (when having to pass them as arguments to functions or store them inside async/generators).
This change is pretty big, because it unblocks a LOT of code from having to take a `&mut Context` on each call. It also paves the road for possibly making `JsError` a proper variant of `JsValue`, which can be a pretty big optimization for try/catch.
A downside of this is that it exposes some brand new error types to our public API. However, we can now implement `Error` on `JsError`, making our `JsResult` type a bit more inline with Rust's best practices.
~Will mark this as draft, since it's missing some documentation and a lot of examples, but~ it's pretty much feature complete. As always, any comments about the design are very much appreciated!
Note: Since there are a lot of changes which are essentially just rewriting `context.throw` to `JsNativeError::%type%`, I'll leave an "index" of the most important changes here:
- [boa_engine/src/error.rs](https://github.com/boa-dev/boa/pull/2283/files#diff-f15f2715655440626eefda5c46193d29856f4949ad37380c129a8debc6b82f26)
- [boa_engine/src/builtins/error/mod.rs](https://github.com/boa-dev/boa/pull/2283/files#diff-3eb1e4b4b5c7210eb98192a5277f5a239148423c6b970c4ae05d1b267f8f1084)
- [boa_tester/src/exec/mod.rs](https://github.com/boa-dev/boa/pull/2283/files#diff-fc3d7ad7b5e64574258c9febbe56171f3309b74e0c8da35238a76002f3ee34d9)
This Pull Request fixes#1371. And yeah, the number of file changes is real...
It changes the following:
- Split the ast `Node` into `Statement` and `Expression`.
- Rewrite the parser and bytecompiler to conform to this change.
- Refactor some ast nodes into reusable structures.
- Rewrite `contains_arguments` and `contains` to ease the transition into a future ast visitor.
List of things that were apparently fixed by this refactor?:
- Implement read-assign operation for private accessors (e.g. `this.#field ||= 5`).
- `var await` declaration now allowed outside `async` functions and inside functions nested in async functions.
- Reject redeclarations of variables declared in the init list of a for loop.
Still missing some documentation adjustments, will try to do it ASAP.
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel necessary.
--->
This Pull Request is related to #2098.
It changes the following:
- Implements `JsRegExp`
- Adds a brief `JsRegExp` example under `boa_examples`
I think it's time to address the elephant in the room.
This Pull Request will (hopefully!) solve part of #736.
This is a complete rewrite of `JsString`, but instead of storing `u8` bytes it stores `u16` words. The `encode!` macro (renamed to `utf16!` for simplicity) from the `const-utf16` crate allows us to create UTF-16 encoded arrays at compilation time. `JsString` implements `Deref<Target=[u16]>` to unlock the slice methods and possibly make some manipulations easier. However, we would need to create our own library of utilities for `JsString`.
This Pull Request closes#2080.
It moves all implementors of the `JsObjectType` trait into their own `js_object` module.
This should simplify documentation and by doing a `pub(crate)` export in `object` little to no imports within the crate need to be changed, simplifying the usage of this module within the boa_engine crate.
Documentation within the `object` module has been updated to reflect this change and in a way that it is shown on the home page of the documentation.
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel necessary.
--->
This Pull Request is related to #2098 .
It changes the following:
- Implements a wrapper for `DataView`
- Adds an example of `JsDataView` to the `JsArrayBuffer` example file under boa_examples
Co-authored-by: jedel1043 <jedel0124@gmail.com>
This Pull Request switches our codebase to the brand new [workspace inherited keys](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table), which allows us to define common package options that are usable within each crate's Cargo.toml file.
It also allows to share dependency versions between crates, but I defined only shared versions for our workspace members. It would be a good follow-up to lift all the shared dependencies between crates into the global Cargo.toml.
This Pull Request fixes/closes #1987.
It changes the following:
- Add a prototype to the global object.
- Implement `__get_prototype_of__`, `__set_prototype_of__`, `__get_own_property__`, and `__own_property_keys__` for the global object
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel neccesary.
--->
This Pull Request fixes [x-after-break-to-label](dc1dc28aa4/test/language/block-scope/leave/x-after-break-to-label.js)
### Example
```js
{
let x = 2;
L: {
let x = 3;
console.log(x === 3);
break L;
console.log(false);
}
console.log(x === 2);
}
```
### Previously
> Uncaught "SyntaxError": "Cannot use the undeclared label 'L'"
### Now
> true <br> true
### What did I do
1. add `lable` to `Node::Block`
2. push labelled-block's `control info` to `jump_info` list
3. pop it before `Opcode::PopEnvironment`
Co-authored-by: creampnx_x <2270436024@qq.com>
This Pull Request closes#894.
It changes the following:
- Adds the `encodeURI()`, `decodeURI()`, `encodeURIComponent()` and `decodeURIComponent()` functions
- Passes all the tests except for those depending on #1987 or on the comment below.
Things to discuss:
- I'm unable to find in the spec information regarding the only failing tests, which relate to [this](f1870753fa/test/built-ins/encodeURI/S15.1.3.3_A1.1_T2.js):
> If string.charAt(k) in [0xDC00 - 0xDFFF], throw URIError
Let me know your thoughts :)
Co-authored-by: raskad <32105367+raskad@users.noreply.github.com>
This Pull Request changes the following:
- Implement [Async-from-Sync Iterator Objects](https://tc39.es/ecma262/#sec-async-from-sync-iterator-objects)
- Give the proper `async` hint to `GetIterator` when executing a delegate yield expression in an async generator function
This Pull Request fixes/closes #2148.
It changes the following:
- When we start an assignment expression, the `/` token must be a regular expression literal. The division can only occur between expressions after the assignment operator.
- Added tests for the new behaviour, taken from #2177
This overrides #2177
This Pull Request fixes a potential overflow when trying to convert a `u64` into a `usize` and then trying to create a byte data block.
Related to this, we seem to be using a `u64` and `i64` as a general approach for an "integer", but ECMAScript doesn't have bounds for them, so they could be as big as infinite. Should we use `u128` and `i128` to have a bigger range?
This would add a performance penalty, though, and we don't have 128-bit platforms usually, so the benefit would probably be minimal, at least when trying to allocate.
This PR fixes a case where a forward slash is located in a regex class: `let regex = /[/]/;`. In this case, the forward slash should not close the regex literal.
This fixes `test/built-ins/RegExp/regexp-class-chars.js`
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel neccesary.
--->
This Pull Request fixes: 79e3bc5176/test/language/computed-property-names/object/method/super.js
This PR solves the bug of using the `super` keyword in the method attribute of object. When the environment is `None`, the `vm` gets the top element of `vm.stack` as `this`, such as:
```js
var a = {
f() {
return super.m();
}
};
var b = {
m() {
retrun "super";
}
};
Object.setPrototypeOf(a, b);
a.f(); // the top of stack is `a`
let f = a.f;
f(); // the top of stack is `global_this`, so `super` cannot be used
```
### Can be improved
What I think is that when I use `object.method()`, the engine should bind `this_object` to the `environment`, instead of using `vm.stack.last()...`.
### TODOS
1. `super` need to look for properties all the way to the end.
Co-authored-by: creampnx_x <2270436024@qq.com>
This PR fixes#2275
There are keywords that are allowed as identifiers.
https://tc39.es/ecma262/#sec-keywords-and-reserved-words
> Those that are always allowed as identifiers, but also appear as keywords within certain syntactic productions, at places where Identifier is not allowed: as, async, from, get, meta, of, set, and target.
This PR adds test cases for them, and fixes some cases such as
`class A { set(a, b) { } }`
`function of() { }`
`let obj = {async: true}`
`async()`
There can be a line terminator in the middle of variable declaration statement. For example,
```js
var a
, b;
```
In this case, we should not insert semicolon automatically.
This fixes:
- test262/test/language/asi/S7.9_A7_T8.js
- test262/test/language/asi/S7.9_A7_T9.js
Skip `to_string` for integer type primitives in `to_property_key`. It's unnecessary to convert the integer value to string and convert back to `Index(u32)` type.
In this example code, it improves around 10% of runtime.
```js
let arr = [1,2,3,4,5];
for (let i = 0; i < 10000000; i++) {
arr[0] = 123;
}
```
Before: 6.24s
After: 5.38s
This Pull Request changes the following:
- Create the `%Array.prototype.values%` function object once and use it in both the `Array` prototype and as the `@@iterator` value of `arguments` objects.
This fixes a test where `arguments[Symbol.iterator]` and `[][Symbol.iterator]` would not be equal.
Currently we only spread spread-expressions if they are the last argument in the function call. With this fix all arguments are spread if needed. The downside is that an array object is allocated to store all arguments if the arguments contain a spread-expression. But with dense indexed properties inplemented in #2167 this should be reasonably fast.
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel neccesary.
--->
This Pull Request fixes#1615.
It changes the following:
- Removes the `Trace` implementation from types that don't need it (except for `JsSymbol` and `JsString`, which are needed elsewere).
- Uses `#[unsafe_ignore_trace]` in places where we need to implement `Trace` for part of a structure.
- Implements a custom `Trace` in enums where deriving it is not possible, since `#[unsafe_ignore_trace]` doesn't work for enums.
Co-authored-by: raskad <32105367+raskad@users.noreply.github.com>
This Pull Request changes the following:
- Implement parsing/cover-conversion for field accessor member expressions in [DestructuringAssignmentTarget](https://tc39.es/ecma262/#prod-DestructuringAssignmentTarget).
- Modify the `CopyDataProperties` opcode to account for excluded keys that are only known at runtime.
This Pull Request fixes#1560.
It changes the following:
- Implement `AsyncGeneratorFunction` builtin object.
- Implement `AsyncGenerator` builtin object.
- Implement async generator execution.
- Add some parse errors for async generators.
The `AsyncGenerator.prototype.return()` method currently does not work correctly with `finally` blocks, but I think we should merge this first to not increase the complexity of the pr too much.
Currently async generator class methods are not being parsed correctly. In comparison to the current main branch this only fixes a few tests, but after #2200 is merged, it should be aroud 1000 additional passing tests.
This PR fixes the length/index types from `usize` to `u64`, because in JavaScript the length can be from `0` to `2^53 - 1` it cannot be represented in a `usize`. On `64-bit` architectures this is fine because it is already a unsigned 64bit number and these changes essentially do nothing. But on 32bit architectures this was causing the length to be truncated giving an unexpected result.
fixes/closes #2182
It changes the following:
- Make length a `u64` to be able to represent all possible length values
- Change `JsValue::to_length()` t return `u64`
- Change `JsValue::to_index()` t return `u64`
This Pull Request changes the following:
- Modify `CreateDynamicFunction` to work with generator functions.
- Add the name `anonymus` to functions created via `CreateDynamicFunction` to comply with the spec.
- Fix a bug in the `Yield` parser where the parser would expect a token when no token is a legal case.
- Change the `Yield::new` function to require less turbofishes.
Previously we parsed arrow functions without the relevant cover grammar `CoverParenthesizedExpressionAndArrowParameterList`. This leads to either arrow functions or parenthesized expressions not being parsed correctly. Implementing this is a bit tricky, as the cover grammar is being parsed in `PrimaryExpression` while arrow functions are parsed in `AssignmentExpression`. This means that we have to return the covered parameter list that was parsed via `CoverParenthesizedExpressionAndArrowParameterList` in `PrimaryExpression` to `AssignmentExpression`. Fortunately this works pretty good and now the full arrow function test suite, with the exception of a few tests that require other features, passes.
This Pull Request changes the following:
- Implement `CoverParenthesizedExpressionAndArrowParameterList` parsing.
- Implement `CoverInitializedName` parsing in object literals.
- Fix a bug where an environment would be wrongly removed from the environment stack when an expression in default function parameters throws.
- Add more valid cases where on object literal can be converted to an object declaration pattern.
- Implement `Expression` parsing manually to avoid some cases where the parser would prematurely throw an error.
- Implement parsing of arrow functions via `CoverParenthesizedExpressionAndArrowParameterList`.
- Remove unneeded `AllowIn` flag on array and object declaration pattern parsers.
- Fix an of-by-one bug in the trace output.
This PR adds the `ArrayBuffer` rust wrapper. It also provides a capability to construct a `JsArrayBuffer` from a user defined blob of data ( `Vec<u8>` ) and it is not cloned, it is directly used as the internal buffer.
This allows us to replace the inifficent `Vec<u8>` to `JsArray` then to `TypedArray` (in typed arrays `from_iter`), with a `JsArrayBuffer` created from user data to `TypedArray`. With this `Vec<u8>` to `JsTypedArray` should be fully fixed as discussed in #2058.
This PR adds a safe wrapper around JavaScript `JsSet` from `builtins::set`, and is being tracked at #2098.
Implements following methods
- [x] `Set.prototype.size`
- [x] `Set.prototype.add(value)`
- [x] `Set.prototype.clear()`
- [x] `Set.prototype.delete(value)`
- [x] `Set.prototype.has(value)`
- [x] `Set.prototype.forEach(callbackFn[, thisArg])`
Implement wrapper for `builtins::set_iterator`, to be used by following.
- [x] `Set.prototype.values()`
- [x] `Set.prototype.keys()`
- [x] `Set.prototype.entries()`
*Note: Are there any other functions that should be added?
Also adds `set_create()` and made `get_size()` public in `builtins::set`.
This PR implements an optimization done by V8 and spidermonkey. Which stores indexed properties in two class storage methods dense and sparse. The dense method stores the property in a contiguous array ( `Vec<T>` ) where the index is the property key. This storage method is the default. While on the other hand we have sparse storage method which stores them in a hash map with key `u32` (like we currently do). This storage method is a backup and is slower to access because we have to do a hash map lookup, instead of an array access.
In the dense array we can store only data descriptors that have a value field and are `writable`, `configurable` and `enumerable` (which by default array elements are). Since all the fields of the property descriptor are the same except value field, we can omit them an just store the `JsValue`s in `Vec<JsValue>` this decreases the memory consumption and because it is smaller we are less likely to have cache misses.
There are cases where we have to convert from dense to sparse (the slow case):
- If we insert index elements in a non-incremental way, like `array[1000] = 1000` (inserting an element to an index that is already occupied only replaces it does not make it sparse)
- If we delete from the middle of the array (making a hole), like `delete array[10]` (only converts if there is actualy an element there, so calling delete on a non-existent index property will do nothing)
Once it becomes sparse is *stays* sparse there is no way to convert it again. (the computation needed to check whether it can be converted outweighs the benefits of this optimization)
I did some local benchmarks and on array creation/pop and push there is ~45% speed up and the impact _should_ be bigger the more elements we have. For example the code below on `main` takes `~21.5s` while with this optimization is `~3.5s` (both on release build).
```js
let array = [];
for (let i = 0; i < 50000; ++i) {
array[i] = i;
}
```
In addition I also made `Array::create_array_from_list` do a direct setting of the properties (small deviation from spec but it should have the same behaviour), with this #2058 should be fixed, conversion from `Vec` to `JsArray`, not `JsTypedArray` for that I will work on next :)
<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel neccessary.
--->
This Pull Request related to JsMap for #2098.
Any feedback on implementing JsMapIterator would be welcome. I wasn't entirely sure if it was the right approach, but as I worked on the example file, it felt like something at least similar would be needed to use Map's .entries(), .keys(), and .values() methods.
It changes the following:
- Implements JsMap Wrapper
- Implements JsMapIterator Wrapper
- Creates JsMap example in boa_examples
This storage method should be more cache friendly since we store in contiguous memory, besides that it should make #2157 a bit easier. Will work on that next after this gets merged :)
It changes the following:
- Remove the unneeded `prev` field in `CallFrame`
- Preallocate some space for future calls (16 slots)
This Pull Request changes the following:
- Implement `AsyncFunction` builtin object.
- Add `Async` as a function object data type.
- Implement `async function` and `await` compilation and execution.
- Parse `await` in more positions.
This Pull Request changes the following:
- Fix `Promise.then` length to 2.
- Fix `all`, `allSettled` and `any` element lists to actually be shared between closures.
- Fix `allSettled` reject element function to call resolve instead of reject.
The remaining failing tests for `Promise` fail because of some errors in the arrow function parsing.
This Pull Request changes the following:
- Fix the `this` value that is passend to function calls to be `undefined` if the function is not a property reference
- Add special handling for setting the `this` value for function calls where the function is a private property reference or a super property reference
So, @raskad and myself had a short discussion about the state of #736, and we came to the conclusion that it would be a good time to implement our own string interner; partly because the `string-interner` crate is a bit unmaintained (as shown by https://github.com/Robbepop/string-interner/pull/42 and https://github.com/Robbepop/string-interner/pull/47), and partly because it would be hard to experiment with custom optimizations for UTF-16 strings. I still want to thank @Robbepop for the original implementation though, because some parts of this design have been shamelessly stolen from it 😅.
Having said that, this PR is a complete reimplementation of the interner, but with some modifications to (hopefully!) make it a bit easier to experiment with UTF-16 strings, apply optimizations, and whatnot :)
This Pull Request changes the following:
- Implement `super` expression parsing / execution.
- Implement early errors for `super` expressions.
- Refactor / add internal slot representation for environment and function objects.