├── github_deploy_key.enc
├── .travis.yml
├── package.json
├── deploy.sh
├── ADVANCED.md
├── README.md
└── spec.html
/github_deploy_key.enc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tc39/proposal-bigint/HEAD/github_deploy_key.enc
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: off
2 |
3 | language: node_js
4 |
5 | node_js:
6 | - "8"
7 |
8 | script:
9 | - bash ./deploy.sh
10 |
11 | env:
12 | global:
13 | - ENCRYPTION_LABEL: "a352b59e508f"
14 | - GH_USER_NAME: "littledan"
15 | - GH_USER_EMAIL: "littledan@igalia.com"
16 | - PRIVATE_KEY_FILE_NAME: "github_deploy_key.enc"
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "proposal-bigint",
4 | "version": "1.0.0",
5 | "description": "ECMAScript BigInt proposal",
6 | "repository": "tc39/proposal-bigint",
7 | "author": "ECMA TC39",
8 | "license": "SEE LICENSE IN https://tc39.github.io/ecma262/#sec-copyright-and-software-license",
9 | "homepage": "https://tc39.github.io/proposal-bigint/",
10 | "dependencies": {
11 | "ecmarkup": "^3.12.0"
12 | },
13 | "devDependencies": {
14 | "@alrra/travis-scripts": "^3.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ev
4 |
5 | # Enable SSH authentication
6 |
7 | ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
8 | ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
9 | ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
10 | ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
11 |
12 | if [[ $ENCRYPTED_KEY == "" ]]; then
13 | echo "Auto-deploy GitHub key missing; exiting without a build"
14 | exit 0
15 | fi
16 |
17 | $(npm bin)/set-up-ssh --key "$ENCRYPTED_KEY" \
18 | --iv "$ENCRYPTED_IV" \
19 | --path-encrypted-key "$PRIVATE_KEY_FILE_NAME"
20 |
21 | # Update the content from the `gh-pages` branch
22 |
23 | $(npm bin)/update-branch --commands "mkdir out && ecmarkup spec.html out/index.html" \
24 | --commit-message "Update gh-pages [skip ci]" \
25 | --directory "out" \
26 | --distribution-branch "gh-pages" \
27 | --source-branch "master"
28 |
29 |
--------------------------------------------------------------------------------
/ADVANCED.md:
--------------------------------------------------------------------------------
1 | # BigInt: Arbitrary precision integers in JavaScript
2 |
3 | Daniel Ehrenberg, Igalia. Stage 3
4 |
5 | Thanks for help and feedback on this effort from Brendan Eich, Waldemar Horwat, Jaro Sevcik, Benedikt Meurer, Michael Saboff, Adam Klein and others.
6 |
7 | ## API outline
8 |
9 | BigInts are a new numerical type supporting literals (`1234n`) and arithmetic with operator overloading (`1n + 2n` makes `3n`).
10 |
11 | ### Literals, operators and their meanings
12 |
13 | BigInts are, logically, arbitrary mathematic integers, with operator definitions which fall out naturally:
14 | - Binary `+`, `-`, `*` and `**` find their mathematical answer when applied to two BigInts
15 | - `/` and `%` round towards 0
16 | - Bitwise operations `|`, `&`, `<<`, `>>`, `^` operate logically
17 | - Negative numbers to be interpreted as infinite-length two's complement (see [discussion](https://github.com/tc39/proposal-bigint/issues/3)).
18 | - When applied to two BigInts, comparison operators `==`, `===`, `<`, `>`, `>=`, and `<=` perform a mathematical comparison
19 | - Missing operators
20 | - `>>>` is not supported, as all BigInts are signed; to get an unsigned shift, pass in a positive BigInt to `>>` ([discussion](https://github.com/tc39/proposal-bigint/issues/6))
21 | - Unary `+` is unsupported on BigInts due to asm.js requirements; details explained below
22 | - In a conditional, `if (0n)` executes the `else` branch.
23 |
24 | Literals for BigInts are similar to Number literals, but followed by `n`. They can be written with binary, octal or hexadecimal notation, e.g., `0x100n`. Legacy octal syntax (`0640`) is not allowed, only new-style (`0o064n`).
25 |
26 | The choice of `BigInt` comes from an attempt to preserve user intuition about the lack of compatibility of `BigInt` with things that are currently based on `Number`s. Because implicit coercions lead to TypeErrors, the guidance is that existing users of Numbers should stay with Numbers if it works for the application, and only large usages need to upgrade to `BigInt`. The name `BigInt` is hoped to emphasize this not-by-default usage. The suffix `n` is basically arbitrary.
27 |
28 | ### The BigInt constructor
29 |
30 | BigInts are a primitive type, and `BigInt` forms a constructor which can be used analogously to `Number`--to convert various types to BigInt values, as well as to be an object wrapper for BigInt values when used with property access.
31 |
32 | When called as a function, it is similar to the `Number` constructor: It converts strings, Numbers, etc into BigInts.
33 |
34 | #### Library functions
35 |
36 | - `BigInt.asUintN(width, BigInt)`: Wrap a BigInt between 0 and 2width-1
37 | - `BigInt.asIntN(width, BigInt)`: Wrap a BigInt between -2width-1 and 2width-1-1
38 |
39 | ### TypedArrays and DataViews
40 |
41 | BigInts give JavaScript the ability to accurately represent 64-bit signed and unsigned integers:
42 | - BigUint64Array and BigInt64Array, whose elements read from property access are BigInts
43 | - DataView.prototype.getBigInt64/getBigUint64, returning a BigInt
44 |
45 | Similarly, BigInts may be used by the WebAssembly FFI for 64-bit arguments and return values to functions.
46 |
47 | ### No implicit conversions or mixed operands
48 |
49 | A key design decision is to disallow mixed operations between BigInts and Numbers. The driving factor: Any implicit coercions would lose information.
50 |
51 | When adding two values of different numeric types, between large integers and floating point numbers, the mathematical value of the result may be outside of the domain of either. For example, `(2n**53n + 1n) + 0.5` has a value which cannot be accurately represented in either range. Floating point arithmetic is not the exact mathematical value, but at least it is well-defined by IEEE 754. The entire aim of introducing BigInt is, on the other hand, to make a way to preserve integer precision of larger values.
52 |
53 | Many (all?) other dynamically typed programming languages which have multiple numeric types implement a *numeric tower*. This forms an ordering between types--on the built-in numeric types, when an operator is used with operands from two types, the greater type is chosen as the domain, and the "less general" operand is cast to the "more general" type. Unfortunately, as the previous example shows, there is no "more general" type between arbitrary integers and double-precision floats. The typical resolution, then, is to take floats as the "more general" type.
54 |
55 | Silently losing precision sometimes may be a problem, but in most dynamically typed programming languages which provide integers and floats, integers are written like `1` and floats are written like `1.0`. It's possible to scan code for operations which may introduce floating point precision by looking for a decimal point. JavaScript exacerbates the scope of losing precision by making the unfortunate decision that a simple literal like `1` is a float. So, if mixed-precision were allowed, an innocent calculation such as `2n ** 53n + 1` would produce the float `2**53`--defeating the core functionality of this feature.
56 |
57 | To avoid this problem, this proposal bans implicit coercions between Numbers and BigInts, including operations which are mixed type. `1n + 1` throws a TypeError. So does passing `1n` as an argument into any JavaScript standard library function or Web API which expects a Number. Instead, to convert between types, an explicit call to `Number()` or `BigInt()` needs to be made to decide which domain to operate in. `0 === 0n` returns `false`.
58 |
59 | Comparisons form an exception to this rule: It's mathematically well-defined to allow comparison operators such as `<` and `==` compare between Numbers and BigInts. Unlike operators like `+`, there is no loss of precision, since the output is just a Boolean. Further, `==` is extended in comparisons with strings in analogous ways, such as `0n == ""` is `true`. Although we may not be able to extend this support to user-defined types, it seems sufficiently important for meeting user expectations that this proposal adds them as a one-off.
60 |
61 | ## Design goals
62 |
63 | #### Find a balance between maintaining user intuition and preserving precision
64 |
65 | When a messy situation comes up, this proposal errs on the side of throwing an exception rather than silently giving a bad answer. This is what's behind throwing a TypeError on adding a BigInt and a Number: If we don't have a good answer, better to not give one.
66 |
67 | Some JavaScript users will surely have the intuition that everything will just work, and that exceptions will not be thrown, when doing this sort of interoperation, even at the cost of losing precision. Axel Rauschmeyer [elaborated](https://gist.github.com/rauschma/13d48d1c49615ce2396ce7c9e45d4cd1) a proposal which elaborates this approach. [Further discussion](https://github.com/tc39/proposal-integer/issues/36) raised a few issues with this approach which are a direct result of upgrading the behavior of existing Numbers, both in terms of compatibility and reasonable expectations of invariants of JavaScript values. Given the tradeoffs, we have chosen to stick with the distinct type approach.
68 |
69 | ### Don't break math
70 |
71 | The semantics of all operators should ideally be based on some mathematical first principles, and certainly be well-defined, rather than excessively exposing implementation artifacts. `/` and `%` round towards 0, this is to match well-established computer conventions; aside from that, all operators have clean, mathematical definitions which don't appeal to the implementation shape.
72 |
73 | ### Don't break asm.js
74 |
75 | Although this proposal introduces operator overloading, it throws in any of the cases that asm.js depends on for setting up type checking. asm.js relies on a few identities:
76 | - Unary `+` followed by an expression is always either a Number, or results in throwing. For this reason, unfortunately, `+` on a BigInt needs to throw, rather than being symmetrical with `+` on Number: Otherwise, previously "type-declared" asm.js code would now be polymorphic.
77 | - `|0` always returns a Number in int32 range, or throws. This proposal maintains that, as it would throw on a BigInt for being a mixed operand type.
78 | - `Math.fround` always returns a Number in float32 range, or throws. This proposal would throw if `Math.fround` is called with a BigInt, preserving the property.
79 |
80 | Analogously, `>>> 0` always returns a Number in uint32 range, throwing as `>>>` is not supported on BigInt at all. Note: asm.js itself does not require this property, as `>>>` may be an overloaded operator, and `|0` is used for all `int` parameter declarations, but `>>> 0` is a common idiom to achieve this property in JavaScript code.
81 |
82 | This proposal makes special allowances to make BigInt usable in asm.js code to build support for 64-bit integers, by including the standard library functions `BigInt.asUintN` and `BigInt.asIntN` as well as `BigUint64Array` and `BigInt64Array`.
83 | The operator overloading in this proposal should not complicate the asm.js model: asm.js already treats operators as "overloaded" between floats, doubles, and signed and unsigned integers.
84 |
85 | ### Don't break potential future value types extensions
86 |
87 | - Should pave the cowpath to value types, as previously discussed, in conjunction with the work done on SIMD.js.
88 | - BigInts are a new primitive type, and have associated wrappers, as do the other primitives, and SIMD.js, and as value types would get.
89 | - Operator overloading on value types may follow a similar pattern of requiring uniform argument types; this avoids the very difficult proposition of double dispatch. By not supporting mixed operands, BigInt gets no superpowers which would be very difficult to generalize. Mixed comparisons are a one-off exception to this principle, however.
90 | - `L` has been proposed as a literal suffix for positive Int64 values. This proposal uses `n` to leave that space free for later (bikeshedding welcome!).
91 |
92 | ### Don't break JavaScript ergonomics
93 |
94 | This proposal comes with built-in operator overloading in order to not make BigInts too ugly to be usable. One particular hazard, if BigInts were to be operated on with static methods, is that users may convert the BigInt into a Number in order to use the `+` operator on it--this would work most of the time, just not with big enough values, so it might pass tests. By including operator overloading, it would be even shorter code to add the BigInts properly than to convert them to Numbers, which minimizes the chance of this bug.
95 |
96 | ### Don't break a consistent model of JavaScript
97 |
98 | This proposal adds a new primitive type with wrappers, similar to Symbol. As part of integrating BigInts into the JavaScript specification, a high amount of rigor will be required to differentiate three types floating around in the specification: Mathematical values, BigInts and Numbers.
99 |
100 | ### Don't break the web
101 |
102 | We need to choose a web-compatible name to add to the global object. There is some worry that the name `Integer` could have a web compatibility risk, though we don't actually have data about this. Changing the semantics of existing operations performed on existing numbers might also have compatibility risk, and this proposal avoids making these kinds of changes.
103 |
104 | ### Don't break good performance
105 |
106 | Design work here is being done in conjunction with planned prototyping in V8; this will be used to develop feedback to ensure that the proposal is efficiently implementable.
107 |
108 | ## Design alternatives not selected here
109 |
110 | ### Int64/Uint64
111 |
112 | Brendan Eich previously proposed two types--signed and unsigned Int64/Uint64, for JavaScript. These meet many of the concrete use cases for BigInts. One claim is that they may provide more predictable performance; however, my understanding is that, if the appropriate casting operator (e.g., `BigInt.asUintN`) is used everywhere, an implementation like V8 is expected provide the same performance for BigInt as it would for an Int64 type. The risks of this approach are that the performance won't pan out without harder-to-remove cliffs, or that the ergonomics will be too bad for performance-sensitive code--we'll watch for these risks as the prototype advances.
113 |
114 | ### Allowing mixed operands
115 |
116 | We could allow mixed operands like `1 + 1n` returning `2` (a Number). It would lose precision, be harder to implement with as high performance, and not generalize well to user-defined types, but it would follow the well-worn path of many other programming languages, which have just let users deal with these issues.
117 |
118 | ### Leave out TypedArrays and DataView methods for now
119 |
120 | One possibility would be to wait until a potential future Int64/Uint64 proposal is created for TypedArray classes and DataView methods. However, they are included here, following the pattern of existing TypedArrays which return Numbers--a more general type than the contents, but one which accurately represents it.
121 |
122 | ## Left for future proposals
123 |
124 | ### Function and constant library ([bug](https://github.com/tc39/proposal-bigint/issues/20))
125 |
126 | It would be reasonable to add integer-related mathematical library functions, especially those which could be more efficiently based on instructions found on CPUs likely to be used by implementations. This includes:
127 | - Bitcast between BigInt and Number
128 | - Find first set/unset bit
129 | - Popcount
130 | - Find most significant set/unset bit
131 | - Convenience functions for doing arithmetic in a specific modulus (e.g., 64-bit signed or unsigned) rather than requiring use of the wrap functions and arithmetic separately.
132 | - Constants for the maximum and minimum 64-bit signed and unsigned integer
133 |
134 | ### Any other numerical types, and generalization to binary data and value types
135 |
136 | In the course of development of ES2015, the proposal to add 64-bit integers was generalized significantly into a value types/binary data proposal. This big proposal became very complicated and unwieldy, so it was dropped from ES2015. The current proposal is much smaller, and could be built on incrementally. Value types and smaller integer types may be possible follow-ons, and this proposal is designed to generalize to those, but not block on them.
137 |
138 | ## Implementation status
139 |
140 | - [V8](https://bugs.chromium.org/p/v8/issues/detail?id=6791) by Georg Neis and Jakob Kummerow
141 | - [JSC](https://bugs.webkit.org/show_bug.cgi?id=175359) by Caio Lima and Robin Morisset
142 | - [SpiderMonkey](https://bugzilla.mozilla.org/show_bug.cgi?id=1366287) by Robin Templeton
143 |
144 | ## Specification
145 |
146 | See the [specification](https://tc39.github.io/proposal-bigint/) for more fine details.
147 |
148 | ### Related specification proposals
149 |
150 | - [BigInt WebAssembly JS API integration proposal](https://github.com/WebAssembly/spec/pull/707)
151 | - [HTML serialization of BigInt](https://github.com/whatwg/html/pull/3480)
152 | - [BigInt as an IndexedDB key](https://github.com/w3c/IndexedDB/pull/231)
153 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BigInt: Arbitrary precision integers in JavaScript
2 |
3 | Daniel Ehrenberg, Igalia. Stage 4
4 |
5 | This proposal is complete and already merged into ECMA262 specification. See the specification text [here](https://tc39.es/ecma262/).
6 |
7 | Thanks for help and feedback on this effort from Brendan Eich, Waldemar Horwat, Jaro Sevcik, Benedikt Meurer, Michael Saboff, Adam Klein, Sarah Groff-Palermo and others.
8 |
9 | ## Contents
10 | 1. [What Is It?](#what-is-it)
11 | 2. [How Does It Work?](#how-does-it-work)
12 | - [Syntax](#syntax)
13 | - [Example: Calculating Primes](#example-calculating-primes)
14 | - [Operators](#operators)
15 | - [Comparisons](#comparisons)
16 | - [Conditionals](#conditionals)
17 | - [Other API Notes](#other-api-notes)
18 | 3. [Gotchas & Exceptions](#gotchas--exceptions)
19 | - [Interoperation with `Number` and `String`](#interoperation-with-number-and-string)
20 | - [Rounding](#rounding)
21 | - [Cryptography](#cryptography)
22 | - [Other Exceptions](#other-exceptions)
23 | - [Usage Recommendations](#usage-recommendations)
24 | 4. [About the Proposal](#about-the-proposal)
25 | - [Motivation, Or Why Do We Need Such Big Numbers?](#motivation-why-do-we-need-such-big-numbers)
26 | - [Design Philosophy, Or Why Is This Like This?](#design-goals-or-why-is-this-like-this)
27 | - [State of the Proposal](#state-of-the-proposal)
28 |
29 |
30 | ## What Is It?
31 |
32 | `BigInt` is a new primitive that provides a way to represent whole numbers larger than 253, which is the largest number Javascript can reliably represent with the `Number` primitive.
33 |
34 | ```js
35 | const x = Number.MAX_SAFE_INTEGER;
36 | // ↪ 9007199254740991, this is 1 less than 2^53
37 |
38 | const y = x + 1;
39 | // ↪ 9007199254740992, ok, checks out
40 |
41 | const z = x + 2
42 | // ↪ 9007199254740992, wait, that’s the same as above!
43 | ```
44 |
45 | [Learn more about how numbers are represented in Javascript in the slides from Daniel's talk at JSConfEU.](https://docs.google.com/presentation/d/1apPbAiv_-mJF35P31IjaII8UA6TwSynCA_zhfDEmgOE/edit#slide=id.g38a1897a56_0_97)
46 |
47 | ## How Does It Work?
48 |
49 | The following sections show `BigInt` in action. A number have been influenced by or taken outright from [Mathias Bynens's BigInt v8 update, which includes more details than this page.](https://developers.google.com/web/updates/2018/05/bigint)
50 |
51 | ### Syntax
52 |
53 | A `BigInt` is created by appending `n` to the end of the integer or by calling the constructor.
54 |
55 | ```js
56 |
57 | const theBiggestInt = 9007199254740991n;
58 |
59 | const alsoHuge = BigInt(9007199254740991);
60 | // ↪ 9007199254740991n
61 |
62 | const hugeButString = BigInt('9007199254740991');
63 | // ↪ 9007199254740991n
64 |
65 | ```
66 |
67 | ### Example: Calculating Primes
68 |
69 | ```js
70 | function isPrime(p) {
71 | for (let i = 2n; i * i <= p; i++) {
72 | if (p % i === 0n) return false;
73 | }
74 | return true;
75 | }
76 |
77 | // Takes a BigInt as an argument and returns a BigInt
78 | function nthPrime(nth) {
79 | let maybePrime = 2n;
80 | let prime = 0n;
81 |
82 | while (nth >= 0n) {
83 | if (isPrime(maybePrime)) {
84 | nth -= 1n;
85 | prime = maybePrime;
86 | }
87 | maybePrime += 1n;
88 | }
89 |
90 | return prime;
91 | }
92 |
93 | ```
94 |
95 | ### Operators
96 |
97 | You can use `+`, `*`, `-`, `**` and `%` with `BigInt`s, just like with `Number`s.
98 |
99 | ```js
100 |
101 | const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
102 | // ↪ 9007199254740991
103 |
104 | const maxPlusOne = previousMaxSafe + 1n;
105 | // ↪ 9007199254740992n
106 |
107 | const theFuture = previousMaxSafe + 2n;
108 | // ↪ 9007199254740993n, this works now!
109 |
110 | const multi = previousMaxSafe * 2n;
111 | // ↪ 18014398509481982n
112 |
113 | const subtr = multi – 10n;
114 | // ↪ 18014398509481972n
115 |
116 | const mod = multi % 10n;
117 | // ↪ 2n
118 |
119 | const bigN = 2n ** 54n;
120 | // ↪ 18014398509481984n
121 |
122 | bigN * -1n
123 | // ↪ –18014398509481984n
124 |
125 | ```
126 |
127 | The `/` operator also work as expected with whole numbers. However, since these are `BigInt`s and not `BigDecimal`s, this operation will round towards 0, which is to say, it will not return any fractional digits.
128 |
129 | ```js
130 |
131 | const expected = 4n / 2n;
132 | // ↪ 2n
133 |
134 | const rounded = 5n / 2n;
135 | // ↪ 2n, not 2.5n
136 |
137 | ```
138 |
139 | [See the advanced documentation for use with bitwise operators.](/ADVANCED.md)
140 |
141 | ### Comparisons
142 |
143 | A `BigInt` is not strictly equal to a `Number`, but it is loosely so.
144 |
145 | ```js
146 |
147 | 0n === 0
148 | // ↪ false
149 |
150 | 0n == 0
151 | // ↪ true
152 |
153 | ```
154 |
155 | `Number`s and `BigInt`s may be compared as usual.
156 |
157 | ```js
158 | 1n < 2
159 | // ↪ true
160 |
161 | 2n > 1
162 | // ↪ true
163 |
164 | 2 > 2
165 | // ↪ false
166 |
167 | 2n > 2
168 | // ↪ false
169 |
170 | 2n >= 2
171 | // ↪ true
172 | ```
173 |
174 | They may be mixed in arrays and sorted.
175 |
176 | ```js
177 |
178 | const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
179 | // ↪ [4n, 6, -12n, 10, 4, 0, 0n]
180 |
181 | mixed.sort();
182 | // ↪ [-12n, 0, 0n, 10, 4n, 4, 6]
183 | ```
184 |
185 | ### Conditionals
186 |
187 | A `BigInt` behaves like a `Number` in cases where it is converted to a `Boolean`: `if`, `||`, `&&`, `Boolean`, `!`.
188 |
189 | ```js
190 |
191 | if (0n) {
192 | console.log('Hello from the if!');
193 | } else {
194 | console.log('Hello from the else!');
195 | }
196 |
197 | // ↪ "Hello from the else!"
198 |
199 | 0n || 12n
200 | // ↪ 12n
201 |
202 | 0n && 12n
203 | // ↪ 0n
204 |
205 | Boolean(0n)
206 | // ↪ false
207 |
208 | Boolean(12n)
209 | // ↪ true
210 |
211 | !12n
212 | // ↪ false
213 |
214 | !0n
215 | // ↪ true
216 |
217 | ```
218 |
219 | ### Other API Notes
220 |
221 | `BigInt`s may also be used in `BigInt64Array` and `BigUint64Array` [typed arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) for 64-bit integers.
222 |
223 | ```js
224 | const view = new BigInt64Array(4);
225 | // ↪ [0n, 0n, 0n, 0n]
226 | view.length;
227 | // ↪ 4
228 | view[0];
229 | // ↪ 0n
230 | view[0] = 42n;
231 | view[0];
232 | // ↪ 42n
233 |
234 | // Highest possible BigInt value that can be represented as a
235 | // signed 64-bit integer.
236 | const max = 2n ** (64n - 1n) - 1n;
237 | view[0] = max;
238 | view[0];
239 | // ↪ 9_223_372_036_854_775_807n
240 | view[0] = max + 1n;
241 | view[0];
242 | // ↪ -9_223_372_036_854_775_808n
243 | // ^ negative because of overflow
244 |
245 | ```
246 |
247 | [For more about `BigInt` library functions, see the advanced section.](/ADVANCED.md)
248 |
249 |
250 | ## Gotchas & Exceptions
251 |
252 | ### Interoperation with `Number` and `String`
253 |
254 | The biggest surprise may be that `BigInt`s cannot be operated on interchangeably with `Number`s. Instead a `TypeError` will be thrown. ([Read the design philosophy for more about why this decision was made.](#design-goals-or-why-is-this-like-this))
255 |
256 |
257 | ```js
258 |
259 | 1n + 2
260 | // ↪ TypeError: Cannot mix BigInt and other types, use explicit conversions
261 |
262 | 1n * 2
263 | // ↪ TypeError: Cannot mix BigInt and other types, use explicit conversions
264 |
265 | ```
266 |
267 | `BigInt`s also cannot be converted to `Number`s using the unary `+`. `Number` must be used.
268 |
269 | ```js
270 |
271 | +1n
272 | // ↪ TypeError: Cannot convert a BigInt value to a number
273 |
274 | Number(1n)
275 | // ↪ 1
276 |
277 | ```
278 |
279 | The `BigInt` *can* however be concatenated with a `String`.
280 |
281 |
282 | ```js
283 |
284 | 1n + '2'
285 | // ↪ "12"
286 |
287 | '2' + 1n
288 | // ↪ "21"
289 |
290 | ```
291 |
292 | For this reason, it is recommended to continue using `Number` for code which will only encounter values under 253.
293 |
294 | Reserve `BigInt` for cases where large values are expected. Otherwise, by converting back and forth, you may lose the very precision you are hoping to preserve.
295 |
296 | ```js
297 | const largeFriend = 900719925474099267n;
298 | const alsoLarge = largeFriend + 2n;
299 |
300 | const sendMeTheBiggest = (n, m) => Math.max(Number(n), Number(m));
301 |
302 | sendMeTheBiggest(largeFriend, alsoLarge)
303 | // ↪900719925474099300 // This is neither argument!
304 | ```
305 |
306 | Reserve `Number` values for cases when they are integers up to 253, for other cases, using a string (or a `BigInt` literal) would be advisable to not lose precision.
307 |
308 | ```js
309 | const badPrecision = BigInt(9007199254740993);
310 | // ↪9007199254740992n
311 |
312 | const goodPrecision = BigInt('9007199254740993');
313 | // ↪9007199254740993n
314 |
315 | const alsoGoodPrecision = 9007199254740993n;
316 | // ↪9007199254740993n
317 | ```
318 |
319 | ### Rounding
320 |
321 | As noted above, the `BigInt` only represents whole numbers. `Number` only reliably represents integers up to 253. That means both dividing and converting to a `Number` can lead to rounding.
322 |
323 | ```js
324 |
325 | 5n / 2n
326 | // ↪ 2n
327 |
328 | Number(151851850485185185047n)
329 | // ↪ 151851850485185200000
330 |
331 | ```
332 |
333 | ### Cryptography
334 |
335 | The operations supported on `BigInt`s are not constant time. `BigInt` is therefore [unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).
336 |
337 | Many platforms provide native support for cryptography, such as [webcrypto](https://w3c.github.io/webcrypto/Overview.html) or [node crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
338 |
339 |
340 | ### Other Exceptions
341 |
342 | Attempting to convert a fractional value to a `BigInt` throws an exception both when the value is represented as an `Number` and a `String`.
343 |
344 | ```js
345 | BigInt(1.5)
346 | // ↪ RangeError: The number 1.5 is not a safe integer and thus cannot be converted to a BigInt
347 |
348 | BigInt('1.5')
349 | // ↪ SyntaxError: Cannot convert 1.5 to a BigInt
350 |
351 | ```
352 |
353 | Operations in the `Math` library will throw an error when used with `BigInt`s, as will `|`.
354 |
355 | ```js
356 |
357 | Math.round(1n)
358 | // ↪ TypeError: Cannot convert a BigInt value to a number
359 |
360 | Math.max(1n, 10n)
361 | // ↪ TypeError: Cannot convert a BigInt value to a number
362 |
363 | 1n|0
364 | // ↪ TypeError: Cannot mix BigInt and other types, use explicit conversions
365 |
366 | ```
367 |
368 | `parseInt` and `parseFloat` will however convert a `BigInt` to a `Number` and lose precision in the process. (This is because these functions discard trailing non-numeric values — including `n`.
369 |
370 | ```js
371 |
372 | parseFloat(1234n)
373 | // ↪1234
374 |
375 | parseInt(10n)
376 | // ↪10
377 |
378 | // precision lost!
379 | parseInt(900719925474099267n)
380 | // ↪900719925474099300
381 | ```
382 |
383 | Finally, `BigInt`s cannot be serialized to JSON. There are, however, libraries — for instance, [granola](https://github.com/kanongil/granola) — that can handle this for you.
384 |
385 | ```js
386 | const bigObj = {a: BigInt(10n)};
387 | JSON.stringify(bigObj)
388 | // ↪TypeError: Do not know how to serialize a BigInt
389 | ```
390 |
391 | ### Usage Recommendations
392 |
393 | ### Coercion
394 | Because coercing between `Number` and BigInt can lead to loss of precision, it is recommended to only use BigInt when values greater than 253 are reasonably expected and not to coerce between the two types.
395 |
396 | ## About the Proposal
397 |
398 | ### Motivation: Why Do We Need Such Big Numbers?
399 |
400 | There are a number of cases in JavaScript coding where integers larger than 253 come up — both instances where signed or unsigned 64-bit integers are needed and times where we may want integers even larger than 64-bits.
401 |
402 | #### 64-bit Use Cases
403 |
404 | Often, other systems with which Javascript interacts provides data as 64-bit integers, which lose precision when coerced to Javascript Numbers.
405 |
406 | These might come when reading certain machine registers or wire protocols or using protobufs or JSON documents that have GUIDs generated by 64-bit systems in them — including things like credit card or account numbers — which currently must remain strings in Javascript. (Note, however, `BigInt`s cannot be serialized to JSON directly. But you can use libraries like [granola](https://github.com/kanongil/granola) to serialize and deserialize BigInt and other JS datatypes to JSON.)
407 |
408 | In node, `fs.stat` may give some data as 64-bit integers, which [has caused issues already](https://github.com/nodejs/node/issues/12115):
409 |
410 | ```js
411 | fs.lstatSync('one.gif').ino
412 | // ↪ 9851624185071828
413 |
414 | fs.lstatSync('two.gif').ino
415 | // ↪ 9851624185071828, duplicate, but different file!
416 | ```
417 |
418 | Finally, 64-bit integers enable higher resolution — _nanosecond!_ — timestamps. These will be put to use in the [temporal proposal](https://github.com/tc39/proposal-temporal), currently in Stage 1.
419 |
420 | #### Bigger Than 64-bit Use Cases
421 |
422 | Integers larger than 64-bit values are most likely to arise when doing mathematical calculations with larger integers, such as solving Project Euler problems or exact geometric calculations. Adding `BigInt` makes it possible to meet a reasonable user expectation of a high-level language that integer arithmetic will be "correct" and not suddenly overflow.
423 |
424 | If this seems far-fetched, consider the case of [the Pentium FDIV bug](https://en.wikipedia.org/wiki/Pentium_FDIV_bug). In 1994, a bug in Pentium chips made floating point values rarely —but possibly — imprecise. It was discovered by a mathematics professor who was relying on that precision.
425 |
426 | ### Design Goals, Or Why Is This Like This?
427 |
428 | These principles guided the decisions made with this proposal. Check out [`ADVANCED.md`](/ADVANCED.md) for more in-depth discussion of each.
429 |
430 | #### Find a balance between maintaining user intuition and preserving precision
431 |
432 | In general, this proposal has aimed to work in a manner complementary to user intuition about how Javascript works. At the same time, the goal for this proposal is to add further affordances for precision to the language. Sometimes these can conflict.
433 |
434 | When a messy situation comes up, this proposal errs on the side of throwing an exception rather than rely on type coercion and risk giving an imprecise answer. This is what's behind throwing a `TypeError` on adding a `BigInt` and a `Number` and other [exceptions detailed above](#gotchas--exceptions): If we don't have a good answer, better to not give one.
435 |
436 | For more discussion of these choices, see [Axel Rauschmeyer's proposal](https://gist.github.com/rauschma/13d48d1c49615ce2396ce7c9e45d4cd1) and [further discussion of its effects on Numbers](https://github.com/tc39/proposal-integer/issues/36). We ended up concluding that it would be impractical to provide transparent interoperability between Number and BigInt.
437 |
438 | #### Don't break math
439 |
440 | The semantics of all operators should ideally be based on some mathematical first principles, to match developer expectations. The division and modulo operators are based on conventions from other programming languages for integers.
441 |
442 | #### Don't break JavaScript ergonomics
443 |
444 | This proposal comes with built-in operator overloading in order to not make `BigInt`s too ugly to be usable. One particular hazard, if `BigInts` were to be operated on with static methods, is that users may convert the `BigInt` into a `Number` in order to use the `+` operator on it--this would work most of the time, just not with big enough values, so it might pass tests. By including operator overloading, it would be even shorter code to add the `BigInt`s properly than to convert them to `Numbers`, which minimizes the chance of this bug.
445 |
446 | #### Don't break the web
447 |
448 | This proposal doesn't change anything about the way Numbers work. The name `BigInt` was chosen in part to avoid compatibility risks carried by the more general `Integer` name (and in part to make it clear that they are useful for the "big" cases).
449 |
450 | #### Don't break good performance
451 |
452 | Design work here has been done in conjunction with prototyping in to ensure that the proposal is efficiently implementable.
453 |
454 | #### Don't break potential future value types extensions
455 |
456 | When adding new primitives to the language, it is important to avoid giving them superpowers that would be very difficult to generalize. This is another good reason for `BigInt` to avoid mixed operands.
457 |
458 | Mixed comparisons are a one-off exception to this principle, however, taken in support of the intuition design principle.
459 |
460 | #### Don't break a consistent model of JavaScript
461 |
462 | This proposal adds a new primitive type with wrappers, similar to `Symbol`. As part of integrating `BigInt`s into the JavaScript specification, a high amount of rigor will be required to differentiate three types floating around in the specification: Mathematical values, `BigInt`s and `Number`s.
463 |
464 | ### State of the Proposal
465 |
466 | This proposal is currently in [Stage 4.](https://tc39.github.io/process-document/)
467 |
468 | `BigInt` has been shipped in Chrome, Node, Firefox, and is underway in Safari.
469 | - [V8](https://bugs.chromium.org/p/v8/issues/detail?id=6791) by Georg Neis and Jakob Kummerow.
470 | - [JSC](https://bugs.webkit.org/show_bug.cgi?id=179001) by Caio Lima and Robin Morisset.
471 | - [SpiderMonkey](https://bugzilla.mozilla.org/show_bug.cgi?id=1366287) by Robin Templeton and Andy Wingo.
472 |
473 | Related specification proposals:
474 | - [BigInt WebAssembly JS API integration proposal](https://github.com/WebAssembly/spec/pull/707)
475 | - [HTML serialization of BigInt](https://github.com/whatwg/html/pull/3480)
476 | - [BigInt as an IndexedDB key](https://github.com/w3c/IndexedDB/pull/231)
477 |
--------------------------------------------------------------------------------
/spec.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | title: BigInt
5 | status: proposal
6 | stage: 4
7 | location: https://github.com/tc39/proposal-bigint
8 | copyright: false
9 | contributors: Daniel Ehrenberg, Brendan Eich
10 |
11 |
75 |
76 |
77 | Introduction
78 | This proposal adds arbitrary-precision integers to ECMAScript. For motivation and a high-level introduction, see the explainer document.
79 |
80 |
81 | I attempted to write this specification draft with an eye towards intelligibility and clarifying issues, rather than looking exactly like the final specification. In particular, the translation of the operations on the Number type into the new form are omitted, as they are identical to the previous definitions and would be expressed only as a lengthy refactoring to skip when reading this text.
82 | If you find any part of this specification unclear or confusing, please file an issue.
83 |
84 |
85 |
86 | Numeric Types
87 | ECMAScript has two built-in numeric types: Number and BigInt. In this specification, every numeric type _T_ contains a multiplicative identity value denoted _T_::unit. The specification types also have the following abstract operations, likewise denoted _T_::op for a given operation with specification name op. Unless noted otherwise, argument and result types are all _T_.
88 |
89 |
90 |
91 |
92 | |
93 | Invocation Synopsis
94 | |
95 |
96 | Value and Purpose
97 | |
98 |
99 |
100 | |
101 | _T_::unaryMinus(x)
102 | |
103 |
104 | A specification function invoked when applying the unary minus operator. Called by the semantics of the unary - operator.
105 | |
106 |
107 |
108 | |
109 | _T_::bitwiseNOT(x)
110 | |
111 |
112 | A specification function invoked when applying the bitwise NOT operator. Called by the semantics of the bitwise NOT operator for `~x`.
113 | |
114 |
115 |
116 | |
117 | _T_::exponentiate(x, y)
118 | |
119 |
120 | A specification function invoked when applying the exponentiation operator. Called by the semantics of the exponentiation operator for `x ** y`.
121 | |
122 |
123 |
124 | |
125 | _T_::multiply(x, y)
126 | |
127 |
128 | A specification function invoked when applying the multiplication operator. Called by the semantics of the `*` operator for `x * y`.
129 | |
130 |
131 |
132 | |
133 | _T_::divide(x, y)
134 | |
135 |
136 | A specification function invoked when applying the division operator. Called by the semantics of the `/` operator for `x / y`.
137 | |
138 |
139 |
140 | |
141 | _T_::remainder(x, y)
142 | |
143 |
144 | A specification function invoked when applying the truncating remainder ("mod") operator. Called by the semantics of the `%` operator for `x % y`.
145 | Revisit this name, as Number::remainder explicitly doesn't do the IEEE 754 remainder operation. However, modulo also seems problematic. (issue)
146 | |
147 |
148 |
149 | |
150 | _T_::add(x, y)
151 | |
152 |
153 | A specification function invoked when applying the addition operator. Called by the semantics of the `+` operator for `x + y`.
154 | |
155 |
156 |
157 | |
158 | _T_::subtract(x, y)
159 | |
160 |
161 | A specification function invoked when applying the subtraction operator. Called by the semantics of the `-` operator for `x - y`.
162 | |
163 |
164 |
165 | |
166 | _T_::leftShift(x, y)
167 | |
168 |
169 | A specification function invoked when applying the left shift operator to two operands, both of type _T_. Called by the semantics of the `<<` operator for `x << y`.
170 | |
171 |
172 |
173 | |
174 | _T_::signedRightShift(x, y)
175 | |
176 |
177 | A specification function invoked when applying the right shift operator to two operands, both of type _T_. Called by the semantics of the `>>` operator for `x >> y`.
178 | |
179 |
180 |
181 | |
182 | _T_::unsignedRightShift(x, y)
183 | |
184 |
185 | A specification function invoked when applying the right shift operator to two operands, both of type _T_. Called by the semantics of the `>>>` operator for `x >>> y`.
186 | |
187 |
188 |
189 | |
190 | _T_::lessThan(x, y)
191 | |
192 |
193 | A specification function invoked when applying one of the four partial-order relational operators. The return value must be *false*, *true*, or *undefined* (for unordered inputs). Called by the Abstract Relational Comparison algorithm for `x < y`, `x > y`, `x <= y`, and `x >= y`.
194 | |
195 |
196 |
197 | |
198 | _T_::equal(x, y)
199 | |
200 |
201 | A specification function invoked when applying equality operators. The return value must be *false* or *true*. Called by the Strict Equality Comparison algorithm for `x == y`, `x != y`, `x === y`, and `x !== y`.
202 | |
203 |
204 |
205 | |
206 | _T_::sameValue(x, y)
207 | |
208 |
209 | A specification function invoked when applying abstract operation SameValue. The return value must be *false* or *true*. Called from Object internal methods to test exact value equality. May not throw an exception.
210 | |
211 |
212 |
213 | |
214 | _T_::sameValueZero(x, y)
215 | |
216 |
217 | A specification function invoked when applying abstract operation SameValueZero. The return value must be *false* or *true*. Called from Array, Map, and Set methods to test value equality ignoring differences among members of the zero cohort (e.g., *-0* and *+0*). May not throw an exception.
218 | |
219 |
220 |
221 | |
222 | _T_::bitwiseAND(x, y)
223 | |
224 |
225 | A specification function invoked when applying binary bitwise AND operator. Called by the Binary Bitwise Operators algorithm for `x & y`.
226 | |
227 |
228 |
229 | |
230 | _T_::bitwiseXOR(x, y)
231 | |
232 |
233 | A specification function invoked when applying binary bitwise XOR operator. Called by the Binary Bitwise Operators algorithm for `x ^ y`.
234 | |
235 |
236 |
237 | |
238 | _T_::bitwiseOR(x, y)
239 | |
240 |
241 | A specification function invoked when applying binary bitwise OR operator. Called by the Binary Bitwise Operators algorithm for `x | y`.
242 | |
243 |
244 |
245 |
246 |
247 | The _T_::unit value and _T_::_op_ operations are not a part of the ECMAScript language; they are defined here solely to aid the specification of the semantics of the ECMAScript language. Other abstract operations are defined throughout this specification.
248 | Because the numeric types are in general not convertible without loss of precision or truncation, the ECMAScript language provides no implicit conversion among these types. Programmers must explicitly call `Number` and `BigInt` functions to convert among types when calling a function which requires another type.
249 |
250 | The first and subsequent editions of ECMAScript have provided, for certain operators, implicit numeric conversions that could lose precision or truncate. These legacy implicit conversions are maintained for backward compatibility, but not provided for BigInt in order to minimize opportunity for programmer error, and to leave open the option of generalized value types in a future edition.
251 |
252 |
253 |
254 |
255 | The BigInt Type
256 | The BigInt type represents a mathematical integer value. The value may be any size and is not limited to a particular bit-width. Generally, where not otherwise noted, operations are designed to return exact mathematically-based answers. For binary operations, BigInts act as two's complement binary strings, with negative numbers treated as having bits set infinitely to the left.
257 |
258 | The BigInt::unit value is *1n*.
259 |
260 |
261 | BigInt::unaryMinus (_x_)
262 | The abstract operation BigInt::unaryMinus with an argument _x_ of BigInt type returns the result of negating _x_.
263 | There is only one *0n* value; `-0n` is the same as *0n*.
264 |
265 |
266 |
267 | BigInt::bitwiseNOT (_x_)
268 | The abstract operation BigInt::bitwiseNOT with an argument _x_ of BigInt type returns the one's complement of _x_; that is, -_x_ - 1.
269 |
270 |
271 |
272 | BigInt::exponentiate (_base_, _exponent_)
273 |
274 | 1. If _exponent_ < 0, throw a *RangeError* exception.
275 | 1. If _base_ is *0n* and _exponent_ is *0n*, return *1n*.
276 | 1. Return a BigInt representing the mathematical value of _base_ raised to the power _exponent_.
277 |
278 |
279 |
280 |
281 | BigInt::multiply (_x_, _y_)
282 | The abstract operation BigInt::multiply with two arguments _x_ and _y_ of BigInt type returns a BigInt representing the result of multiplying _x_ and _y_.
283 | Even if the result has a much larger bit width than the input, the exact mathematical answer is given.
284 |
285 |
286 |
287 | BigInt::divide (_x_, _y_)
288 |
289 | 1. If _y_ is *0n*, throw a *RangeError* exception.
290 | 1. Let _quotient_ be the mathematical value of _x_ divided by _y_.
291 | 1. Return a BigInt representing _quotient_ rounded towards 0 to the next integral value.
292 |
293 |
294 |
295 |
296 | BigInt::remainder (_n_, _d_)
297 |
298 | 1. If _d_ is *0n*, throw a *RangeError* exception.
299 | 1. If _n_ is *0n*, return *0n*.
300 | 1. Let _r_ be the BigInt defined by the mathematical relation _r_ = _n_ - (_d_ × _q_) where _q_ is a BigInt that is negative only if _n_/_d_ is negative and positive only if _n_/_d_ is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of _n_ and _d_.
301 | 1. Return _r_.
302 |
303 | The sign of the result equals the sign of the dividend.
304 |
305 |
306 |
307 | BigInt::add (_x_, _y_)
308 | The abstract operation BigInt::add with two arguments _x_ and _y_ of BigInt type returns a BigInt representing the sum of _x_ and _y_.
309 |
310 |
311 |
312 | BigInt::subtract (_x_, _y_)
313 | The abstract operation BigInt::subtract with two arguments _x_ and _y_ of BigInt type returns the BigInt representing the difference _x_ minus _y_.
314 |
315 |
316 |
317 | BigInt::leftShift (_x_, _y_)
318 | The abstract operation BigInt::leftShift with two arguments _x_ and _y_ of BigInt:
319 |
320 | 1. If _y_ < 0, then
321 | 1. Return a BigInt representing _x_ ÷ 2-_y_, rounding down to the nearest integer, including for negative numbers.
322 | 1. Return a BigInt representing _x_ × 2_y_.
323 |
324 | Semantics here should be equivalent to a bitwise shift, treating the BigInt as an infinite length string of binary two's complement digits.
325 |
326 |
327 |
328 | BigInt::signedRightShift (_x_, _y_)
329 | The abstract operation BigInt::signedRightShift with arguments _x_ and _y_ of type BigInt:
330 |
331 | 1. Return BigInt::leftShift(_x_, -_y_).
332 |
333 |
334 |
335 |
336 | BigInt::unsignedRightShift (_x_, _y_)
337 | The abstract operation BigInt::unsignedRightShift with two arguments _x_ and _y_ of type BigInt:
338 |
339 | 1. Throw a *TypeError* exception.
340 |
341 |
342 |
343 |
344 | BigInt::lessThan (_x_, _y_)
345 | The abstract operation BigInt::lessThan with two arguments _x_ and _y_ of BigInt type returns *true* if _x_ is less than _y_ and *false* otherwise.
346 |
347 |
348 |
349 | BigInt::equal (_x_, _y_)
350 | The abstract operation BigInt::equal with two arguments _x_ and _y_ of BigInt type returns *true* if _x_ and _y_ have the same mathematical integer value and *false* otherwise.
351 |
352 |
353 |
354 | BigInt::sameValue (_x_, _y_)
355 | The abstract operation BigInt::sameValue with two arguments _x_ and _y_ of BigInt type:
356 |
357 | 1. Return BigInt::equal(_x_, _y_).
358 |
359 |
360 |
361 |
362 | BigInt::sameValueZero (_x_, _y_)
363 | The abstract operation BigInt::sameValueZero with two arguments _x_ and _y_ of BigInt type:
364 |
365 | 1. Return BigInt::equal(_x_, _y_).
366 |
367 |
368 |
369 |
370 | BitwiseOp(_op_, _x_, _y_)
371 |
372 | 1. Let _result_ be 0.
373 | 1. Let _shift_ be 0.
374 | 1. Repeat, until (_x_ = 0 or _x_ = -1) and (_y_ = 0 or _y_ = -1),
375 | 1. Let _xDigit_ be _x_ modulo 2.
376 | 1. Let _yDigit_ be _y_ modulo 2.
377 | 1. Let _result_ be _result_ + 2_shift_ × _op_(_xDigit_, _yDigit_).
378 | 1. Let _shift_ be _shift_ + 1.
379 | 1. Let _x_ be (_x_ - _xDigit_) / 2.
380 | 1. Let _y_ be (_y_ - _yDigit_) / 2.
381 | 1. If _op_(_x_ modulo 2, _y_ modulo 2) ≠ 0, then
382 | 1. Let _result_ be _result_ - 2_shift_. NOTE: This extends the sign.
383 | 1. Return _result_.
384 |
385 |
386 |
387 |
388 | BigInt::bitwiseAND (_x_, _y_)
389 |
390 | 1. Return BitwiseOp(`&`, _x_, _y_).
391 |
392 |
393 |
394 |
395 | BigInt::bitwiseXOR (_x_, _y_)
396 |
397 | 1. Return BitwiseOp(`^`, _x_, _y_).
398 |
399 |
400 |
401 |
402 | BigInt::bitwiseOR (_x_, _y_)
403 |
404 | 1. Return BitwiseOp(`|`, _x_, _y_).
405 |
406 |
407 |
408 |
409 |
410 | As part of the integration with the main specification, the Number type will have a similar definition of operations, derived from the current operator definitions. Because the semantics are not proposed to change, for ease of review, the refactoring is omitted from this spec draft.
411 |
412 |
413 |
414 |
415 | Modifications to the Number grammar
416 |
417 | NumericLiteral ::
418 | DecimalLiteral
419 | DecimalIntegerLiteral BigIntLiteralSuffix
420 | BinaryIntegerLiteral
421 | OctalIntegerLiteral
422 | HexIntegerLiteral
423 | NumericLiteralBase
424 | NumericLiteralBase BigIntLiteralSuffix
425 | LegacyOctalIntegerLiteral
426 |
427 | NumericLiteralBase ::
428 | BinaryIntegerLiteral
429 | OctalIntegerLiteral
430 | HexIntegerLiteral
431 |
432 | BigIntLiteralSuffix :: `n`
433 |
434 |
435 |
436 | Static Semantics: BigInt Value
437 | NumericLiteral :: NumericLiteralBase BigIntLiteralSuffix
438 |
439 | -
440 | Let the value of |NumericLiteral| be the MV of |NumericLiteralBase| represented as BigInt.
441 |
442 |
443 | NumericLiteral :: DecimalIntegerLiteral BigIntLiteralSuffix
444 |
445 | -
446 | Let the value of |NumericLiteral| be the MV of |DecimalIntegerLiteral| represented as BigInt.
447 |
448 |
449 |
450 |
451 |
452 | Static Semantics: Number Value
453 | NumericLiteral :: NumericLiteralBase
454 | The MV is rounded to a value of the Number type.
455 |
456 |
457 | Rounding to the nearest Number will be moved from the MV calculation to a Number Value Static Semantics section so that it doesn't apply to BigInts.
458 |
459 |
460 |
461 |
462 |
463 | Abstract Operations
464 |
465 | Type Conversion
466 | The BigInt type has no implicit conversions in the ECMAScript language; programmers must call BigInt explicitly to convert values from other types.
467 |
468 |
469 | ToPrimitive ( _input_ [ , _PreferredType_ ] )
470 |
471 |
472 |
473 |
474 | |
475 | Input Type
476 | |
477 |
478 | Result
479 | |
480 |
481 |
482 | |
483 | BigInt
484 | |
485 |
486 | Return _input_.
487 | |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 | ToBoolean ( _argument_ )
496 | The abstract operation ToBoolean converts _argument_ to a value of type Boolean according to :
497 |
498 |
499 |
500 |
501 | |
502 | Argument Type
503 | |
504 |
505 | Result
506 | |
507 |
508 |
509 | |
510 | BigInt
511 | |
512 |
513 | Return *false* if _argument_ is *0n*; otherwise return *true*.
514 | |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 | ToNumber ( _argument_ )
523 | The abstract operation ToNumber converts _argument_ to a value of type Number according to :
524 |
525 |
526 |
527 |
528 | |
529 | Argument Type
530 | |
531 |
532 | Result
533 | |
534 |
535 |
536 | |
537 | BigInt
538 | |
539 |
540 | Throw a *TypeError* exception
541 | |
542 |
543 |
544 |
545 |
546 |
547 | Although it would be possible to define a conversion here, to find the nearest Number for a BigInt, such a conversion may lose precision. ToNumber is called implicitly from so many places, but BigInts would not add any value if they lost precision all the time; you might as well just use Numbers instead in the first place. A key design decision of this specification is to disallow implicit conversions, and force programmers to use explicit conversions themselves instead.
548 |
549 |
550 |
551 | ToNumber Applied to the String Type
552 |
553 | Some differences should be noted between the syntax of a |StringNumericLiteral| and a |NumericLiteral|:
554 |
555 | -
556 | A |StringNumericLiteral| may not include a |BigIntLiteralSuffix|.
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 | ToString ( _argument_ )
565 | The abstract operation ToString converts _argument_ to a value of type String according to :
566 |
567 |
568 |
569 |
570 | |
571 | Argument Type
572 | |
573 |
574 | Result
575 | |
576 |
577 |
578 | |
579 | BigInt
580 | |
581 |
582 | See .
583 | |
584 |
585 |
586 |
587 |
588 |
589 |
590 | ToString Applied to the BigInt Type
591 | The abstract operation ToString converts a BigInt _i_ to String format as follows:
592 |
593 | 1. If _i_ is less than zero, return the string-concatenation of the String `"-"` and ToString(-_i_).
594 | 1. Return the String value consisting of the code units of the digits of the decimal representation of _i_.
595 |
596 |
597 |
598 |
599 |
600 | ToObject ( _argument_ )
601 | The abstract operation ToObject converts _argument_ to a value of type Object according to :
602 |
603 |
604 |
605 |
606 | |
607 | Argument Type
608 | |
609 |
610 | Result
611 | |
612 |
613 |
614 | |
615 | BigInt
616 | |
617 |
618 | Return a new BigInt object whose [[BigIntData]] internal slot is set to _argument_. See BigInt Objects for a description of BigInt objects.
619 | |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 | ToNumeric ( _value_ )
628 | The abstract operation ToNumeric returns _value_ converted to a numeric value of type Number or BigInt. This abstract operation functions as follows:
629 |
630 | 1. Let _primValue_ be ? ToPrimitive(_value_, hint Number).
631 | 1. If Type(_primValue_) is BigInt, return _primValue_.
632 | 1. Return ToNumber(_primValue_).
633 |
634 |
635 |
636 |
637 | RequireObjectCoercible ( _argument_ )
638 | The abstract operation RequireObjectCoercible throws an error if _argument_ is a value that cannot be converted to an Object using ToObject. It is defined by :
639 |
640 |
641 |
642 |
643 | |
644 | Argument Type
645 | |
646 |
647 | Result
648 | |
649 |
650 |
651 | |
652 | BigInt
653 | |
654 |
655 | Return _argument_.
656 | |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 | Testing and Comparison Operations
666 |
667 | SameValue ( _x_, _y_ )
668 | The internal comparison abstract operation SameValue(_x_, _y_), where _x_ and _y_ are ECMAScript language values, produces *true* or *false*. Such a comparison is performed as follows:
669 |
670 | 1. If Type(_x_) is different from Type(_y_), return *false*.
671 | 1. If Type(_x_) is Number or BigInt, then
672 | 1. If _x_ is *NaN* and _y_ is *NaN*, return *true*.
673 | 1. If _x_ is *+0* and _y_ is *-0*, return *false*.
674 | 1. If _x_ is *-0* and _y_ is *+0*, return *false*.
675 | 1. If _x_ is the same Number value as _y_, return *true*.
676 | 1. Return *false*.
677 | 1. Return ! Type(_x_)::sameValue(_x_, _y_).
678 | 1. Return SameValueNonNumberNumeric(_x_, _y_).
679 |
680 | The previous Number-related contents of this algorithm will be moved into Number::sameValue.
681 |
682 |
683 |
684 |
685 | SameValueZero ( _x_, _y_ )
686 | The internal comparison abstract operation SameValueZero(_x_, _y_), where _x_ and _y_ are ECMAScript language values, produces *true* or *false*. Such a comparison is performed as follows:
687 |
688 | 1. If Type(_x_) is different from Type(_y_), return *false*.
689 | 1. If Type(_x_) is Number or BigInt, then
690 | 1. If _x_ is *NaN* and _y_ is *NaN*, return *true*.
691 | 1. If _x_ is *+0* and _y_ is *-0*, return *true*.
692 | 1. If _x_ is *-0* and _y_ is *+0*, return *true*.
693 | 1. If _x_ is the same Number value as _y_, return *true*.
694 | 1. Return *false*.
695 | 1. Return ! Type(_x_)::sameValueZero(_x_, _y_).
696 | 1. Return SameValueNonNumberNumeric(_x_, _y_).
697 |
698 | The previous Number-related contents of this algorithm will be moved into Number::sameValueZero.
699 |
700 |
701 |
702 | SameValueNonNumberNumeric ( _x_, _y_ )
703 | The internal comparison abstract operation SameValueNonNumeric(_x_, _y_), where neither _x_ nor _y_ are numeric type values, produces *true* or *false*. Such a comparison is performed as follows:
704 |
705 | 1. Assert: Type(_x_) is not Number or BigInt.
706 | 1. Assert: Type(_x_) is the same as Type(_y_).
707 | 1. If Type(_x_) is Undefined, return *true*.
708 | 1. If Type(_x_) is Null, return *true*.
709 | 1. If Type(_x_) is String, then
710 | 1. If _x_ and _y_ are exactly the same sequence of code units (same length and same code units at corresponding indices), return *true*; otherwise, return *false*.
711 | 1. If Type(_x_) is Boolean, then
712 | 1. If _x_ and _y_ are both *true* or both *false*, return *true*; otherwise, return *false*.
713 | 1. If Type(_x_) is Symbol, then
714 | 1. If _x_ and _y_ are both the same Symbol value, return *true*; otherwise, return *false*.
715 | 1. If _x_ and _y_ are the same Object value, return *true*. Otherwise, return *false*.
716 |
717 |
718 |
719 |
720 |
721 | Abstract Relational Comparison
722 | The comparison _x_ < _y_, where _x_ and _y_ are values, produces *true*, *false*, or *undefined* (which indicates that at least one operand is *NaN*). In addition to _x_ and _y_ the algorithm takes a Boolean flag named _LeftFirst_ as a parameter. The flag is used to control the order in which operations with potentially visible side-effects are performed upon _x_ and _y_. It is necessary because ECMAScript specifies left to right evaluation of expressions. The default value of _LeftFirst_ is *true* and indicates that the _x_ parameter corresponds to an expression that occurs to the left of the _y_ parameter's corresponding expression. If _LeftFirst_ is *false*, the reverse is the case and operations must be performed upon _y_ before _x_. Such a comparison is performed as follows:
723 |
724 | 1. If the _LeftFirst_ flag is *true*, then
725 | 1. Let _px_ be ? ToPrimitive(_x_, hint Number).
726 | 1. Let _py_ be ? ToPrimitive(_y_, hint Number).
727 | 1. Else the order of evaluation needs to be reversed to preserve left to right evaluation,
728 | 1. Let _py_ be ? ToPrimitive(_y_, hint Number).
729 | 1. Let _px_ be ? ToPrimitive(_x_, hint Number).
730 | 1. If both _px_ and _py_ are Strings, then
731 | 1. If _py_ is a prefix of _px_, return *false*. (A String value _p_ is a prefix of String value _q_ if _q_ can be the result of concatenating _p_ and some other String _r_. Note that any String is a prefix of itself, because _r_ may be the empty String.)
732 | 1. If _px_ is a prefix of _py_, return *true*.
733 | 1. Let _k_ be the smallest nonnegative integer such that the code unit at index _k_ within _px_ is different from the code unit at index _k_ within _py_. (There must be such a _k_, for neither String is a prefix of the other.)
734 | 1. Let _m_ be the integer that is the code unit at index _k_ within _px_.
735 | 1. Let _n_ be the integer that is the code unit at index _k_ within _py_.
736 | 1. If _m_ < _n_, return *true*. Otherwise, return *false*.
737 | 1. Else,
738 | 1. Let _nx_ be ? ToNumber(_px_). Because _px_ and _py_ are primitive values evaluation order is not important.
739 | 1. Let _ny_ be ? ToNumber(_py_).
740 | 1. If _nx_ is *NaN*, return *undefined*.
741 | 1. If _ny_ is *NaN*, return *undefined*.
742 | 1. If _nx_ and _ny_ are the same Number value, return *false*.
743 | 1. If _nx_ is *+0* and _ny_ is *-0*, return *false*.
744 | 1. If _nx_ is *-0* and _ny_ is *+0*, return *false*.
745 | 1. If _nx_ is *+∞*, return *false*.
746 | 1. If _ny_ is *+∞*, return *true*.
747 | 1. If _ny_ is *-∞*, return *false*.
748 | 1. If _nx_ is *-∞*, return *true*.
749 | 1. If the mathematical value of _nx_ is less than the mathematical value of _ny_ —note that these mathematical values are both finite and not both zero—return *true*. Otherwise, return *false*.
750 | 1. If Type(_px_) is BigInt and Type(_py_) is String, then
751 | 1. Let _ny_ be StringToBigInt(_py_).
752 | 1. If _ny_ is *NaN*, return *undefined*.
753 | 1. Return BigInt::lessThan(_px_, _ny_).
754 | 1. If Type(_px_) is String and Type(_py_) is BigInt, then
755 | 1. Let _nx_ be StringToBigInt(_px_).
756 | 1. If _nx_ is *NaN*, return *undefined*.
757 | 1. Return BigInt::lessThan(_nx_, _py_).
758 | 1. Let _nx_ be ? ToNumeric(_px_). NOTE: Because _px_ and _py_ are primitive values evaluation order is not important.
759 | 1. Let _ny_ be ? ToNumeric(_py_).
760 | 1. If Type(_nx_) is the same as Type(_ny_), return Type(_nx_)::lessThan(_nx_, _ny_).
761 | 1. Assert: Type(_nx_) is BigInt and Type(_ny_) is Number, or Type(_nx_) is Number and Type(_ny_) is BigInt.
762 | 1. If _nx_ or _ny_ is *NaN*, return *undefined*.
763 | 1. If _nx_ is *-∞* or _ny_ is *+∞*, return *true*.
764 | 1. If _nx_ is *+∞* or _ny_ is *-∞*, return *false*.
765 | 1. If the mathematical value of _nx_ is less than the mathematical value of _ny_, return *true*, otherwise return *false*.
766 |
767 | The previous Number-related contents of this algorithm will be moved into Number::lessThan.
768 |
769 |
770 |
771 |
772 | Abstract Equality Comparison
773 | The comparison _x_ == _y_, where _x_ and _y_ are values, produces *true* or *false*. Such a comparison is performed as follows:
774 |
775 | 1. If Type(_x_) is the same as Type(_y_), then
776 | 1. Return the result of performing Strict Equality Comparison _x_ === _y_.
777 | 1. If _x_ is *null* and _y_ is *undefined*, return *true*.
778 | 1. If _x_ is *undefined* and _y_ is *null*, return *true*.
779 | 1. If Type(_x_) is Number and Type(_y_) is String, return the result of the comparison _x_ == ToNumber(_y_).
780 | 1. If Type(_x_) is String and Type(_y_) is Number, return the result of the comparison ToNumber(_x_) == _y_.
781 | 1. If Type(_x_) is BigInt and Type(_y_) is String, then
782 | 1. Let _n_ be StringToBigInt(_y_).
783 | 1. If _n_ is *NaN*, return *false*.
784 | 1. Return the result of the comparison _x_ == _n_.
785 | 1. If Type(_x_) is String and Type(_y_) is BigInt, return the result of the comparison _y_ == _x_.
786 | 1. If Type(_x_) is Boolean, return the result of the comparison ToNumber(_x_) == _y_.
787 | 1. If Type(_y_) is Boolean, return the result of the comparison _x_ == ToNumber(_y_).
788 | 1. If Type(_x_) is either String, Number, BigInt, or Symbol and Type(_y_) is Object, return the result of the comparison _x_ == ? ToPrimitive(_y_).
789 | 1. If Type(_x_) is Object and Type(_y_) is either String, Number, BigInt, or Symbol, return the result of the comparison ? ToPrimitive(_x_) == _y_.
790 | 1. If Type(_x_) is BigInt and Type(_y_) is Number, or if Type(_x_) is Number and Type(_y_) is BigInt, then
791 | 1. If _x_ or _y_ are any of *NaN*, *+∞*, or *-∞*, return *false*.
792 | 1. If the mathematical value of _x_ is equal to the mathematical value of _y_, return *true*, otherwise return *false*.
793 | 1. Return *false*.
794 |
795 |
796 |
797 |
798 |
799 | Strict Equality Comparison
800 | The comparison _x_ === _y_, where _x_ and _y_ are values, produces *true* or *false*. Such a comparison is performed as follows:
801 |
802 | 1. If Type(_x_) is different from Type(_y_), return *false*.
803 | 1. If Type(_x_) is Number or BigInt, then
804 | 1. If _x_ is *NaN*, return *false*.
805 | 1. If _y_ is *NaN*, return *false*.
806 | 1. If _x_ is the same Number value as _y_, return *true*.
807 | 1. If _x_ is *+0* and _y_ is *-0*, return *true*.
808 | 1. If _x_ is *-0* and _y_ is *+0*, return *true*.
809 | 1. Return *false*.
810 | 1. Return ! Type(_x_)::equal(_x_, _y_).
811 | 1. Return SameValueNonNumberNumeric(_x_, _y_).
812 |
813 | The previous Number-related contents of this algorithm will be moved into Number::equal.
814 |
815 |
816 |
817 |
818 |
819 | ECMAScript Language: Expressions
820 |
821 |
822 | Update Expressions
823 |
824 |
825 |
826 | Postfix Increment Operator
827 |
828 |
829 |
830 | Runtime Semantics: Evaluation
831 | UpdateExpression : LeftHandSideExpression `++`
832 |
833 | 1. Let _lhs_ be the result of evaluating |LeftHandSideExpression|.
834 | 1. Let _oldValue_ be ? ToNumber(? GetValue(_lhs_)).
835 | 1. Let _newValue_ be the result of adding the value 1 to _oldValue_, using the same rules as for the `+` operator (see ).
836 | 1. Let _oldValue_ be ? ToNumeric(? GetValue(_lhs_)).
837 | 1. Let _newValue_ be ? Type(_oldvalue_)::add(_oldValue_, Type(_oldValue_)::unit).
838 | 1. Perform ? PutValue(_lhs_, _newValue_).
839 | 1. Return _oldValue_.
840 |
841 |
842 |
843 |
844 |
845 |
846 | Postfix Decrement Operator
847 |
848 |
849 |
850 | Runtime Semantics: Evaluation
851 | UpdateExpression : LeftHandSideExpression `--`
852 |
853 | 1. Let _lhs_ be the result of evaluating |LeftHandSideExpression|.
854 | 1. Let _oldValue_ be ? ToNumber(? GetValue(_lhs_)).
855 | 1. Let _newValue_ be the result of subtracting the value 1 from _oldValue_, using the same rules as for the `-` operator (see ).
856 | 1. Let _oldValue_ be ? ToNumeric(? GetValue(_lhs_)).
857 | 1. Let _newValue_ be ? Type(_oldvalue_)::subtract(_oldValue_, Type(_oldValue_)::unit).
858 | 1. Perform ? PutValue(_lhs_, _newValue_).
859 | 1. Return _oldValue_.
860 |
861 |
862 |
863 |
864 |
865 |
866 | Prefix Increment Operator
867 |
868 |
869 |
870 | Runtime Semantics: Evaluation
871 | UpdateExpression : `++` UnaryExpression
872 |
873 | 1. Let _expr_ be the result of evaluating |UnaryExpression|.
874 | 1. Let _oldValue_ be ? ToNumber(? GetValue(_expr_)).
875 | 1. Let _newValue_ be the result of adding the value 1 to _oldValue_, using the same rules as for the `+` operator (see ).
876 | 1. Let _oldValue_ be ? ToNumeric(? GetValue(_expr_)).
877 | 1. Let _newValue_ be ? Type(_oldvalue_)::add(_oldValue_, Type(_oldValue_)::unit).
878 | 1. Perform ? PutValue(_expr_, _newValue_).
879 | 1. Return _newValue_.
880 |
881 |
882 |
883 |
884 |
885 |
886 | Prefix Decrement Operator
887 |
888 |
889 |
890 | Runtime Semantics: Evaluation
891 | UpdateExpression : `--` UnaryExpression
892 |
893 | 1. Let _expr_ be the result of evaluating |UnaryExpression|.
894 | 1. Let _oldValue_ be ? ToNumber(? GetValue(_expr_)).
895 | 1. Let _newValue_ be the result of subtracting the value 1 from _oldValue_, using the same rules as for the `-` operator (see ).
896 | 1. Let _oldValue_ be ? ToNumeric(? GetValue(_expr_)).
897 | 1. Let _newValue_ be ? Type(_oldvalue_)::subtract(_oldValue_, Type(_oldValue_)::unit).
898 | 1. Perform ? PutValue(_expr_, _newValue_).
899 | 1. Return _newValue_.
900 |
901 |
902 |
903 |
904 |
905 | Unary Operators
906 |
907 |
908 | The `typeof` Operator
909 |
910 |
911 |
912 | Runtime Semantics: Evaluation
913 | UnaryExpression : `typeof` UnaryExpression
914 |
915 |
916 |
917 |
918 | |
919 | Type of _val_
920 | |
921 |
922 | Result
923 | |
924 |
925 |
926 | |
927 | BigInt
928 | |
929 |
930 | `"bigint"`
931 | |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 | Unary `+` Operator
942 |
943 | The unary + operator converts its operand to Number type.
944 |
945 |
946 |
947 |
948 | Runtime Semantics: Evaluation
949 | UnaryExpression : `+` UnaryExpression
950 |
951 | 1. Let _expr_ be the result of evaluating |UnaryExpression|.
952 | 1. Return ? ToNumber(? GetValue(_expr_)).
953 |
954 | The definition here is unchanged, and still uses ToNumber rather than ToNumeric. This means that `+` will throw on BigInts. The semantics here are designed to allow expressions of the form `+x` to always return Numbers, which is necessary to preserve assumptions made by asm.js.
955 |
956 |
957 |
958 |
959 |
960 | Unary `-` Operator
961 |
962 | The unary `-` operator converts its operand to Number type and then negates it. Negating *+0* produces *-0*, and negating *-0* produces *+0*.
963 |
964 |
965 |
966 |
967 | Runtime Semantics: Evaluation
968 | UnaryExpression : `-` UnaryExpression
969 |
970 | 1. Let _expr_ be the result of evaluating |UnaryExpression|.
971 | 1. Let _oldValue_ be ? ToNumberToNumeric(? GetValue(_expr_)).
972 | 1. If _oldValue_ is *NaN*, return *NaN*.
973 | 1. Return the result of negating _oldValue_; that is, compute a Number with the same magnitude but opposite sign.
974 | 1. Let _T_ be Type(_oldValue_).
975 | 1. Return ? _T_::unaryMinus(_oldValue_).
976 |
977 |
978 |
979 |
980 |
981 |
982 | Bitwise NOT Operator ( `~` )
983 |
984 |
985 |
986 | Runtime Semantics: Evaluation
987 | UnaryExpression : `~` UnaryExpression
988 |
989 | 1. Let _expr_ be the result of evaluating |UnaryExpression|.
990 | 1. Let _oldValue_ be ? ToInt32ToNumeric(? GetValue(_expr_)).
991 | 1. Return the result of applying bitwise complement to _oldValue_. The result is a signed 32-bit integer.
992 | 1. Let _T_ be Type(_oldValue_).
993 | 1. Return ? _T_::bitwiseNOT(_oldValue_).
994 |
995 |
996 |
997 |
998 |
999 |
1000 | Exponentiation Operator
1001 |
1002 | Runtime Semantics: Evaluation
1003 |
1004 | ExponentiationExpression : UpdateExpression `**` ExponentiationExpression
1005 |
1006 |
1007 | 1. Let _left_ be the result of evaluating _UpdateExpression_.
1008 | 1. Let _leftValue_ be ? GetValue(_left_).
1009 | 1. Let _right_ be the result of evaluating _ExponentiationExpression_.
1010 | 1. Let _rightValue_ be ? GetValue(_right_).
1011 | 1. Let _base_ be ? ToNumberToNumeric(_leftValue_).
1012 | 1. Let _exponent_ be ? ToNumberToNumeric(_rightValue_).
1013 | 1. Return the result of Applying the ** operator with _base_ and _exponent_ as specified in .
1014 | 1. If Type(_base_) is different from Type(_exponent_), throw a *TypeError* exception.
1015 | 1. Return ? Type(_base_)::exponentiate(_base_, _exponent_).
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 | Multiplicative Operators
1023 |
1024 |
1025 | Runtime Semantics: Evaluation
1026 | MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
1027 |
1028 | 1. Let _left_ be the result of evaluating |MultiplicativeExpression|.
1029 | 1. Let _leftValue_ be ? GetValue(_left_).
1030 | 1. Let _right_ be the result of evaluating |ExponentiationExpression|.
1031 | 1. Let _rightValue_ be ? GetValue(_right_).
1032 | 1. Let _lnum_ be ? ToNumberToNumeric(_leftValue_).
1033 | 1. Let _rnum_ be ? ToNumberToNumeric(_rightValue_).
1034 | 1. Return the result of applying the |MultiplicativeOperator| (`*`, `/`, or `%`) to _lnum_ and _rnum_ as specified in , , or .
1035 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1036 | 1. Let _T_ be Type(_lnum_).
1037 | 1. If |MultiplicativeOperator| is `*`, return _T_::multiply(_lnum_, _rnum_).
1038 | 1. If |MultiplicativeOperator| is `/`, return _T_::divide(_lnum_, _rnum_).
1039 | 1. Otherwise, |MultiplicativeOperator| is `%`; return _T_::remainder(_lnum_, _rnum_).
1040 |
1041 |
1042 |
1043 |
1044 |
1045 |
1046 | Additive Operators
1047 |
1048 | The Addition Operator ( `+` )
1049 |
1050 | The addition operator either performs string concatenation or numeric addition.
1051 |
1052 |
1053 |
1054 |
1055 | Runtime Semantics: Evaluation
1056 | AdditiveExpression : AdditiveExpression `+` MultiplicativeExpression
1057 |
1058 | 1. Let _lref_ be the result of evaluating |AdditiveExpression|.
1059 | 1. Let _lval_ be ? GetValue(_lref_).
1060 | 1. Let _rref_ be the result of evaluating |MultiplicativeExpression|.
1061 | 1. Let _rval_ be ? GetValue(_rref_).
1062 | 1. Let _lprim_ be ? ToPrimitive(_lval_).
1063 | 1. Let _rprim_ be ? ToPrimitive(_rval_).
1064 | 1. If Type(_lprim_) is String or Type(_rprim_) is String, then
1065 | 1. Let _lstr_ be ? ToString(_lprim_).
1066 | 1. Let _rstr_ be ? ToString(_rprim_).
1067 | 1. Return the string-concatenation of _lstr_ and _rstr_.
1068 | 1. Let _lnum_ be ? ToNumberToNumeric(_lprim_).
1069 | 1. Let _rnum_ be ? ToNumberToNumeric(_rprim_).
1070 | 1. Return the result of applying the addition operation to _lnum_ and _rnum_. See the Note below .
1071 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1072 | 1. Let _T_ be Type(_lnum_).
1073 | 1. Return _T_::add(_lnum_, _rnum_).
1074 |
1075 |
1076 | No hint is provided in the calls to ToPrimitive in steps 5 and 6. All standard objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given. Exotic objects may handle the absence of a hint in some other manner.
1077 |
1078 |
1079 | Step 7 differs from step 5 of the Abstract Relational Comparison algorithm, by using the logical-or operation instead of the logical-and operation.
1080 |
1081 |
1082 |
1083 |
1084 |
1085 |
1086 | The Subtraction Operator ( `-` )
1087 |
1088 |
1089 |
1090 | Runtime Semantics: Evaluation
1091 | AdditiveExpression : AdditiveExpression `-` MultiplicativeExpression
1092 |
1093 | 1. Let _lref_ be the result of evaluating |AdditiveExpression|.
1094 | 1. Let _lval_ be ? GetValue(_lref_).
1095 | 1. Let _rref_ be the result of evaluating |MultiplicativeExpression|.
1096 | 1. Let _rval_ be ? GetValue(_rref_).
1097 | 1. Let _lnum_ be ? ToNumberToNumeric(_lval_).
1098 | 1. Let _rnum_ be ? ToNumberToNumeric(_rval_).
1099 | 1. Return the result of applying the subtraction operation to _lnum_ and _rnum_. See the note below .
1100 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1101 | 1. Let _T_ be Type(_lnum_).
1102 | 1. Return _T_::subtract(_lnum_, _rnum_).
1103 |
1104 |
1105 |
1106 |
1107 |
1108 |
1109 |
1110 | Bitwise Shift Operators
1111 |
1112 |
1113 |
1114 | The Left Shift Operator ( `<<` )
1115 |
1116 | Performs a bitwise left shift operation on the left operand by the amount specified by the right operand.
1117 |
1118 |
1119 |
1120 |
1121 | Runtime Semantics: Evaluation
1122 | ShiftExpression : ShiftExpression `<<` AdditiveExpression
1123 |
1124 | 1. Let _lref_ be the result of evaluating |ShiftExpression|.
1125 | 1. Let _lval_ be ? GetValue(_lref_).
1126 | 1. Let _rref_ be the result of evaluating |AdditiveExpression|.
1127 | 1. Let _rval_ be ? GetValue(_rref_).
1128 | 1. Let _lnum_ be ? ToInt32ToNumeric(_lval_).
1129 | 1. Let _rnum_ be ? ToUint32ToNumeric(_rval_).
1130 | 1. Let _shiftCount_ be the result of masking out all but the least significant 5 bits of _rnum_, that is, compute _rnum_ & 0x1F.
1131 | 1. Return the result of left shifting _lnum_ by _shiftCount_ bits. The result is a signed 32-bit integer.
1132 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1133 | 1. Let _T_ be Type(_lnum_).
1134 | 1. Return _T_::leftShift(_lnum_, _rnum_).
1135 |
1136 |
1137 |
1138 |
1139 |
1140 |
1141 | The Signed Right Shift Operator ( `>>` )
1142 |
1143 | Performs a sign-filling bitwise right shift operation on the left operand by the amount specified by the right operand.
1144 |
1145 |
1146 |
1147 |
1148 | Runtime Semantics: Evaluation
1149 | ShiftExpression : ShiftExpression `>>` AdditiveExpression
1150 |
1151 | 1. Let _lref_ be the result of evaluating |ShiftExpression|.
1152 | 1. Let _lval_ be ? GetValue(_lref_).
1153 | 1. Let _rref_ be the result of evaluating |AdditiveExpression|.
1154 | 1. Let _rval_ be ? GetValue(_rref_).
1155 | 1. Let _lnum_ be ? ToInt32ToNumeric(_lval_).
1156 | 1. Let _rnum_ be ? ToUint32ToNumeric(_rval_).
1157 | 1. Let _shiftCount_ be the result of masking out all but the least significant 5 bits of _rnum_, that is, compute _rnum_ & 0x1F.
1158 | 1. Return the result of performing a sign-extending right shift of _lnum_ by _shiftCount_ bits. The most significant bit is propagated. The result is a signed 32-bit integer.
1159 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1160 | 1. Let _T_ be Type(_lnum_).
1161 | 1. Return _T_::signedRightShift(_lnum_, _rnum_).
1162 |
1163 |
1164 |
1165 |
1166 |
1167 |
1168 | The Unsigned Right Shift Operator ( `>>>` )
1169 |
1170 | Performs a zero-filling bitwise right shift operation on the left operand by the amount specified by the right operand.
1171 |
1172 |
1173 |
1174 |
1175 | Runtime Semantics: Evaluation
1176 | ShiftExpression : ShiftExpression `>>>` AdditiveExpression
1177 |
1178 | 1. Let _lref_ be the result of evaluating |ShiftExpression|.
1179 | 1. Let _lval_ be ? GetValue(_lref_).
1180 | 1. Let _rref_ be the result of evaluating |AdditiveExpression|.
1181 | 1. Let _rval_ be ? GetValue(_rref_).
1182 | 1. Let _lnum_ be ? ToInt32ToNumeric(_lval_).
1183 | 1. Let _rnum_ be ? ToUint32ToNumeric(_rval_).
1184 | 1. Let _shiftCount_ be the result of masking out all but the least significant 5 bits of _rnum_, that is, compute _rnum_ & 0x1F.
1185 | 1. Return the result of performing a zero-filling right shift of _lnum_ by _shiftCount_ bits. Vacated bits are filled with zero. The result is an unsigned 32-bit integer.
1186 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1187 | 1. Let _T_ be Type(_lnum_).
1188 | 1. Return _T_::unsignedRightShift(_lnum_, _rnum_).
1189 |
1190 |
1191 |
1192 |
1193 |
1194 |
1195 |
1196 | Binary Bitwise Operators
1197 |
1198 |
1199 |
1200 | Runtime Semantics: Evaluation
1201 | The production A : A @ B, where @ is one of the bitwise operators in the productions above, is evaluated as follows:
1202 |
1203 | 1. Let _lref_ be the result of evaluating _A_.
1204 | 1. Let _lval_ be ? GetValue(_lref_).
1205 | 1. Let _rref_ be the result of evaluating _B_.
1206 | 1. Let _rval_ be ? GetValue(_rref_).
1207 | 1. Let _lnum_ be ? ToInt32ToNumeric(_lval_).
1208 | 1. Let _rnum_ be ? ToUint32ToNumeric(_rval_).
1209 | 1. If Type(_lnum_) is different from Type(_rnum_), throw a *TypeError* exception.
1210 | 1. Let _T_ be Type(_lnum_).
1211 | 1. If @ is `&`, return _T_::bitwiseAND(_lnum_, _rnum_).
1212 | 1. If @ is `|`, return _T_::bitwiseOR(_lnum_, _rnum_).
1213 | 1. Otherwise, @ is `^`; return _T_::bitwiseXOR(_lnum_, _rnum_).
1214 |
1215 |
1216 |
1217 |
1218 |
1219 |
1220 | BigInt Objects
1221 |
1222 | The BigInt Constructor
1223 | The BigInt constructor is the %BigInt% intrinsic object and the initial value of the `BigInt` property of the global object. When `BigInt` is called as a function, it performs a type conversion.
1224 |
1225 | The `BigInt` constructor is not intended to be used with the `new` operator or to be subclassed. It may be used as the value of an `extends` clause of a class definition but a `super` call to the `BigInt` constructor will cause an exception.
1226 |
1227 |
1228 | IsInteger ( _number_ )
1229 |
1230 | 1. Assert: Type(_number_) is Number.
1231 | 1. If _number_ is *NaN*, *+∞*, or *-∞*, return *false*.
1232 | 1. Let _integer_ be ! ToInteger(_number_).
1233 | 1. If ! SameValueZero(_integer_, _number_) is *false*, return *false*.
1234 | 1. Otherwise, return *true*.
1235 |
1236 |
1237 |
1238 |
1239 | NumberToBigInt ( _number_ )
1240 |
1241 | 1. Assert: Type(_number_) is Number.
1242 | 1. If IsInteger(_number_) is *false*, throw a *RangeError* exception.
1243 | 1. Return a BigInt representing the mathematical value of _number_.
1244 |
1245 |
1246 |
1247 |
1248 | BigInt ( _value_ )
1249 | When `BigInt` is called with argument _value_, the following steps are taken:
1250 |
1251 | 1. If NewTarget is not *undefined*, throw a *TypeError* exception.
1252 | 1. Let _prim_ be ? ToPrimitive(_value_, hint Number).
1253 | 1. If Type(_prim_) is Number, return ? NumberToBigInt(_prim_).
1254 | 1. Otherwise, return ? ToBigInt(_value_).
1255 |
1256 |
1257 |
1258 |
1259 |
1260 | Properties of the BigInt Constructor
1261 | The value of the [[Prototype]] internal slot of the BigInt constructor is the intrinsic object %FunctionPrototype%.
1262 | The BigInt constructor has the following properties:
1263 |
1264 |
1265 |
1266 | BigInt.asUintN ( _bits_, _bigint_ )
1267 | When the `BigInt.asUintN` function is called with two arguments _bits_ and _bigint_, the following steps are taken:
1268 |
1269 | 1. Let _bits_ be ? ToIndex(_bits_).
1270 | 1. Let _bigint_ be ? ToBigInt(_bigint_).
1271 | 1. Return a BigInt representing _bigint_ modulo 2_bits_.
1272 |
1273 |
1274 |
1275 |
1276 |
1277 | BigInt.asIntN ( _bits_, _bigint_ )
1278 | When the `BigInt.asIntN` is called with two arguments _bits_ and _bigint_, the following steps are taken:
1279 |
1280 | 1. Let _bits_ be ? ToIndex(_bits_).
1281 | 1. Let _bigint_ be ? ToBigInt(_bigint_).
1282 | 1. Let _mod_ be a BigInt representing _bigint_ modulo 2_bits_.
1283 | 1. If _mod_ ≥ 2_bits_ - 1, return _mod_ - 2_bits_; otherwise, return _mod_.
1284 |
1285 |
1286 |
1287 |
1288 | BigInt.prototype
1289 | The initial value of `BigInt.prototype` is the intrinsic object %BigIntPrototype%.
1290 | This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }.
1291 |
1292 |
1293 |
1294 |
1295 | Properties of the BigInt Prototype Object
1296 | The BigInt prototype object is the intrinsic object %BigIntPrototype%. The BigInt prototype object is an ordinary object. The BigInt prototype is not a BigInt object; it does not have a [[BigIntData]] internal slot.
1297 | The value of the [[Prototype]] internal slot of the BigInt prototype object is the intrinsic object %ObjectPrototype%.
1298 | The abstract operation thisBigIntValue(_value_) performs the following steps:
1299 |
1300 | 1. If Type(_value_) is BigInt, return _value_.
1301 | 1. If Type(_value_) is Object and _value_ has a [[BigIntData]] internal slot, then
1302 | 1. Assert: Type(_value_.[[BigIntData]]) is BigInt.
1303 | 1. Return _value_.[[BigIntData]].
1304 | 1. Throw a *TypeError* exception.
1305 |
1306 | The phrase “this BigInt value” within the specification of a method refers to the result returned by calling the abstract operation thisBigIntValue with the *this* value of the method invocation passed as the argument.
1307 |
1308 |
1309 |
1310 | BigInt.prototype.constructor
1311 | The initial value of `BigInt.prototype.constructor` is the intrinsic object %BigInt%.
1312 |
1313 |
1314 |
1315 |
1316 | BigInt.prototype.toLocaleString ( [ _reserved1_ [ , _reserved2_ ] ] )
1317 | An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the `BigInt.prototype.toLocaleString` method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of the `toLocaleString` method is used.
1318 | Produces a String value that represents this BigInt value formatted according to the conventions of the host environment's current locale. This function is implementation-dependent, and it is permissible, but not encouraged, for it to return the same thing as `toString`.
1319 | The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.
1320 |
1321 |
1322 |
1323 |
1324 | BigInt.prototype.toString ( [ _radix_ ] )
1325 |
1326 | The optional _radix_ should be an integer value in the inclusive range 2 to 36. If _radix_ not present or is *undefined* the Number 10 is used as the value of _radix_.
1327 |
1328 | The following steps are performed:
1329 |
1330 | 1. Let _x_ be ? thisBigIntValue(*this* value).
1331 | 1. If _radix_ is not present, let _radixNumber_ be 10.
1332 | 1. Else if _radix_ is *undefined*, let _radixNumber_ be 10.
1333 | 1. Else, let _radixNumber_ be ? ToInteger(_radix_).
1334 | 1. If _radixNumber_ < 2 or _radixNumber_ > 36, throw a *RangeError* exception.
1335 | 1. If _radixNumber_ = 10, return ! ToString(_x_).
1336 | 1. Return the String representation of this Number value using the radix specified by _radixNumber_. Letters `a`-`z` are used for digits with values 10 through 35. The precise algorithm is implementation-dependent, however the algorithm should be a generalization of that specified in .
1337 |
1338 | The `toString` function is not generic; it throws a *TypeError* exception if its *this* value is not a BigInt or a BigInt object. Therefore, it cannot be transferred to other kinds of objects for use as a method.
1339 |
1340 |
1341 |
1342 |
1343 | BigInt.prototype.valueOf ( )
1344 |
1345 | 1. Return ? thisBigIntValue(*this* value).
1346 |
1347 |
1348 |
1349 |
1350 | BigInt.prototype [ @@toStringTag ]
1351 | The initial value of the @@toStringTag property is the String value `"BigInt"`.
1352 | This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.
1353 |
1354 |
1355 |
1356 |
1357 |
1358 | Modified algorithms
1359 |
1360 |
1361 | Runtime Semantics: SerializeJSONProperty ( _key_, _holder_ )
1362 | The abstract operation SerializeJSONProperty with arguments _key_, and _holder_ has access to _ReplacerFunction_ from the invocation of the `stringify` method. Its algorithm is as follows:
1363 |
1364 | 1. Let _value_ be ? Get(_holder_, _key_).
1365 | 1. If Type(_value_) is Object or BigInt, then
1366 | 1. Let _toJSON_ be ? GetGetV(_value_, `"toJSON"`).
1367 | 1. If IsCallable(_toJSON_) is *true*, then
1368 | 1. Set _value_ to ? Call(_toJSON_, _value_, « _key_ »).
1369 | 1. If _ReplacerFunction_ is not *undefined*, then
1370 | 1. Set _value_ to ? Call(_ReplacerFunction_, _holder_, « _key_, _value_ »).
1371 | 1. If Type(_value_) is Object, then
1372 | 1. If _value_ has a [[NumberData]] internal slot, then
1373 | 1. Set _value_ to ? ToNumber(_value_).
1374 | 1. Else if _value_ has a [[StringData]] internal slot, then
1375 | 1. Set _value_ to ? ToString(_value_).
1376 | 1. Else if _value_ has a [[BooleanData]] internal slot, then
1377 | 1. Set _value_ to _value_.[[BooleanData]].
1378 | 1. Else if _value_ has a [[BigIntData]] internal slot, then
1379 | 1. Set _value_ to _value_.[[BigIntData]].
1380 | 1. If _value_ is *null*, return `"null"`.
1381 | 1. If _value_ is *true*, return `"true"`.
1382 | 1. If _value_ is *false*, return `"false"`.
1383 | 1. If Type(_value_) is String, return QuoteJSONString(_value_).
1384 | 1. If Type(_value_) is Number, then
1385 | 1. If _value_ is finite, return ! ToString(_value_).
1386 | 1. Else, return `"null"`.
1387 | 1. If Type(_value_) is BigInt, throw a *TypeError* exception.
1388 | 1. If Type(_value_) is Object and IsCallable(_value_) is *false*, then
1389 | 1. Let _isArray_ be ? IsArray(_value_).
1390 | 1. If _isArray_ is *true*, return ? SerializeJSONArray(_value_).
1391 | 1. Else, return ? SerializeJSONObject(_value_).
1392 | 1. Return *undefined*.
1393 |
1394 |
1395 |
1396 |
1397 |
1398 | Number ( _value_ )
1399 | When `Number` is called with argument _value_, the following steps are taken:
1400 |
1401 | 1. If no arguments were passed to this function invocation, let _n_ be *+0*.
1402 | 1. Else,
1403 | 1. Let _prim_ be ? ToNumeric(_value_).
1404 | 1. If Type(_prim_) is BigInt, let _n_ be the Number value for _prim_.
1405 | 1. Otherwise, let _n_ be _prim_.
1406 | 1. If NewTarget is *undefined*, return _n_.
1407 | 1. Let _O_ be ? OrdinaryCreateFromConstructor(NewTarget, `"%NumberPrototype%"`, « [[NumberData]] »).
1408 | 1. Set _O_.[[NumberData]] to _n_.
1409 | 1. Return _O_.
1410 |
1411 | See in the second-to-last paragraph for the definition of the phrase "The Number value for _prim_".
1412 | That paragraph should possibly be refactored into a separate abstract operation; see this bug for more discussion about the integration of different numeric types and casting operations between them.
1413 |
1414 |
1415 |
1416 |
1417 | Math.pow ( _base_, _exponent_ )
1418 |
1419 | 1. Let _base_ be ? ToNumber(_base_).
1420 | 1. Let _exponent_ be ? ToNumber(_exponent_).
1421 | 1. Return Number::exponentiate(_base_, _exponent_).
1422 |
1423 |
1424 |
1425 |
1426 |
1427 | TypedArrays and DataViews
1428 | BigInt is integrated into TypedArray, DataView, SharedArrayBuffer and Atomics by providing Int64 and Uint64 access as represented by BigInts on the ECMAScript side.
1429 |
1430 |
1431 | TypedArray Objects
1432 |
1433 |
1434 |
1435 |
1436 | |
1437 | Constructor Name and Intrinsic
1438 | |
1439 |
1440 | Element Type
1441 | |
1442 |
1443 | Element Size
1444 | |
1445 |
1446 | Conversion Operation
1447 | |
1448 |
1449 | Description
1450 | |
1451 |
1452 | Equivalent C Type
1453 | |
1454 |
1455 |
1456 |
1457 | BigInt64Array
1458 |
1459 | %BigInt64Array%
1460 | |
1461 |
1462 | BigInt64
1463 | |
1464 |
1465 | 8
1466 | |
1467 |
1468 | ToBigInt64
1469 | |
1470 |
1471 | 64-bit two's complement signed integer
1472 | |
1473 |
1474 | signed long long
1475 | |
1476 |
1477 |
1478 |
1479 | BigUint64Array
1480 |
1481 | %BigUint64Array%
1482 | |
1483 |
1484 | BigUint64
1485 | |
1486 |
1487 | 8
1488 | |
1489 |
1490 | ToBigUint64
1491 | |
1492 |
1493 | 64-bit unsigned integer
1494 | |
1495 |
1496 | unsigned long long
1497 | |
1498 |
1499 |
1500 |
1501 |
1502 |
1503 |
1504 |
1505 | StringToBigInt ( _argument_ )
1506 | Apply the algorithm in with the following changes:
1507 |
1508 | - Replace the |StrUnsignedDecimalLiteral| production with |DecimalDigits| to not allow *Infinity*, decimal points, or exponents.
1509 | - If the MV is *NaN*, return *NaN*, otherwise return the BigInt which exactly corresponds to the MV, rather than rounding to a Number.
1510 |
1511 | StringToBigInt(`""`) is `0n` according to the logic in .
1512 |
1513 |
1514 |
1515 | ToBigInt ( _argument_ )
1516 | The abstract operation ToBigInt converts its argument _argument_ to a BigInt value, or throws if an implicit conversion from Number would be required.
1517 |
1518 | 1. Let _prim_ be ? ToPrimitive(_argument_, hint Number).
1519 | 1. Return the value that _prim_ corresponds to in .
1520 |
1521 |
1522 |
1523 |
1524 |
1525 | |
1526 | Argument Type
1527 | |
1528 |
1529 | Result
1530 | |
1531 |
1532 |
1533 | |
1534 | Undefined
1535 | |
1536 |
1537 | Throw a *TypeError* exception.
1538 | |
1539 |
1540 |
1541 | |
1542 | Null
1543 | |
1544 |
1545 | Throw a *TypeError* exception.
1546 | |
1547 |
1548 |
1549 | |
1550 | Boolean
1551 | |
1552 |
1553 | Return `1n` if _prim_ is *true* and `0n` if _prim_ is *false*.
1554 | |
1555 |
1556 |
1557 | |
1558 | BigInt
1559 | |
1560 |
1561 | Return _prim_.
1562 | |
1563 |
1564 |
1565 | |
1566 | Number
1567 | |
1568 |
1569 | Throw a *TypeError* exception.
1570 | |
1571 |
1572 |
1573 | |
1574 | String
1575 | |
1576 |
1577 |
1578 | 1. Let _n_ be StringToBigInt(_prim_).
1579 | 1. If _n_ is *NaN*, throw a *SyntaxError* exception.
1580 | 1. Return _n_.
1581 |
1582 | |
1583 |
1584 |
1585 | |
1586 | Symbol
1587 | |
1588 |
1589 | Throw a *TypeError* exception.
1590 | |
1591 |
1592 |
1593 |
1594 |
1595 |
1596 |
1597 |
1598 | ToBigInt64 ( _argument_ )
1599 | The abstract operation ToBigInt64 converts _argument_ to one of 264 integer values in the range -263 through 263-1, inclusive. This abstract operation functions as follows:
1600 |
1601 | 1. Let _n_ be ? ToBigInt(_argument_).
1602 | 1. Let _int64bit_ be _n_ modulo 264.
1603 | 1. If _int64bit_ ≥ 263, return _int64bit_ - 264; otherwise return _int64bit_.
1604 |
1605 |
1606 |
1607 |
1608 | ToBigUint64 ( _argument_ )
1609 | The abstract operation ToBigUint64 converts _argument_ to one of 264 integer values in the range 0 through 264-1, inclusive. This abstract operation functions as follows:
1610 |
1611 | 1. Let _n_ be ? ToBigInt(_argument_).
1612 | 1. Let _int64bit_ be _n_ modulo 264.
1613 | 1. Return _int64bit_.
1614 |
1615 |
1616 |
1617 |
1618 | RawBytesToNumberNumeric( _type_, _rawBytes_, _isLittleEndian_ )
1619 | The abstract operation RawBytesToNumberNumeric takes three parameters, a String _type_, a List _rawBytes_, and a Boolean _isLittleEndian_. This operation performs the following steps:
1620 |
1621 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for Element Type _type_.
1622 | 1. If _isLittleEndian_ is *false*, reverse the order of the elements of _rawBytes_.
1623 | 1. If _type_ is `"Float32"`, then
1624 | 1. Let _value_ be the byte elements of _rawBytes_ concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2008 binary32 value.
1625 | 1. If _value_ is an IEEE 754-2008 binary32 NaN value, return the *NaN* Number value.
1626 | 1. Return the Number value that corresponds to _value_.
1627 | 1. If _type_ is `"Float64"`, then
1628 | 1. Let _value_ be the byte elements of _rawBytes_ concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2008 binary64 value.
1629 | 1. If _value_ is an IEEE 754-2008 binary64 NaN value, return the *NaN* Number value.
1630 | 1. Return the Number value that corresponds to _value_.
1631 | 1. If the first code unit of _type_ is `"U"` or _type_ is `"BigUint64"`, then
1632 | 1. Let _intValue_ be the byte elements of _rawBytes_ concatenated and interpreted as a bit string encoding of an unsigned little-endian binary number.
1633 | 1. Else,
1634 | 1. Let _intValue_ be the byte elements of _rawBytes_ concatenated and interpreted as a bit string encoding of a binary little-endian two's complement number of bit length _elementSize_ × 8.
1635 | 1. If _type_ is `"BigUint64"` or `"BigInt64"`, return the BigInt value that corresponds to _intValue_.
1636 | 1. Otherwise, return the Number value that corresponds to _intValue_.
1637 |
1638 |
1639 |
1640 |
1641 | NumberNumericToRawBytes( _type_, _value_, _isLittleEndian_ )
1642 | The abstract operation NumberNumericToRawBytes takes three parameters, a String _type_, a BigInt or a Number _value_, and a Boolean _isLittleEndian_. This operation performs the following steps:
1643 |
1644 | 1. If _type_ is `"Float32"`, then
1645 | 1. Set _rawBytes_ to a List containing the 4 bytes that are the result of converting _value_ to IEEE 754-2008 binary32 format using “Round to nearest, ties to even” rounding mode. If _isLittleEndian_ is *false*, the bytes are arranged in big endian order. Otherwise, the bytes are arranged in little endian order. If _value_ is *NaN*, _rawValue_ may be set to any implementation chosen IEEE 754-2008 binary32 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable *NaN* value.
1646 | 1. Else if _type_ is `"Float64"`, then
1647 | 1. Set _rawBytes_ to a List containing the 8 bytes that are the IEEE 754-2008 binary64 format encoding of _value_. If _isLittleEndian_ is *false*, the bytes are arranged in big endian order. Otherwise, the bytes are arranged in little endian order. If _value_ is *NaN*, _rawValue_ may be set to any implementation chosen IEEE 754-2008 binary64 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable *NaN* value.
1648 | 1. Else,
1649 | 1. Let _n_ be the Number value of the Element Size specified in for Element Type _type_.
1650 | 1. Let _convOp_ be the abstract operation named in the Conversion Operation column in for Element Type _type_.
1651 | 1. Let _intValue_ be _convOp_(_value_) treated as a mathematical value, whether the result is a BigInt or Number.
1652 | 1. If _intValue_ ≥ 0, then
1653 | 1. Let _rawBytes_ be a List containing the _n_-byte binary encoding of _intValue_. If _isLittleEndian_ is *false*, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.
1654 | 1. Else,
1655 | 1. Let _rawBytes_ be a List containing the _n_-byte binary two's complement encoding of _intValue_. If _isLittleEndian_ is *false*, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.
1656 | 1. Return _rawBytes_.
1657 |
1658 |
1659 |
1660 |
1661 |
1662 | IntegerIndexedElementSet ( _O_, _index_, _value_ )
1663 | The abstract operation IntegerIndexedElementSet with arguments _O_, _index_, and _value_ performs the following steps:
1664 |
1665 | 1. Assert: Type(_index_) is Number.
1666 | 1. Assert: _O_ is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and [[TypedArrayName]] internal slots.
1667 | 1. Let _arrayTypeName_ be the String value of _O_.[[TypedArrayName]].
1668 | 1. Let _elementType_ be the String value of the Element Type value in for _arrayTypeName_.
1669 | 1. If _arrayTypeName_ is `"BigUint64Array"` or `"BigInt64Array"`, let _numValue_ be ? ToBigInt(_value_).
1670 | 1. Otherwise, let _numValue_ be ? ToNumber(_value_).
1671 | 1. Let _buffer_ be _O_.[[ViewedArrayBuffer]].
1672 | 1. If IsDetachedBuffer(_buffer_) is *true*, throw a *TypeError* exception.
1673 | 1. If IsInteger(_index_) is *false*, return *false*.
1674 | 1. If _index_ = *-0*, return *false*.
1675 | 1. Let _length_ be _O_.[[ArrayLength]].
1676 | 1. If _index_ < 0 or _index_ ≥ _length_, return *false*.
1677 | 1. Let _offset_ be _O_.[[ByteOffset]].
1678 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for _arrayTypeName_.
1679 | 1. Let _indexedPosition_ be (_index_ × _elementSize_) + _offset_.
1680 | 1. Perform SetValueInBuffer(_buffer_, _indexedPosition_, _elementType_, _numValue_, *true*, `"Unordered"`).
1681 | 1. Return *true*.
1682 |
1683 |
1684 |
1685 |
1686 |
1687 | SetValueInBuffer ( _arrayBuffer_, _byteIndex_, _type_, _value_, _isTypedArray_, _order_ [ , _isLittleEndian_ ] )
1688 | The abstract operation SetValueInBuffer takes seven parameters, an ArrayBuffer or SharedArrayBuffer _arrayBuffer_, an integer _byteIndex_, a String _type_, a Number _value_, a Boolean _isTypedArray_, a String _order_, and optionally a Boolean _isLittleEndian_. This operation performs the following steps:
1689 |
1690 | 1. Assert: IsDetachedBuffer(_arrayBuffer_) is *false*.
1691 | 1. Assert: There are sufficient bytes in _arrayBuffer_ starting at _byteIndex_ to represent a value of _type_.
1692 | 1. Assert: _byteIndex_ is an integer value ≥ 0.
1693 | 1. Assert: Type(_value_) is BigInt if _type_ is `"BigInt64"` or `"BigUint64"`; otherwise, Type(_value_) is Number.
1694 | 1. Let _block_ be _arrayBuffer_.[[ArrayBufferData]].
1695 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for Element Type _type_.
1696 | 1. If _isLittleEndian_ is not present, set _isLittleEndian_ to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
1697 | 1. Let _rawBytes_ be NumberNumericToRawBytes(_type_, _value_, _isLittleEndian_).
1698 | 1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then
1699 | 1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1700 | 1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
1701 | 1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"`, or if _type_ is `"BigInt64"` or `"BigUint64"` and _order_ is not `"Init"` or `"Unordered"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.
1702 | 1. Append WriteSharedMemory{ [[Order]]: _order_, [[NoTear]]: _noTear_, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_, [[Payload]]: _rawBytes_ } to _eventList_.
1703 | 1. Else, store the individual bytes of _rawBytes_ into _block_, in order, starting at _block_[_byteIndex_].
1704 | 1. Return NormalCompletion(*undefined*).
1705 |
1706 | BigInt64 and BigUint64, like Float64, are excluded from the list of types which experience noTear writes. That is, non-atomic writes may be observed in a partially completed state.
1707 |
1708 |
1709 |
1710 |
1711 | GetValueFromBuffer ( _arrayBuffer_, _byteIndex_, _type_, _isTypedArray_, _order_ [ , _isLittleEndian_ ] )
1712 | The abstract operation GetValueFromBuffer takes six parameters, an ArrayBuffer or SharedArrayBuffer _arrayBuffer_, an integer _byteIndex_, a String _type_, a Boolean _isTypedArray_, a String _order_, and optionally a Boolean _isLittleEndian_. This operation performs the following steps:
1713 |
1714 | 1. Assert: IsDetachedBuffer(_arrayBuffer_) is *false*.
1715 | 1. Assert: There are sufficient bytes in _arrayBuffer_ starting at _byteIndex_ to represent a value of _type_.
1716 | 1. Assert: _byteIndex_ is an integer value ≥ 0.
1717 | 1. Let _block_ be _arrayBuffer_.[[ArrayBufferData]].
1718 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for Element Type _type_.
1719 | 1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then
1720 | 1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1721 | 1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
1722 | 1. If _isTypedArray_ is *true* and _type_ is `"Int8"`, `"Uint8"`, `"Int16"`, `"Uint16"`, `"Int32"`, or `"Uint32"` or if _type_ is `"BigInt64"` or `"BigUint64"` and _order_ is not `"Init"` or `"Unordered"`, let _noTear_ be *true*; otherwise let _noTear_ be *false*.
1723 | 1. Let _rawValue_ be a List of length _elementSize_ of nondeterministically chosen byte values.
1724 | 1. NOTE: In implementations, _rawValue_ is the result of a non-atomic or atomic read instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
1725 | 1. Let _readEvent_ be ReadSharedMemory{ [[Order]]: _order_, [[NoTear]]: _noTear_, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_ }.
1726 | 1. Append _readEvent_ to _eventList_.
1727 | 1. Append Chosen Value Record { [[Event]]: _readEvent_, [[ChosenValue]]: _rawValue_ } to _execution_.[[ChosenValues]].
1728 | 1. Else, let _rawValue_ be a List of _elementSize_ containing, in order, the _elementSize_ sequence of bytes starting with _block_[_byteIndex_].
1729 | 1. If _isLittleEndian_ is not present, set _isLittleEndian_ to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
1730 | 1. Return RawBytesToNumberNumeric(_type_, _rawValue_, _isLittleEndian_).
1731 |
1732 |
1733 |
1734 |
1735 | GetModifySetValueInBuffer( _arrayBuffer_, _byteIndex_, _type_, _value_, _op_ [ , _isLittleEndian_ ] )
1736 | The abstract operation GetModifySetValueInBuffer takes six parameters, a SharedArrayBuffer _arrayBuffer_, a nonnegative integer _byteIndex_, a String _type_, a Number _value_, a semantic function _op_, and optionally a Boolean _isLittleEndian_. This operation performs the following steps:
1737 |
1738 | 1. Assert: IsSharedArrayBuffer(_arrayBuffer_) is *true*.
1739 | 1. Assert: There are sufficient bytes in _arrayBuffer_ starting at _byteIndex_ to represent a value of _type_.
1740 | 1. Assert: _byteIndex_ is an integer value ≥ 0.
1741 | 1. Assert: Type(_value_) is BigInt if _type_ is `"BigInt64"` or `"BigUint64"`; otherwise, Type(_value_) is Number.
1742 | 1. Let _block_ be _arrayBuffer_.[[ArrayBufferData]].
1743 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for Element Type _type_.
1744 | 1. If _isLittleEndian_ is not present, set _isLittleEndian_ to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
1745 | 1. Let _rawBytes_ be NumberNumericToRawBytes(_type_, _value_, _isLittleEndian_).
1746 | 1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
1747 | 1. Let _eventList_ be the [[EventList]] field of the element in _execution_.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
1748 | 1. Let _rawBytesRead_ be a List of length _elementSize_ of nondeterministically chosen byte values.
1749 | 1. NOTE: In implementations, _rawBytesRead_ is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
1750 | 1. Let _rmwEvent_ be ReadModifyWriteSharedMemory{ [[Order]]: `"SeqCst"`, [[NoTear]]: *true*, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_, [[Payload]]: _rawBytes_, [[ModifyOp]]: _op_ }.
1751 | 1. Append _rmwEvent_ to _eventList_.
1752 | 1. Append Chosen Value Record { [[Event]]: _rmwEvent_, [[ChosenValue]]: _rawBytesRead_ } to _execution_.[[ChosenValues]].
1753 | 1. Return RawBytesToNumberNumeric(_type_, _rawBytesRead_, _isLittleEndian_).
1754 |
1755 |
1756 |
1757 |
1758 | ValidateSharedIntegerTypedArray(_typedArray_ [ , _waitable_ ] )
1759 | The abstract operation ValidateSharedIntegerTypedArray takes one argument _typedArray_ and an optional Boolean _waitable_. It performs the following steps:
1760 |
1761 | 1. If _waitable_ is not present, set _waitable_ to *false*.
1762 | 1. If Type(_typedArray_) is not Object, throw a *TypeError* exception.
1763 | 1. If _typedArray_ does not have a [[TypedArrayName]] internal slot, throw a *TypeError* exception.
1764 | 1. Let _typeName_ be _typedArray_.[[TypedArrayName]].
1765 | 1. If _waitable_ is *true*, then
1766 | 1. If _typeName_ is not `"Int32Array"` or `"BigInt64Array"`, throw a *TypeError* exception.
1767 | 1. Else,
1768 | 1. If _typeName_ is not `"Int8Array"`, `"Uint8Array"`, `"Int16Array"`, `"Uint16Array"`, `"Int32Array"`, `"Uint32Array"`, `"BigUint64Array"`, or `"BigInt64Array"`, throw a *TypeError* exception.
1769 | 1. Assert: _typedArray_ has a [[ViewedArrayBuffer]] internal slot.
1770 | 1. Let _buffer_ be _typedArray_.[[ViewedArrayBuffer]].
1771 | 1. If IsSharedArrayBuffer(_buffer_) is *false*, throw a *TypeError* exception.
1772 | 1. Return _buffer_.
1773 |
1774 |
1775 |
1776 |
1777 | AtomicReadModifyWrite( _typedArray_, _index_, _value_, _op_ )
1778 | The abstract operation AtomicReadModifyWrite takes four arguments, _typedArray_, _index_, _value_, and a pure combining operation _op_. The pure combining operation _op_ takes two List of byte values arguments and returns a List of byte values. The operation atomically loads a value, combines it with another value, and stores the result of the combination. It returns the loaded value. It performs the following steps:
1779 |
1780 | 1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1781 | 1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1782 | 1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1783 | 1. If _arrayTypeName_ is `"BigUint64Array"` or `"BigInt64Array"`, let _v_ be ? ToBigInt(_v_).
1784 | 1. Otherwise, let _v_ be ? ToInteger(_value_).
1785 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for _arrayTypeName_.
1786 | 1. Let _elementType_ be the String value of the Element Type value in for _arrayTypeName_.
1787 | 1. Let _offset_ be _typedArray_.[[ByteOffset]].
1788 | 1. Let _indexedPosition_ be (_i_ × _elementSize_) + _offset_.
1789 | 1. Return GetModifySetValueInBuffer(_buffer_, _indexedPosition_, _elementType_, _v_, _op_).
1790 |
1791 |
1792 |
1793 |
1794 | Atomics.compareExchange ( _typedArray_, _index_, _expectedValue_, _replacementValue_ )
1795 | The following steps are taken:
1796 |
1797 | 1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1798 | 1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1799 | 1. If _arrayTypeName_ is `"BigUint64Array"` or `"BigInt64Array"`,
1800 | 1. Let _expected_ be ? ToBigInt(_expectedValue_).
1801 | 1. Let _replacement_ be ? ToBigInt(_replacementValue_).
1802 | 1. Otherwise,
1803 | 1. Let _expected_ be ? ToInteger(_expectedValue_).
1804 | 1. Let _replacement_ be ? ToInteger(_replacementValue_).
1805 | 1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1806 | 1. Let _elementType_ be the String value of the Element Type value in for _arrayTypeName_.
1807 | 1. Let _isLittleEndian_ be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
1808 | 1. Let _expectedBytes_ be NumberNumericToRawBytes(_elementType_, _expected_, _isLittleEndian_).
1809 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for _arrayTypeName_.
1810 | 1. Let _offset_ be _typedArray_.[[ByteOffset]].
1811 | 1. Let _indexedPosition_ be (_i_ × _elementSize_) + _offset_.
1812 | 1. Let `compareExchange` denote a semantic function of two List of byte values arguments that returns the second argument if the first argument is element-wise equal to _expectedBytes_.
1813 | 1. Return GetModifySetValueInBuffer(_buffer_, _indexedPosition_, _elementType_, _replacement_, `compareExchange`).
1814 |
1815 |
1816 |
1817 |
1818 | Atomics.isLockFree( _size_ )
1819 | The following steps are taken:
1820 |
1821 | 1. Let _n_ be ? ToInteger(_size_).
1822 | 1. Let _AR_ be the Agent Record of the surrounding agent.
1823 | 1. If _n_ equals 1, return _AR_.[[IsLockFree1]].
1824 | 1. If _n_ equals 2, return _AR_.[[IsLockFree2]].
1825 | 1. If _n_ equals 4, return *true*.
1826 | 1. If _n_ equals 8, return _AR_.[[IsLockFree8]].
1827 | 1. Return *false*.
1828 |
1829 |
1830 | `Atomics.isLockFree`() is an optimization primitive. The intuition is that if the atomic step of an atomic primitive (`compareExchange`, `load`, `store`, `add`, `sub`, `and`, `or`, `xor`, or `exchange`) on a datum of size _n_ bytes will be performed without the calling agent acquiring a lock outside the _n_ bytes comprising the datum, then `Atomics.isLockFree`(_n_) will return *true*. High-performance algorithms will use Atomics.isLockFree to determine whether to use locks or atomic operations in critical sections. If an atomic primitive is not lock-free then it is often more efficient for an algorithm to provide its own locking.
1831 | `Atomics.isLockFree`(4) always returns *true* as that can be supported on all known relevant hardware. Being able to assume this will generally simplify programs.
1832 | Regardless of the value of `Atomics.isLockFree`, all atomic operations are guaranteed to be atomic. For example, they will never have a visible operation take place in the middle of the operation (e.g., "tearing").
1833 |
1834 |
1835 |
1836 |
1837 | Atomics.wait( _typedArray_, _index_, _value_, _timeout_ )
1838 | `Atomics.wait` puts the calling agent in a wait queue and puts it to sleep until it is awoken or the sleep times out. The following steps are taken:
1839 |
1840 | 1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_, *true*).
1841 | 1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1842 | 1. If _typedArray_.[[TypedArrayName]] is `"BigInt64Array"`, let _v_ be ? ToBigInt64(_value_).
1843 | 1. Otherwise, let _v_ be ? ToInt32(_value_).
1844 | 1. Let _q_ be ? ToNumber(_timeout_).
1845 | 1. If _q_ is *NaN*, let _t_ be *+∞*, else let _t_ be max(_q_, 0).
1846 | 1. Let _B_ be AgentCanSuspend().
1847 | 1. If _B_ is *false*, throw a *TypeError* exception.
1848 | 1. Let _block_ be _buffer_.[[ArrayBufferData]].
1849 | 1. Let _offset_ be _typedArray_.[[ByteOffset]].
1850 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for _arrayTypeName_.
1851 | 1. Let _indexedPosition_ be (_i_ × 4_elementSize_) + _offset_.
1852 | 1. Let _WL_ be GetWaiterList(_block_, _indexedPosition_).
1853 | 1. Perform EnterCriticalSection(_WL_).
1854 | 1. Let _w_ be ! AtomicLoad(_typedArray_, _i_).
1855 | 1. If _v_ is not equal to _w_, then
1856 | 1. Perform LeaveCriticalSection(_WL_).
1857 | 1. Return the String `"not-equal"`.
1858 | 1. Let _W_ be AgentSignifier().
1859 | 1. Perform AddWaiter(_WL_, _W_).
1860 | 1. Let _awoken_ be Suspend(_WL_, _W_, _t_).
1861 | 1. If _awoken_ is *true*, then
1862 | 1. Assert: _W_ is not on the list of waiters in _WL_.
1863 | 1. Else,
1864 | 1. Perform RemoveWaiter(_WL_, _W_).
1865 | 1. Perform LeaveCriticalSection(_WL_).
1866 | 1. If _awoken_ is *true*, return the String `"ok"`.
1867 | 1. Return the String `"timed-out"`.
1868 |
1869 |
1870 |
1871 |
1872 | Atomics.notify( _typedArray_, _index_, _count_ )
1873 | `Atomics.notify` wakes up some agents that are sleeping in the wait queue. The following steps are taken:
1874 |
1875 | 1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_, *true*).
1876 | 1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1877 | 1. If _count_ is *undefined*, let _c_ be *+∞*.
1878 | 1. Else,
1879 | 1. Let _intCount_ be ? ToInteger(_count_).
1880 | 1. Let _c_ be max(_intCount_, 0).
1881 | 1. Let _block_ be _buffer_.[[ArrayBufferData]].
1882 | 1. Let _offset_ be _typedArray_.[[ByteOffset]].
1883 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for _arrayTypeName_.
1884 | 1. Let _indexedPosition_ be (_i_ × 4_elementSize_) + _offset_.
1885 | 1. Let _WL_ be GetWaiterList(_block_, _indexedPosition_).
1886 | 1. Let _n_ be 0.
1887 | 1. Perform EnterCriticalSection(_WL_).
1888 | 1. Let _S_ be RemoveWaiters(_WL_, _c_).
1889 | 1. Repeat, while _S_ is not an empty List,
1890 | 1. Let _W_ be the first agent in _S_.
1891 | 1. Remove _W_ from the front of _S_.
1892 | 1. Perform WakeWaiter(_WL_, _W_).
1893 | 1. Add 1 to _n_.
1894 | 1. Perform LeaveCriticalSection(_WL_).
1895 | 1. Return _n_.
1896 |
1897 |
1898 |
1899 |
1900 | Atomics.store( _typedArray_, _index_, _value_ )
1901 | The following steps are taken:
1902 |
1903 | 1. Let _buffer_ be ? ValidateSharedIntegerTypedArray(_typedArray_).
1904 | 1. Let _i_ be ? ValidateAtomicAccess(_typedArray_, _index_).
1905 | 1. If _arrayTypeName_ is `"BigUint64Array"` or `"BigInt64Array"`, let _v_ be ? ToBigInt(_value_).
1906 | 1. Otherwise, let _v_ be ? ToInteger(_value_).
1907 | 1. Let _arrayTypeName_ be _typedArray_.[[TypedArrayName]].
1908 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for _arrayTypeName_.
1909 | 1. Let _elementType_ be the String value of the Element Type value in for _arrayTypeName_.
1910 | 1. Let _offset_ be _typedArray_.[[ByteOffset]].
1911 | 1. Let _indexedPosition_ be (_i_ × _elementSize_) + _offset_.
1912 | 1. Perform SetValueInBuffer(_buffer_, _indexedPosition_, _elementType_, _v_, *true*, `"SeqCst"`).
1913 | 1. Return _v_.
1914 |
1915 |
1916 |
1917 |
1918 |
1919 | %TypedArray%.prototype.sort ( _comparefn_ )
1920 | %TypedArray%`.prototype.sort` is a distinct function that, except as described below, implements the same requirements as those of `Array.prototype.sort` as defined in . The implementation of the %TypedArray%`.prototype.sort` specification may be optimized with the knowledge that the *this* value is an object that has a fixed length and whose integer indexed properties are not sparse. The only internal methods of the *this* object that the algorithm may call are [[Get]] and [[Set]].
1921 | This function is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.
1922 | Upon entry, the following steps are performed to initialize evaluation of the `sort` function. These steps are used instead of the entry steps in :
1923 |
1924 | 1. If _comparefn_ is not *undefined* and IsCallable(_comparefn_) is *false*, throw a *TypeError* exception.
1925 | 1. Let _obj_ be the *this* value.
1926 | 1. Let _buffer_ be ? ValidateTypedArray(_obj_).
1927 | 1. Let _len_ be _obj_.[[ArrayLength]].
1928 |
1929 | The implementation-defined sort order condition for exotic objects is not applied by %TypedArray%`.prototype.sort`.
1930 | The following version of SortCompare is used by %TypedArray%`.prototype.sort`. It performs a numeric comparison rather than the string comparison used in . SortCompare has access to the _comparefn_ and _buffer_ values of the current invocation of the `sort` method.
1931 | When the TypedArray SortCompare abstract operation is called with two arguments _x_ and _y_, the following steps are taken:
1932 |
1933 | 1. Assert: Both Type(_x_) and Type(_y_) is Number or both are BigInt.
1934 | 1. If _comparefn_ is not *undefined*, then
1935 | 1. Let _v_ be ? ToNumber(? Call(_comparefn_, *undefined*, « _x_, _y_ »)).
1936 | 1. If IsDetachedBuffer(_buffer_) is *true*, throw a *TypeError* exception.
1937 | 1. If _v_ is *NaN*, return *+0*.
1938 | 1. Return _v_.
1939 | 1. If _x_ and _y_ are both *NaN*, return *+0*.
1940 | 1. If _x_ is *NaN*, return 1.
1941 | 1. If _y_ is *NaN*, return -1.
1942 | 1. If _x_ < _y_, return -1.
1943 | 1. If _x_ > _y_, return 1.
1944 | 1. If _x_ is *-0* and _y_ is *+0*, return -1.
1945 | 1. If _x_ is *+0* and _y_ is *-0*, return 1.
1946 | 1. Return *+0*.
1947 |
1948 |
1949 | Because *NaN* always compares greater than any other value, *NaN* property values always sort to the end of the result when _comparefn_ is not provided.
1950 |
1951 |
1952 |
1953 |
1954 | TypedArraySpeciesCreate ( _exemplar_, _argumentList_ )
1955 | The abstract operation TypedArraySpeciesCreate with arguments _exemplar_ and _argumentList_ is used to specify the creation of a new TypedArray object using a constructor function that is derived from _exemplar_. It performs the following steps:
1956 |
1957 | 1. Assert: _exemplar_ is an Object that has a [[TypedArrayName]] internal slot.
1958 | 1. Let _defaultConstructor_ be the intrinsic object listed in column one of for _exemplar_.[[TypedArrayName]].
1959 | 1. Let _constructor_ be ? SpeciesConstructor(_exemplar_, _defaultConstructor_).
1960 | 1. ReturnLet _result_ be ? TypedArrayCreate(_constructor_, _argumentList_).
1961 | 1. Assert: _result_ has a [[TypedArrayName]] internal slot.
1962 | 1. If _result_.[[TypedArrayName]] contains the substring `"Big"` and _exemplar_.[[TypedArrayName]] does not contain the substring `"Big"`, or vice versa, throw a *TypeError* exception.
1963 | 1. Return _result_.
1964 |
1965 |
1966 |
1967 |
1968 |
1969 | %TypedArray%.prototype.fill ( _value_ [ , _start_ [ , _end_ ] ] )
1970 | The interpretation and use of the arguments of %TypedArray%`.prototype.fill` are the same as for `Array.prototype.fill` as defined in .
1971 | The following steps are taken:
1972 |
1973 | 1. Let _O_ be the *this* value.
1974 | 1. Perform ? ValidateTypedArray(_O_).
1975 | 1. Let _len_ be _O_.[[ArrayLength]].
1976 | 1. If _O_.[[TypedArrayName]] is `"BigUint64Array"` or `"BigInt64Array"`, let _value_ be ? ToBigInt(_value_).
1977 | 1. Otherwise, let _value_ be ? ToNumber(_value_).
1978 | 1. Let _relativeStart_ be ? ToInteger(_start_).
1979 | 1. If _relativeStart_ < 0, let _k_ be max((_len_ + _relativeStart_), 0); else let _k_ be min(_relativeStart_, _len_).
1980 | 1. If _end_ is *undefined*, let _relativeEnd_ be _len_; else let _relativeEnd_ be ? ToInteger(_end_).
1981 | 1. If _relativeEnd_ < 0, let _final_ be max((_len_ + _relativeEnd_), 0); else let _final_ be min(_relativeEnd_, _len_).
1982 | 1. If IsDetachedBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception.
1983 | 1. Repeat, while _k_ < _final_
1984 | 1. Let _Pk_ be ! ToString(_k_).
1985 | 1. Perform ! Set(_O_, _Pk_, _value_, *true*).
1986 | 1. Increase _k_ by 1.
1987 | 1. Return _O_.
1988 |
1989 |
1990 |
1991 |
1992 |
1993 | %TypedArray%.prototype.set ( _array_ [ , _offset_ ] )
1994 | Sets multiple values in this _TypedArray_, reading the values from the object _array_. The optional _offset_ value indicates the first element index in this _TypedArray_ where values are written. If omitted, it is assumed to be 0.
1995 |
1996 | 1. Assert: _array_ is any ECMAScript language value other than an Object with a [[TypedArrayName]] internal slot. If it is such an Object, the definition in applies.
1997 | 1. Let _target_ be the *this* value.
1998 | 1. If Type(_target_) is not Object, throw a *TypeError* exception.
1999 | 1. If _target_ does not have a [[TypedArrayName]] internal slot, throw a *TypeError* exception.
2000 | 1. Assert: _target_ has a [[ViewedArrayBuffer]] internal slot.
2001 | 1. Let _targetOffset_ be ? ToInteger(_offset_).
2002 | 1. If _targetOffset_ < 0, throw a *RangeError* exception.
2003 | 1. Let _targetBuffer_ be _target_.[[ViewedArrayBuffer]].
2004 | 1. If IsDetachedBuffer(_targetBuffer_) is *true*, throw a *TypeError* exception.
2005 | 1. Let _targetLength_ be _target_.[[ArrayLength]].
2006 | 1. Let _targetName_ be the String value of _target_.[[TypedArrayName]].
2007 | 1. Let _targetElementSize_ be the Number value of the Element Size value specified in for _targetName_.
2008 | 1. Let _targetType_ be the String value of the Element Type value in for _targetName_.
2009 | 1. Let _targetByteOffset_ be _target_.[[ByteOffset]].
2010 | 1. Let _src_ be ? ToObject(_array_).
2011 | 1. Let _srcLength_ be ? ToLength(? Get(_src_, `"length"`)).
2012 | 1. If _srcLength_ + _targetOffset_ > _targetLength_, throw a *RangeError* exception.
2013 | 1. Let _targetByteIndex_ be _targetOffset_ × _targetElementSize_ + _targetByteOffset_.
2014 | 1. Let _k_ be 0.
2015 | 1. Let _limit_ be _targetByteIndex_ + _targetElementSize_ × _srcLength_.
2016 | 1. Repeat, while _targetByteIndex_ < _limit_
2017 | 1. Let _Pk_ be ! ToString(_k_).
2018 | 1. Let _kNumber_ be ? ToNumber(? Get(_src_, _Pk_)).
2019 | 1. Let _value_ be ? Get(_src_, _Pk_).
2020 | 1. If _target_.[[TypedArrayName]] is `"BigUint64Array"` or `"BigInt64Array"`, let _value_ be ? ToBigInt(_value_).
2021 | 1. Otherwise, let _value_ be ? ToNumber(_value_).
2022 | 1. If IsDetachedBuffer(_targetBuffer_) is *true*, throw a *TypeError* exception.
2023 | 1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, _targetType_, _kNumber__value_, *true*, `"Unordered"`).
2024 | 1. Set _k_ to _k_ + 1.
2025 | 1. Set _targetByteIndex_ to _targetByteIndex_ + _targetElementSize_.
2026 | 1. Return *undefined*.
2027 |
2028 |
2029 |
2030 |
2031 |
2032 | %TypedArray%.prototype.set( _typedArray_ [ , _offset_ ] )
2033 | Sets multiple values in this _TypedArray_, reading the values from the _typedArray_ argument object. The optional _offset_ value indicates the first element index in this _TypedArray_ where values are written. If omitted, it is assumed to be 0.
2034 |
2035 | 1. Assert: _typedArray_ has a [[TypedArrayName]] internal slot. If it does not, the definition in applies.
2036 | 1. Let _target_ be the *this* value.
2037 | 1. If Type(_target_) is not Object, throw a *TypeError* exception.
2038 | 1. If _target_ does not have a [[TypedArrayName]] internal slot, throw a *TypeError* exception.
2039 | 1. Assert: _target_ has a [[ViewedArrayBuffer]] internal slot.
2040 | 1. Let _targetOffset_ be ? ToInteger(_offset_).
2041 | 1. If _targetOffset_ < 0, throw a *RangeError* exception.
2042 | 1. Let _targetBuffer_ be _target_.[[ViewedArrayBuffer]].
2043 | 1. If IsDetachedBuffer(_targetBuffer_) is *true*, throw a *TypeError* exception.
2044 | 1. Let _targetLength_ be _target_.[[ArrayLength]].
2045 | 1. Let _srcBuffer_ be _typedArray_.[[ViewedArrayBuffer]].
2046 | 1. If IsDetachedBuffer(_srcBuffer_) is *true*, throw a *TypeError* exception.
2047 | 1. Let _targetName_ be the String value of _target_.[[TypedArrayName]].
2048 | 1. Let _targetType_ be the String value of the Element Type value in for _targetName_.
2049 | 1. Let _targetElementSize_ be the Number value of the Element Size value specified in for _targetName_.
2050 | 1. Let _targetByteOffset_ be _target_.[[ByteOffset]].
2051 | 1. Let _srcName_ be the String value of _typedArray_.[[TypedArrayName]].
2052 | 1. Let _srcType_ be the String value of the Element Type value in for _srcName_.
2053 | 1. Let _srcElementSize_ be the Number value of the Element Size value specified in for _srcName_.
2054 | 1. Let _srcLength_ be _typedArray_.[[ArrayLength]].
2055 | 1. Let _srcByteOffset_ be _typedArray_.[[ByteOffset]].
2056 | 1. If _srcLength_ + _targetOffset_ > _targetLength_, throw a *RangeError* exception.
2057 | 1. If one of _srcType_ and _targetType_ contains the substring `"Big"` and the other does not, throw a *TypeError* exception.
2058 | 1. If both IsSharedArrayBuffer(_srcBuffer_) and IsSharedArrayBuffer(_targetBuffer_) are *true*, then
2059 | 1. If _srcBuffer_.[[ArrayBufferData]] and _targetBuffer_.[[ArrayBufferData]] are the same Shared Data Block values, let _same_ be *true*; else let _same_ be *false*.
2060 | 1. Else, let _same_ be SameValue(_srcBuffer_, _targetBuffer_).
2061 | 1. If _same_ is *true*, then
2062 | 1. Let _srcByteLength_ be _typedArray_.[[ByteLength]].
2063 | 1. Let _srcBuffer_ be ? CloneArrayBuffer(_srcBuffer_, _srcByteOffset_, _srcByteLength_, %ArrayBuffer%).
2064 | 1. NOTE: %ArrayBuffer% is used to clone _srcBuffer_ because is it known to not have any observable side-effects.
2065 | 1. Let _srcByteIndex_ be 0.
2066 | 1. Else, let _srcByteIndex_ be _srcByteOffset_.
2067 | 1. Let _targetByteIndex_ be _targetOffset_ × _targetElementSize_ + _targetByteOffset_.
2068 | 1. Let _limit_ be _targetByteIndex_ + _targetElementSize_ × _srcLength_.
2069 | 1. If SameValue(_srcType_, _targetType_) is *true*, then
2070 | 1. NOTE: If _srcType_ and _targetType_ are the same, the transfer must be performed in a manner that preserves the bit-level encoding of the source data.
2071 | 1. Repeat, while _targetByteIndex_ < _limit_
2072 | 1. Let _value_ be GetValueFromBuffer(_srcBuffer_, _srcByteIndex_, `"Uint8"`, *true*, `"Unordered"`).
2073 | 1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, `"Uint8"`, _value_, *true*, `"Unordered"`).
2074 | 1. Set _srcByteIndex_ to _srcByteIndex_ + 1.
2075 | 1. Set _targetByteIndex_ to _targetByteIndex_ + 1.
2076 | 1. Else,
2077 | 1. Repeat, while _targetByteIndex_ < _limit_
2078 | 1. Let _value_ be GetValueFromBuffer(_srcBuffer_, _srcByteIndex_, _srcType_, *true*, `"Unordered"`).
2079 | 1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, _targetType_, _value_, *true*, `"Unordered"`).
2080 | 1. Set _srcByteIndex_ to _srcByteIndex_ + _srcElementSize_.
2081 | 1. Set _targetByteIndex_ to _targetByteIndex_ + _targetElementSize_.
2082 | 1. Return *undefined*.
2083 |
2084 |
2085 |
2086 |
2087 |
2088 | _TypedArray_ ( _typedArray_ )
2089 | This description applies only if the _TypedArray_ function is called with at least one argument and the Type of the first argument is Object and that object has a [[TypedArrayName]] internal slot.
2090 | _TypedArray_ called with argument _typedArray_ performs the following steps:
2091 |
2092 | 1. Assert: Type(_typedArray_) is Object and _typedArray_ has a [[TypedArrayName]] internal slot.
2093 | 1. If NewTarget is *undefined*, throw a *TypeError* exception.
2094 | 1. Let _constructorName_ be the String value of the Constructor Name value specified in for this TypedArray constructor.
2095 | 1. Let _O_ be ? AllocateTypedArray(_constructorName_, NewTarget, "%TypedArrayPrototype%").
2096 | 1. Let _srcArray_ be _typedArray_.
2097 | 1. Let _srcData_ be _srcArray_.[[ViewedArrayBuffer]].
2098 | 1. If IsDetachedBuffer(_srcData_) is *true*, throw a *TypeError* exception.
2099 | 1. Let _elementType_ be the String value of the Element Type value in for _constructorName_.
2100 | 1. Let _elementLength_ be _srcArray_.[[ArrayLength]].
2101 | 1. Let _srcName_ be the String value of _srcArray_.[[TypedArrayName]].
2102 | 1. Let _srcType_ be the String value of the Element Type value in for _srcName_.
2103 | 1. Let _srcElementSize_ be the Element Size value in for _srcName_.
2104 | 1. Let _srcByteOffset_ be _srcArray_.[[ByteOffset]].
2105 | 1. Let _elementSize_ be the Element Size value in for _constructorName_.
2106 | 1. Let _byteLength_ be _elementSize_ × _elementLength_.
2107 | 1. If IsSharedArrayBuffer(_srcData_) is *false*, then
2108 | 1. Let _bufferConstructor_ be ? SpeciesConstructor(_srcData_, %ArrayBuffer%).
2109 | 1. Else,
2110 | 1. Let _bufferConstructor_ be %ArrayBuffer%.
2111 | 1. If SameValue(_elementType_, _srcType_) is *true*, then
2112 | 1. If IsDetachedBuffer(_srcData_) is *true*, throw a *TypeError* exception.
2113 | 1. Let _data_ be ? CloneArrayBuffer(_srcData_, _srcByteOffset_, _byteLength_, _bufferConstructor_).
2114 | 1. Else,
2115 | 1. Let _data_ be ? AllocateArrayBuffer(_bufferConstructor_, _byteLength_).
2116 | 1. If IsDetachedBuffer(_srcData_) is *true*, throw a *TypeError* exception.
2117 | 1. If one of _srcType_ and _elementType_ contains the substring `"Big"` and the other does not, throw a *TypeError* exception.
2118 | 1. Let _srcByteIndex_ be _srcByteOffset_.
2119 | 1. Let _targetByteIndex_ be 0.
2120 | 1. Let _count_ be _elementLength_.
2121 | 1. Repeat, while _count_ > 0
2122 | 1. Let _value_ be GetValueFromBuffer(_srcData_, _srcByteIndex_, _srcType_, *true*, `"Unordered"`).
2123 | 1. Perform SetValueInBuffer(_data_, _targetByteIndex_, _elementType_, _value_, *true*, `"Unordered"`).
2124 | 1. Set _srcByteIndex_ to _srcByteIndex_ + _srcElementSize_.
2125 | 1. Set _targetByteIndex_ to _targetByteIndex_ + _elementSize_.
2126 | 1. Decrement _count_ by 1.
2127 | 1. Set _O_.[[ViewedArrayBuffer]] to _data_.
2128 | 1. Set _O_.[[ByteLength]] to _byteLength_.
2129 | 1. Set _O_.[[ByteOffset]] to 0.
2130 | 1. Set _O_.[[ArrayLength]] to _elementLength_.
2131 | 1. Return _O_.
2132 |
2133 |
2134 |
2135 |
2136 |
2137 | SetViewValue ( _view_, _requestIndex_, _isLittleEndian_, _type_, _value_ )
2138 | The abstract operation SetViewValue with arguments _view_, _requestIndex_, _isLittleEndian_, _type_, and _value_ is used by functions on DataView instances to store values into the view's buffer. It performs the following steps:
2139 |
2140 | 1. If Type(_view_) is not Object, throw a *TypeError* exception.
2141 | 1. If _view_ does not have a [[DataView]] internal slot, throw a *TypeError* exception.
2142 | 1. Assert: _view_ has a [[ViewedArrayBuffer]] internal slot.
2143 | 1. Let _getIndex_ be ? ToIndex(_requestIndex_).
2144 | 1. If _type_ is `"BigUint64"` or `"BigInt64"`, let _v_ be ? ToBigInt(_value_).
2145 | 1. Otherwise, let _v_ be ? ToInteger(_value_).
2146 | 1. Set _isLittleEndian_ to ToBoolean(_isLittleEndian_).
2147 | 1. Let _buffer_ be _view_.[[ViewedArrayBuffer]].
2148 | 1. If IsDetachedBuffer(_buffer_) is *true*, throw a *TypeError* exception.
2149 | 1. Let _viewOffset_ be _view_.[[ByteOffset]].
2150 | 1. Let _viewSize_ be _view_.[[ByteLength]].
2151 | 1. Let _elementSize_ be the Number value of the Element Size value specified in for Element Type _type_.
2152 | 1. If _getIndex_ + _elementSize_ > _viewSize_, throw a *RangeError* exception.
2153 | 1. Let _bufferIndex_ be _getIndex_ + _viewOffset_.
2154 | 1. Return SetValueInBuffer(_buffer_, _bufferIndex_, _type_, _v_, *false*, `"Unordered"`, _isLittleEndian_).
2155 |
2156 |
2157 |
2158 |
2159 | DataView.prototype.getBigInt64 ( _byteOffset_ [ , _littleEndian_ ] )
2160 | When the `getBigInt64` method is called with argument _byteOffset_ and optional argument _littleEndian_, the following steps are taken:
2161 |
2162 | 1. Let _v_ be the *this* value.
2163 | 1. If _littleEndian_ is not present, let _littleEndian_ be *undefined*.
2164 | 1. Return ? GetViewValue(_v_, _byteOffset_, _littleEndian_, `"BigInt64"`).
2165 |
2166 |
2167 |
2168 |
2169 | DataView.prototype.getBigUint64 ( _byteOffset_ [ , _littleEndian_ ] )
2170 | When the `getBigUint64` method is called with argument _byteOffset_ and optional argument _littleEndian_, the following steps are taken:
2171 |
2172 | 1. Let _v_ be the *this* value.
2173 | 1. If _littleEndian_ is not present, let _littleEndian_ be *undefined*.
2174 | 1. Return ? GetViewValue(_v_, _byteOffset_, _littleEndian_, `"BigUint64"`).
2175 |
2176 |
2177 |
2178 |
2179 | DataView.prototype.setBigInt64 ( _byteOffset_, _value_ [ , _littleEndian_ ] )
2180 | When the `setBigInt64` method is called with arguments _byteOffset_ and _value_, the following steps are taken:
2181 |
2182 | 1. Let _v_ be the *this* value.
2183 | 1. If _littleEndian_ is not present, let _littleEndian_ be *undefined*.
2184 | 1. Return ? SetViewValue(_v_, _byteOffset_, _littleEndian_, `"BigInt64"`, _value_).
2185 |
2186 |
2187 |
2188 |
2189 | DataView.prototype.setBigUint64 ( _byteOffset_, _value_ [ , _littleEndian_ ] )
2190 | When the `setBigUint64` method is called with arguments _byteOffset_ and _value_, the following steps are taken:
2191 |
2192 | 1. Let _v_ be the *this* value.
2193 | 1. If _littleEndian_ is not present, let _littleEndian_ be *undefined*.
2194 | 1. Return ? SetViewValue(_v_, _byteOffset_, _littleEndian_, `"BigUint64"`, _value_).
2195 |
2196 |
2197 |
2198 |
2199 |
2200 |
2201 | Agents
2202 |
2203 | An agent comprises a set of ECMAScript execution contexts, an execution context stack, a running execution context, a set of named job queues, an Agent Record, and an executing thread. Except for the executing thread, the constituents of an agent belong exclusively to that agent.
2204 | An agent's executing thread executes the jobs in the agent's job queues on the agent's execution contexts independently of other agents, except that an executing thread may be used as the executing thread by multiple agents, provided none of the agents sharing the thread have an Agent Record whose [[CanBlock]] property is *true*.
2205 |
2206 | Some web browsers share a single executing thread across multiple unrelated tabs of a browser window, for example.
2207 |
2208 | While an agent's executing thread executes the jobs in the agent's job queues, the agent is the surrounding agent for the code in those jobs. The code uses the surrounding agent to access the specification level execution objects held within the agent: the running execution context, the execution context stack, the named job queues, and the Agent Record's fields.
2209 |
2210 |
2211 |
2212 |
2213 | | Field Name |
2214 | Value |
2215 | Meaning |
2216 |
2217 |
2218 | | [[LittleEndian]] |
2219 | Boolean |
2220 | The default value computed for the isLittleEndian parameter when it is needed by the algorithms GetValueFromBuffer and SetValueInBuffer. The choice is implementation-dependent and should be the alternative that is most efficient for the implementation. Once the value has been observed it cannot change. |
2221 |
2222 |
2223 | | [[CanBlock]] |
2224 | Boolean |
2225 | Determines whether the agent can block or not. |
2226 |
2227 |
2228 | | [[Signifier]] |
2229 | Any globally-unique value |
2230 | Uniquely identifies the agent within its agent cluster. |
2231 |
2232 |
2233 | | [[IsLockFree1]] |
2234 | Boolean |
2235 | *true* if atomic operations on one-byte values are lock-free, *false* otherwise. |
2236 |
2237 |
2238 | | [[IsLockFree2]] |
2239 | Boolean |
2240 | *true* if atomic operations on two-byte values are lock-free, *false* otherwise. |
2241 |
2242 |
2243 | | [[IsLockFree8]] |
2244 | Boolean |
2245 | *true* if atomic operations on eight-byte values are lock-free, *false* otherwise. |
2246 |
2247 |
2248 | | [[CandidateExecution]] |
2249 | A candidate execution Record |
2250 | See the memory model. |
2251 |
2252 |
2253 |
2254 |
2255 |
2256 | Once the values of [[Signifier]], [[IsLockFree1]], [[IsLockFree2]], and [[IsLockFree8]] have been observed by any agent in the agent cluster they cannot change.
2257 |
2258 |
2259 | The values of [[IsLockFree1]], [[IsLockFree2]], and [[IsLockFree8]] are not necessarily determined by the hardware, but may also reflect implementation choices that can vary over time and between ECMAScript implementations.
2260 |
2261 | There is no [[IsLockFree4]] property: 4-byte atomic operations are always lock-free.
2262 |
2263 | In practice, if an atomic operation is implemented with any type of lock the operation is not lock-free. Lock-free does not imply wait-free: there is no upper bound on how many machine steps may be required to complete a lock-free atomic operation.
2264 |
2265 | That an atomic access of size n is lock-free does not imply anything about the (perceived) atomicity of non-atomic accesses of size n, specifically, non-atomic accesses may still be performed as a sequence of several separate memory accesses. See ReadSharedMemory and WriteSharedMemory for details.
2266 |
2267 |
2268 |
--------------------------------------------------------------------------------