├── .editorconfig ├── .gitattributes ├── .gitignore ├── .nvmrc ├── .travis.yml ├── README.md ├── package.json └── spec.html /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = tab 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [{README.md,package.json,spec.html,.travis.yml}] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Automatically normalize line endings for all text-based files 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | 3 | # Installed npm modules 4 | package-lock.json 5 | node_modules 6 | 7 | # Folder view configuration files 8 | .DS_Store 9 | Desktop.ini 10 | 11 | # Thumbnail cache files 12 | ._* 13 | Thumbs.db 14 | 15 | # Files that might appear on external disks 16 | .Spotlight-V100 17 | .Trashes 18 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 6 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '8' 4 | script: 5 | - npm run build 6 | deploy: 7 | local_dir: dist 8 | email: mathias@qiwi.be 9 | name: Mathias Bynens 10 | provider: pages 11 | skip_cleanup: true 12 | github_token: $GITHUB_TOKEN 13 | on: 14 | branch: master 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ECMAScript proposal: `{BigInt,Number}.fromString` 2 | 3 | ## Status 4 | 5 | This proposal is at stage 1 of [the TC39 process](https://tc39.github.io/process-document/). 6 | 7 | ## Background 8 | 9 | [The `BigInt` proposal](https://github.com/tc39/proposal-bigint) initially included a static `BigInt.parseInt` method. After [some discussion](https://github.com/tc39/proposal-bigint/issues/86), it was [removed](https://github.com/tc39/proposal-bigint/commit/30b5594c30bdf7973323d61504017933673df283) in favor of a separate proposal to add a static `fromString` method to both `BigInt` and `Number`. This is that proposal. 10 | 11 | ## Motivation 12 | 13 | `{BigInt,Number}.prototype.toString(radix)` enables converting a numeric value into a string representation of that value. For `BigInt`s specifically, there is currently no built-in way to do the inverse, i.e. to turn a string representation of a `BigInt` with a given radix back into a `BigInt`. 14 | 15 | For `Number` values, there is [`parseInt(string, radix = 10)`](https://tc39.github.io/ecma262/#sec-parseint-string-radix) and [`Number.parseInt(string, radix = 10)`](https://tc39.github.io/ecma262/#sec-number.parseint), but its behavior is suboptimal: 16 | 17 | - It returns `NaN` instead of throwing a `SyntaxError` exception when `string` does not represent a number. 18 | - It returns `NaN` instead of throwing a `RangeError` exception when `radix` is not valid (i.e. `radix !== 0 && radix < 2` or `radix > 36`). 19 | - It accepts radix `0`, treating it as `10` instead, which does not make sense. 20 | - It ignores leading whitespace and trailing non-digit characters. 21 | - It supports hexadecimal integer literal prefixes `0x` and `0X` but lacks support for octal integer literal prefixes `0o` and `0O` or binary integer literal prefixes `0b` and `0B`, which is inconsistent. 22 | - The fact that `parseInt` has some level of support for integer literal prefixes means that it’s not a clear counterpart to `toString`. 23 | 24 | ## Proposed solution 25 | 26 | We propose extending both `BigInt` and `Number` with a new static `fromString(string, radix = 10)` method which acts as the inverse of `{BigInt,Number}.prototype.toString(radix = 10)`. It accepts only strings that can be produced by `{BigInt,Number}.prototype.toString(radix = 10)`, and throws an exception for any other input. 27 | 28 | ## High-level API 29 | 30 | ```js 31 | Number.fromString('42'); 32 | // → 42 33 | Number.fromString('42', 10); 34 | // → 42 35 | 36 | BigInt.fromString('42'); 37 | // → 42n 38 | BigInt.fromString('42', 10); 39 | // → 42n 40 | ``` 41 | 42 | ## Illustrative examples 43 | 44 | The following examples use `Number.fromString`. The semantics for `BigInt.fromString` are identical except it returns a `BigInt` rather than a `Number`. 45 | 46 | Unlike `parseInt`, `fromString` intentionally lacks special handling for integer literal prefixes. 47 | 48 | ```js 49 | Number.parseInt('0xc0ffee'); 50 | // → 12648430 51 | Number.parseInt('0o755'); 52 | // → 0 53 | Number.parseInt('0b00101010'); 54 | // → 0 55 | 56 | Number.fromString('0xc0ffee'); 57 | // → SyntaxError 58 | Number.fromString('0o755'); 59 | // → SyntaxError 60 | Number.fromString('0b00101010'); 61 | // → SyntaxError 62 | 63 | Number.fromString('C0FFEE', 16); 64 | // → SyntaxError (toString produces lowercase digits) 65 | Number.fromString('c0ffee', 16); 66 | // → 12648430 === 0xc0ffee 67 | Number.fromString('755', 8); 68 | // → 493 === 0o755 69 | Number.fromString('00101010', 2); 70 | // → 42 === 0b00101010 71 | ``` 72 | 73 | Unlike `parseInt`, `fromString` throws a `SyntaxError` exception when `string` does not represent a number. 74 | 75 | ```js 76 | Number.parseInt(''); 77 | // → NaN 78 | Number.parseInt(' \n '); 79 | // → NaN 80 | Number.parseInt('x'); 81 | // → NaN 82 | 83 | Number.fromString(''); 84 | // → SyntaxError 85 | Number.fromString(' \n '); 86 | // → SyntaxError 87 | Number.fromString('x'); 88 | // → SyntaxError 89 | ``` 90 | 91 | Unlike `parseInt`, `fromString` throws a `RangeError` exception when `radix < 2` or `radix > 36`. 92 | 93 | ```js 94 | Number.parseInt('1234', 0); 95 | // → 1234 96 | Number.parseInt('1234', 1); 97 | // → NaN 98 | Number.parseInt('1234', 37); 99 | // → NaN 100 | 101 | Number.fromString('1234', 0); 102 | // → RangeError 103 | Number.fromString('1234', 1); 104 | // → RangeError 105 | Number.fromString('1234', 37); 106 | // → RangeError 107 | ``` 108 | 109 | Unlike `parseInt`, `fromString` throws a `TypeError` exception when `string` is not a string. 110 | 111 | ```js 112 | Number.parseInt(true, 32); 113 | // → 978894 114 | 115 | Number.fromString(true, 32); 116 | // → TypeError 117 | ``` 118 | 119 | ### FAQ 120 | 121 | #### What about legacy octal integers? 122 | 123 | `fromString` intentionally lacks special handling for legacy octal integer literals, i.e. those without the explicit `0o` or `0O` prefix such as `010`. In other words, `Number.fromString('010')` throws a `SyntaxError` exception. 124 | 125 | #### What about numeric separators? 126 | 127 | `fromString` does not need to support [numeric separators](https://github.com/tc39/proposal-numeric-separator), as they cannot occur in `{BigInt,Number}.prototype.toString(radix)` output. `Number.fromString('1_000_000_000')` throws a `SyntaxError` exception. 128 | 129 | #### Does `BigInt.fromString(string)` support the `n` suffix? 130 | 131 | `BigInt.fromString` does not need to support the `n` suffix used for `BigInt` literals, as it doesn’t occur in `BigInt.prototype.toString(radix)` output. Furthermore, supporting it would introduce an ambiguity for radices where `n` is a valid digit: should `BigInt.fromString('1n', 32)` return `1` or `55`? With the current proposal, `BigInt.fromString('1n', 32)` returns `55`, and `BigInt.fromString('1n')` throws a `SyntaxError` exception. 132 | 133 | ## Specification 134 | 135 | * [Ecmarkup source](https://github.com/mathiasbynens/proposal-number-fromstring/blob/master/spec.html) 136 | * [HTML version](https://mathiasbynens.github.io/proposal-number-fromstring/) 137 | 138 | ## Implementations 139 | 140 | * none yet 141 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "test": ":", 5 | "build": "mkdir -p dist; ecmarkup --verbose spec.html dist/index.html --css dist/ecmarkup.css --js dist/ecmarkup.js" 6 | }, 7 | "devDependencies": { 8 | "ecmarkup": "^3.12.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | title: '`{BigInt,Number}.fromString`' 5 | status: proposal 6 | stage: 1 7 | location: https://mathiasbynens.github.io/proposal-number-fromstring/ 8 | copyright: false 9 | contributors: Mathias Bynens 10 |11 | 12 | 13 | 21 |
The `BigInt.fromString` function produces an integer value dictated by interpretation of the contents of the _string_ argument according to the specified _radix_. If _radix_ is *undefined*, it is assumed to be 10.
24 |When the `BigInt.fromString` function is called, the following steps are taken:
25 |The `Number.fromString` function produces a numeric value dictated by interpretation of the contents of the _string_ argument according to the specified _radix_. If _radix_ is *undefined*, it is assumed to be 10.
48 |When the `Number.fromString` function is called, the following steps are taken:
49 |