mirror of https://github.com/boa-dev/boa.git
Tree:
6443aa86ec
add-vhs-ci
benchmarks
control-flow-graph
expect-lints
feature/node_span
feature/snapshot
features
gh-readonly-queue/main/pr-2877-b0ddf5eed00a53281d67fc7d846233fc0d99ce9c
gh-readonly-queue/main/pr-3144-8e48cec73fae708420b9af88813d4870243c491a
main
nan-boxing
optimization/static-shapes
real_conformance
reduce-environment-allocations
refactor/interner
refactor/register-vm
releases/0.17
releases/0.19
semver_checks
tco
utility-crate
wasm-debugger
nightly
v0.10
v0.11
v0.12
v0.13
v0.14
v0.15
v0.16
v0.17
v0.17.1
v0.17.2
v0.17.3
v0.18
v0.19
v0.19.1
v0.2.0
v0.2.1
v0.3.0
v0.4.0
v0.5.0
v0.5.1
v0.6.0
v0.7.0
v0.8.0
v0.9.0
${ noResults }
318 Commits (6443aa86ec278ff05d30da7c9ea96e5a6c836a32)
Author | SHA1 | Message | Date |
---|---|---|---|
Halid Odat | 7248ed1005 |
Make `StringToNumber` spec compliant (#1881)
This PR enables `StringToNumber()` to parse binary, octal and hexadecimal numbers. |
3 years ago |
Halid Odat | 3c59905a1b |
`%NativeError%.[[prototype]]` should be `Error` constructor (#1883)
Before the `%NativeError%` objects (like `TypeError`, `ReferenceError`, etc) `[[prototype]]` field was set to `Function.prototype` but this is wrong it should be the `Error` constructor object itself. This makes the `%NativeError%`s 100% spec compliant :) (except `AggregateError` because its not implemented) |
3 years ago |
raskad | 408e49e460 |
Cleanup vm stack on function return (#1880)
This cleans up the vm stack on a function return. This is needed because when errors are thrown, there may be still values on the stack that cannot be cleaned up via regular control flow. The change should have little performance impact, because the `Vec::truncate` function does not alter the capacity of the vector. |
3 years ago |
Halid Odat | 6e3f93e632 |
Fix `Number.prototype.toString` when passing `undefined` as radix (#1877)
This PR fixes the bug when passing `undefined` as radix in `Number.prototype.toString()` which was throwing a range error, instead of setting the radix to `10` [spec](https://tc39.es/ecma262/#sec-number.prototype.tostring): > **Note** > > The optional radix should be an [integral Number](https://tc39.es/ecma262/#integral-number) value in the inclusive range 2𝔽 to 36𝔽. If radix is undefined then 10𝔽 is used as the value of radix. |
3 years ago |
Halid Odat | 3fe7d09096 |
Make `Error` and `%NativeError%` spec compliant (#1879)
This PR makes `Error` and `%NativeError%` spec compliant. It changes the following: - Adds cause argument object. - Makes `message` non-enumerable. |
3 years ago |
Halid Odat | 4292c193fa |
Implement `Object.prototype.toLocaleString()` (#1875)
It changes the following: - Implement `Object.prototype.toLocaleString()` |
3 years ago |
Halid Odat | 73bcd42640 |
Make `Object.getOwnPropertyDescriptors` spec compliant (#1876)
It changes the following: - Fix `Object.getOwnPropertyDescriptors()` to comply to spec |
3 years ago |
Iban Eguia | ec78e184f3 |
Removed reference counted pointers from `JsValue` variants (#1866)
This Pull Request fixes/closes #1864. It changes the following: - Removed `JsBigInt` from `Const` nodes, using a boxed `BigInt` instead. - Modifies the `JsObject` variant so that it has a similar structure to other variants, where the internal structure is private. The size of `JsValue` stays in 2 64-bit words (in a 64-bit system at least), and the size of `Const` also stays the same. I have noticed that we clone tokens too much in the parser, so I was thinking that we should implement a by-value getter for `kind()`. Something like `kind_unwrap()`. |
3 years ago |
Iban Eguia | 1887b6aebb |
Removing the panic in favour of an error result (#1874)
This Pull Request is related to #1873. It changes the following: - Removes the panic in case a label is not found. I think this should be an early syntax error, but at least we shouldn't panic while we fix the issue with the labels. I think we should solve the issue with labeled statements for 0.15. |
3 years ago |
Halid Odat | ada4ca895f |
Feature arrays with empty elements (#1870)
This PR adds support for arrays with empty elements e.g. `["", false, , , ]`. Before we were filling the empty places with `undefined`, but this is wrong according to [spec](https://tc39.es/ecma262/#sec-runtime-semantics-arrayaccumulation) there shouldn't be undefined with a index at that place, instead only `length` is incremented. So `[,,,].length == 3` and operations like `[,,,,].indexOf(undefined) == -1`, `[,,,,].lastIndexOf(undefined) == -1` etc. |
3 years ago |
Halid Odat | 6b2ca30946 |
Fix equality between objects and `undefined` or `null` (#1872)
This PR fixes equality between object and `null` or `undefined` (like `[] == null`), which was failing the test262 harness test [`compare-array-symbol.js`](
|
3 years ago |
raskad | 60e2294706 |
Implement generator execution (#1790)
This Pull Request fixes/closes #1559. It changes the following: - Implement GeneratorFunction Objects - Implement Generator Objects - Implement generator execution in vm - Create `FormalParameterList` to remove duplicate checks on function parameters - Refactor `MethodDefinition` on object literals |
3 years ago |
Halid Odat | b5678f0b0c |
Removing internal deprecated functions (#1854)
This Pull Request is related to #577 . It changes the following: - Remove `JsValue::set_field` - Remove `JsValue::set_property` - Remove almost all uses of `JsValue::get_field` - Use `.get_v()` instead of `get_field` according to spec in `serialize_json_property` - Remove `Array::new_array()` - Remove `Array::add_to_array_object()` |
3 years ago |
João Borges | 6093a66899 |
Refactorings for Rust 1.59 (#1867)
This Pull Request fixes new lint errors and warnings introduced in rust 1.59 Each commit describes its changse. Co-authored-by: raskad <32105367+raskad@users.noreply.github.com> |
3 years ago |
Halid Odat | 9dda8d3eae |
Toggleable `JsValue` internals displaying (#1865)
This PR makes `JsValue` (object) only display owned properties, cleans up object printing. This can be toggled with `value.display().internals(true)` `>> ({x: 1, y: ""})` _Before:_ <details> <pre> { x: 1, y: "", __proto__: { hasOwnProperty: { length: 1, name: "hasOwnProperty", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, propertyIsEnumerable: { length: 1, name: "propertyIsEnumerable", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, toString: { length: 0, name: "toString", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, valueOf: { length: 0, name: "valueOf", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, isPrototypeOf: { length: 1, name: "isPrototypeOf", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, constructor: { create: { length: 2, name: "create", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, setPrototypeOf: { length: 2, name: "setPrototypeOf", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, getPrototypeOf: { length: 1, name: "getPrototypeOf", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, defineProperty: { length: 3, name: "defineProperty", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, defineProperties: { length: 2, name: "defineProperties", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, assign: { length: 2, name: "assign", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, is: { length: 2, name: "is", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, keys: { length: 1, name: "keys", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, values: { length: 1, name: "values", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, entries: { length: 1, name: "entries", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, seal: { length: 1, name: "seal", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, isSealed: { length: 1, name: "isSealed", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, freeze: { length: 1, name: "freeze", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, isFrozen: { length: 1, name: "isFrozen", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, preventExtensions: { length: 1, name: "preventExtensions", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, isExtensible: { length: 1, name: "isExtensible", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, getOwnPropertyDescriptor: { length: 2, name: "getOwnPropertyDescriptor", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, getOwnPropertyDescriptors: { length: 1, name: "getOwnPropertyDescriptors", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, getOwnPropertyNames: { length: 1, name: "getOwnPropertyNames", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, getOwnPropertySymbols: { length: 1, name: "getOwnPropertySymbols", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, hasOwn: { length: 2, name: "hasOwn", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, fromEntries: { length: 1, name: "fromEntries", __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, length: 1, name: "Object", prototype: [Cycle], __proto__: { name: "", length: 0, apply: { length: 1, name: "apply", __proto__: [Cycle] }, bind: { length: 1, name: "bind", __proto__: [Cycle] }, call: { length: 1, name: "call", __proto__: [Cycle] }, toString: { length: 0, name: "toString", __proto__: [Cycle] }, constructor: { length: 1, name: "Function", prototype: [Cycle], __proto__: [Cycle] }, Symbol(Symbol.hasInstance): { length: 1, name: "[Symbol.iterator]", __proto__: [Cycle] }, __proto__: [Cycle] } }, __proto__: null } } </pre> </details> _After:_ ```text { x: 1, y: "" } ``` |
3 years ago |
Addison Crump | 2c19c6a4b5 |
Correct pop_on_return behaviour (#1853)
This PR changes the following: - Updates the value of `pop_on_return` after a catch as to prevent VM stack corruption - Adds two test cases which demonstrate the issue and demonstrate that it has been fixed I am unsure if it is possible to abuse the patch provided; one would need to catch from within an array initialisation without calling into another frame (e.g., with a lambda), which I don't think is possible. |
3 years ago |
Iban Eguia | 8c92a8fa25 |
Added conversions from and to serde_json's Value type (#1851)
This Pull Request closes #1693. It changes the following: - It adds a fallible conversion from `serde_json::Value` to `JsValue`, which requires a context. - It adds a fallible conversion from `JsValue` to `serde_json::Value`, which requires a context. - Added examples to the documentation of both methods. - Removed some duplicate and non-needed code that I found while doing this. Co-authored-by: RageKnify <RageKnify@gmail.com> |
3 years ago |
Iban Eguia |
4d2772d6a0
|
Rename "Boa" to boa_engine, moved GC and profiler to their crates (#1844)
* Separated GC and Profiler * Fixed prettierignore * Removed re-exports, fixed benchmarks, added some caches * Removed empty line * Update boa_engine/Cargo.toml Co-authored-by: raskad <32105367+raskad@users.noreply.github.com> * Fixed the profiler * Removed empty file Co-authored-by: raskad <32105367+raskad@users.noreply.github.com> |
3 years ago |