Skip to content

Commit a22d5a3

Browse files
committed
feat(compiler): Allow BigInt usage in templates (issue vuejs#11126)
1 parent 6390f70 commit a22d5a3

File tree

6 files changed

+59
-4
lines changed

6 files changed

+59
-4
lines changed

flow/component.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ declare interface Component {
7474
// _virtualComponents?: { [key: string]: Component };
7575

7676
// private methods
77-
77+
_bigInt: Function; // BigInt support
78+
7879
// lifecycle
7980
_init: Function;
8081
_mount: (el?: Element | void, hydrating?: boolean) => Component;

src/compiler/parser/bigint-parser.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* @flow */
2+
3+
/**
4+
* turn "1000n" into "BigInt(1000)"
5+
* and then turn "BigInt(1000)" into "_bigInt(1000)"
6+
*
7+
* by the way, if we meet variable like "l18n"
8+
* we will change "l18n" to "l18@"
9+
* after we finish parse bigint
10+
* we will change "l18@" back to "l18n"
11+
* @param {*} exp
12+
*/
13+
export function parseBigint(exp: string): string {
14+
let expression = exp
15+
.replace(/([a-zA-Z_$]+[0-9]+)n/g, '$1@')
16+
.replace(/([0-9]+)n/g, 'BigInt($1)')
17+
.replace(/([a-zA-Z_$]+[0-9]+)@/g, '$1n')
18+
.replace(/BigInt\(/g, '_bigInt(')
19+
return expression
20+
}

src/compiler/parser/text-parser.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { cached } from 'shared/util'
44
import { parseFilters } from './filter-parser'
5+
import { parseBigint } from './bigint-parser'
56

67
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g
78
const regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g
@@ -36,8 +37,10 @@ export function parseText (
3637
rawTokens.push(tokenValue = text.slice(lastIndex, index))
3738
tokens.push(JSON.stringify(tokenValue))
3839
}
39-
// tag token
40-
const exp = parseFilters(match[1].trim())
40+
// tag token and parse BigInt
41+
let exp = parseFilters(match[1].trim())
42+
exp = parseBigint(exp)
43+
4144
tokens.push(`_s(${exp})`)
4245
rawTokens.push({ '@binding': exp })
4346
lastIndex = index + match[0].length
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* @flow */
2+
import { warn } from 'core/util/index'
3+
/**
4+
* get BigInt function
5+
* if the browser support window.BigInt, we will use it
6+
* if not, we can customize BigInt() for vue
7+
*/
8+
export function getBigintFunc (): Function {
9+
if (typeof window !== 'undefined' && typeof window.BigInt === 'function') {
10+
return window.BigInt
11+
} else if (typeof global !== 'undefined' && typeof global.BigInt === 'function') {
12+
return global.BigInt
13+
} else {
14+
warn(
15+
'BigInt is not support!'
16+
)
17+
// customize our own BigInt() function
18+
return function (arg) {
19+
return arg
20+
}
21+
}
22+
}

src/core/instance/render.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { createElement } from '../vdom/create-element'
1212
import { installRenderHelpers } from './render-helpers/index'
1313
import { resolveSlots } from './render-helpers/resolve-slots'
14+
import { getBigintFunc } from './render-helpers/bigint-helper'
1415
import { normalizeScopedSlots } from '../vdom/helpers/normalize-scoped-slots'
1516
import VNode, { createEmptyVNode } from '../vdom/vnode'
1617

@@ -32,7 +33,8 @@ export function initRender (vm: Component) {
3233
// normalization is always applied for the public version, used in
3334
// user-written render functions.
3435
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
35-
36+
// load BigInt function on vm instance
37+
vm._bigInt = getBigintFunc()
3638
// $attrs & $listeners are exposed for easier HOC creation.
3739
// they need to be reactive so that HOCs using them are always updated
3840
const parentData = parentVnode && parentVnode.data

test/unit/features/filter/filter.spec.js

+7
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,11 @@ describe('Filters', () => {
194194
it('support template string', () => {
195195
expect(parseFilters('`a | ${b}c` | d')).toBe('_f("d")(`a | ${b}c`)')
196196
})
197+
198+
it('bigint support', () => {
199+
const vm = new Vue({
200+
template: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`
201+
}).$mount()
202+
expect(vm.$el.textContent).toBe('6000000010000000')
203+
})
197204
})

0 commit comments

Comments
 (0)