From a22d5a3e08c91ae51a67841b97a7ba1a099a9f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 17:31:25 +0800 Subject: [PATCH 1/8] feat(compiler): Allow BigInt usage in templates (issue #11126) --- flow/component.js | 3 ++- src/compiler/parser/bigint-parser.js | 20 +++++++++++++++++ src/compiler/parser/text-parser.js | 7 ++++-- .../instance/render-helpers/bigint-helper.js | 22 +++++++++++++++++++ src/core/instance/render.js | 4 +++- test/unit/features/filter/filter.spec.js | 7 ++++++ 6 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 src/compiler/parser/bigint-parser.js create mode 100644 src/core/instance/render-helpers/bigint-helper.js diff --git a/flow/component.js b/flow/component.js index 0dc67a48a3e..7855484a379 100644 --- a/flow/component.js +++ b/flow/component.js @@ -74,7 +74,8 @@ declare interface Component { // _virtualComponents?: { [key: string]: Component }; // private methods - + _bigInt: Function; // BigInt support + // lifecycle _init: Function; _mount: (el?: Element | void, hydrating?: boolean) => Component; diff --git a/src/compiler/parser/bigint-parser.js b/src/compiler/parser/bigint-parser.js new file mode 100644 index 00000000000..6155aa1cf14 --- /dev/null +++ b/src/compiler/parser/bigint-parser.js @@ -0,0 +1,20 @@ +/* @flow */ + +/** + * turn "1000n" into "BigInt(1000)" + * and then turn "BigInt(1000)" into "_bigInt(1000)" + * + * by the way, if we meet variable like "l18n" + * we will change "l18n" to "l18@" + * after we finish parse bigint + * we will change "l18@" back to "l18n" + * @param {*} exp + */ +export function parseBigint(exp: string): string { + let expression = exp + .replace(/([a-zA-Z_$]+[0-9]+)n/g, '$1@') + .replace(/([0-9]+)n/g, 'BigInt($1)') + .replace(/([a-zA-Z_$]+[0-9]+)@/g, '$1n') + .replace(/BigInt\(/g, '_bigInt(') + return expression +} \ No newline at end of file diff --git a/src/compiler/parser/text-parser.js b/src/compiler/parser/text-parser.js index cf82a62484f..fe91fe999c1 100644 --- a/src/compiler/parser/text-parser.js +++ b/src/compiler/parser/text-parser.js @@ -2,6 +2,7 @@ import { cached } from 'shared/util' import { parseFilters } from './filter-parser' +import { parseBigint } from './bigint-parser' const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g const regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g @@ -36,8 +37,10 @@ export function parseText ( rawTokens.push(tokenValue = text.slice(lastIndex, index)) tokens.push(JSON.stringify(tokenValue)) } - // tag token - const exp = parseFilters(match[1].trim()) + // tag token and parse BigInt + let exp = parseFilters(match[1].trim()) + exp = parseBigint(exp) + tokens.push(`_s(${exp})`) rawTokens.push({ '@binding': exp }) lastIndex = index + match[0].length diff --git a/src/core/instance/render-helpers/bigint-helper.js b/src/core/instance/render-helpers/bigint-helper.js new file mode 100644 index 00000000000..f7238210a6e --- /dev/null +++ b/src/core/instance/render-helpers/bigint-helper.js @@ -0,0 +1,22 @@ +/* @flow */ +import { warn } from 'core/util/index' +/** + * get BigInt function + * if the browser support window.BigInt, we will use it + * if not, we can customize BigInt() for vue + */ +export function getBigintFunc (): Function { + if (typeof window !== 'undefined' && typeof window.BigInt === 'function') { + return window.BigInt + } else if (typeof global !== 'undefined' && typeof global.BigInt === 'function') { + return global.BigInt + } else { + warn( + 'BigInt is not support!' + ) + // customize our own BigInt() function + return function (arg) { + return arg + } + } +} diff --git a/src/core/instance/render.js b/src/core/instance/render.js index 15b3ad69f3a..a1122adb94a 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -11,6 +11,7 @@ import { import { createElement } from '../vdom/create-element' import { installRenderHelpers } from './render-helpers/index' import { resolveSlots } from './render-helpers/resolve-slots' +import { getBigintFunc } from './render-helpers/bigint-helper' import { normalizeScopedSlots } from '../vdom/helpers/normalize-scoped-slots' import VNode, { createEmptyVNode } from '../vdom/vnode' @@ -32,7 +33,8 @@ export function initRender (vm: Component) { // normalization is always applied for the public version, used in // user-written render functions. vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true) - + // load BigInt function on vm instance + vm._bigInt = getBigintFunc() // $attrs & $listeners are exposed for easier HOC creation. // they need to be reactive so that HOCs using them are always updated const parentData = parentVnode && parentVnode.data diff --git a/test/unit/features/filter/filter.spec.js b/test/unit/features/filter/filter.spec.js index 82c57a3d62e..854ea575064 100644 --- a/test/unit/features/filter/filter.spec.js +++ b/test/unit/features/filter/filter.spec.js @@ -194,4 +194,11 @@ describe('Filters', () => { it('support template string', () => { expect(parseFilters('`a | ${b}c` | d')).toBe('_f("d")(`a | ${b}c`)') }) + + it('bigint support', () => { + const vm = new Vue({ + template: `
{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}
` + }).$mount() + expect(vm.$el.textContent).toBe('6000000010000000') + }) }) From 6fadc238ef19b7bafeea2ecbf1be390a4a043b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 20:45:04 +0800 Subject: [PATCH 2/8] Revert "feat(compiler): Allow BigInt usage in templates (issue #11126)" This reverts commit a22d5a3e08c91ae51a67841b97a7ba1a099a9f0b. --- flow/component.js | 3 +-- src/compiler/parser/bigint-parser.js | 20 ----------------- src/compiler/parser/text-parser.js | 7 ++---- .../instance/render-helpers/bigint-helper.js | 22 ------------------- src/core/instance/render.js | 4 +--- test/unit/features/filter/filter.spec.js | 7 ------ 6 files changed, 4 insertions(+), 59 deletions(-) delete mode 100644 src/compiler/parser/bigint-parser.js delete mode 100644 src/core/instance/render-helpers/bigint-helper.js diff --git a/flow/component.js b/flow/component.js index 7855484a379..0dc67a48a3e 100644 --- a/flow/component.js +++ b/flow/component.js @@ -74,8 +74,7 @@ declare interface Component { // _virtualComponents?: { [key: string]: Component }; // private methods - _bigInt: Function; // BigInt support - + // lifecycle _init: Function; _mount: (el?: Element | void, hydrating?: boolean) => Component; diff --git a/src/compiler/parser/bigint-parser.js b/src/compiler/parser/bigint-parser.js deleted file mode 100644 index 6155aa1cf14..00000000000 --- a/src/compiler/parser/bigint-parser.js +++ /dev/null @@ -1,20 +0,0 @@ -/* @flow */ - -/** - * turn "1000n" into "BigInt(1000)" - * and then turn "BigInt(1000)" into "_bigInt(1000)" - * - * by the way, if we meet variable like "l18n" - * we will change "l18n" to "l18@" - * after we finish parse bigint - * we will change "l18@" back to "l18n" - * @param {*} exp - */ -export function parseBigint(exp: string): string { - let expression = exp - .replace(/([a-zA-Z_$]+[0-9]+)n/g, '$1@') - .replace(/([0-9]+)n/g, 'BigInt($1)') - .replace(/([a-zA-Z_$]+[0-9]+)@/g, '$1n') - .replace(/BigInt\(/g, '_bigInt(') - return expression -} \ No newline at end of file diff --git a/src/compiler/parser/text-parser.js b/src/compiler/parser/text-parser.js index fe91fe999c1..cf82a62484f 100644 --- a/src/compiler/parser/text-parser.js +++ b/src/compiler/parser/text-parser.js @@ -2,7 +2,6 @@ import { cached } from 'shared/util' import { parseFilters } from './filter-parser' -import { parseBigint } from './bigint-parser' const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g const regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g @@ -37,10 +36,8 @@ export function parseText ( rawTokens.push(tokenValue = text.slice(lastIndex, index)) tokens.push(JSON.stringify(tokenValue)) } - // tag token and parse BigInt - let exp = parseFilters(match[1].trim()) - exp = parseBigint(exp) - + // tag token + const exp = parseFilters(match[1].trim()) tokens.push(`_s(${exp})`) rawTokens.push({ '@binding': exp }) lastIndex = index + match[0].length diff --git a/src/core/instance/render-helpers/bigint-helper.js b/src/core/instance/render-helpers/bigint-helper.js deleted file mode 100644 index f7238210a6e..00000000000 --- a/src/core/instance/render-helpers/bigint-helper.js +++ /dev/null @@ -1,22 +0,0 @@ -/* @flow */ -import { warn } from 'core/util/index' -/** - * get BigInt function - * if the browser support window.BigInt, we will use it - * if not, we can customize BigInt() for vue - */ -export function getBigintFunc (): Function { - if (typeof window !== 'undefined' && typeof window.BigInt === 'function') { - return window.BigInt - } else if (typeof global !== 'undefined' && typeof global.BigInt === 'function') { - return global.BigInt - } else { - warn( - 'BigInt is not support!' - ) - // customize our own BigInt() function - return function (arg) { - return arg - } - } -} diff --git a/src/core/instance/render.js b/src/core/instance/render.js index a1122adb94a..15b3ad69f3a 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -11,7 +11,6 @@ import { import { createElement } from '../vdom/create-element' import { installRenderHelpers } from './render-helpers/index' import { resolveSlots } from './render-helpers/resolve-slots' -import { getBigintFunc } from './render-helpers/bigint-helper' import { normalizeScopedSlots } from '../vdom/helpers/normalize-scoped-slots' import VNode, { createEmptyVNode } from '../vdom/vnode' @@ -33,8 +32,7 @@ export function initRender (vm: Component) { // normalization is always applied for the public version, used in // user-written render functions. vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true) - // load BigInt function on vm instance - vm._bigInt = getBigintFunc() + // $attrs & $listeners are exposed for easier HOC creation. // they need to be reactive so that HOCs using them are always updated const parentData = parentVnode && parentVnode.data diff --git a/test/unit/features/filter/filter.spec.js b/test/unit/features/filter/filter.spec.js index 854ea575064..82c57a3d62e 100644 --- a/test/unit/features/filter/filter.spec.js +++ b/test/unit/features/filter/filter.spec.js @@ -194,11 +194,4 @@ describe('Filters', () => { it('support template string', () => { expect(parseFilters('`a | ${b}c` | d')).toBe('_f("d")(`a | ${b}c`)') }) - - it('bigint support', () => { - const vm = new Vue({ - template: `
{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}
` - }).$mount() - expect(vm.$el.textContent).toBe('6000000010000000') - }) }) From 66fbc39f0e18a804750c384e30e57cebe1d4b5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 20:54:18 +0800 Subject: [PATCH 3/8] feat(compiler): Allow BigInt usage in templates (issue #11126) --- src/core/instance/proxy.js | 3 ++- test/unit/features/filter/filter.spec.js | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/instance/proxy.js b/src/core/instance/proxy.js index 95c2b97a91f..967b535fd68 100644 --- a/src/core/instance/proxy.js +++ b/src/core/instance/proxy.js @@ -9,7 +9,7 @@ if (process.env.NODE_ENV !== 'production') { const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + - 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + 'require' // for Webpack/Browserify ) @@ -54,6 +54,7 @@ if (process.env.NODE_ENV !== 'production') { const hasHandler = { has (target, key) { + console.log(target, key) const has = key in target const isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data)) diff --git a/test/unit/features/filter/filter.spec.js b/test/unit/features/filter/filter.spec.js index 82c57a3d62e..854ea575064 100644 --- a/test/unit/features/filter/filter.spec.js +++ b/test/unit/features/filter/filter.spec.js @@ -194,4 +194,11 @@ describe('Filters', () => { it('support template string', () => { expect(parseFilters('`a | ${b}c` | d')).toBe('_f("d")(`a | ${b}c`)') }) + + it('bigint support', () => { + const vm = new Vue({ + template: `
{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}
` + }).$mount() + expect(vm.$el.textContent).toBe('6000000010000000') + }) }) From 6f2eee749a9a9565a8f9a0f4a040beabbf847f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 21:06:27 +0800 Subject: [PATCH 4/8] Revert "feat(compiler): Allow BigInt usage in templates (issue #11126)" This reverts commit a22d5a3e08c91ae51a67841b97a7ba1a099a9f0b. --- test/unit/features/filter/filter.spec.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/unit/features/filter/filter.spec.js b/test/unit/features/filter/filter.spec.js index 854ea575064..82c57a3d62e 100644 --- a/test/unit/features/filter/filter.spec.js +++ b/test/unit/features/filter/filter.spec.js @@ -194,11 +194,4 @@ describe('Filters', () => { it('support template string', () => { expect(parseFilters('`a | ${b}c` | d')).toBe('_f("d")(`a | ${b}c`)') }) - - it('bigint support', () => { - const vm = new Vue({ - template: `
{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}
` - }).$mount() - expect(vm.$el.textContent).toBe('6000000010000000') - }) }) From 9e05266abca4c54db0dc425e8a11c909af68eff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 21:08:01 +0800 Subject: [PATCH 5/8] Revert "feat(compiler): Allow BigInt usage in templates (issue #11126)" This reverts commit 66fbc39f0e18a804750c384e30e57cebe1d4b5ee. --- src/core/instance/proxy.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/instance/proxy.js b/src/core/instance/proxy.js index 967b535fd68..95c2b97a91f 100644 --- a/src/core/instance/proxy.js +++ b/src/core/instance/proxy.js @@ -9,7 +9,7 @@ if (process.env.NODE_ENV !== 'production') { const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + - 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify ) @@ -54,7 +54,6 @@ if (process.env.NODE_ENV !== 'production') { const hasHandler = { has (target, key) { - console.log(target, key) const has = key in target const isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data)) From 7b626a849d6e8a20a35ba42e6351f10d3d67da02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 21:39:46 +0800 Subject: [PATCH 6/8] feat(compiler): Allow BigInt usage in templates (issue #11126) --- src/core/instance/proxy.js | 7 ++++++- test/unit/features/filter/filter.spec.js | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core/instance/proxy.js b/src/core/instance/proxy.js index 95c2b97a91f..423d58788d9 100644 --- a/src/core/instance/proxy.js +++ b/src/core/instance/proxy.js @@ -6,11 +6,16 @@ import { warn, makeMap, isNative } from '../util/index' let initProxy if (process.env.NODE_ENV !== 'production') { + const supportBigInt = + (typeof window !== 'undefined' && typeof window.BigInt === 'function') || + (typeof global !== 'undefined' && typeof global.BigInt === 'function') + const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + - 'require' // for Webpack/Browserify + 'require,' + // for Webpack/Browserify + (supportBigInt ? 'BigInt' : '') // for BigInt support issue #11126 ) const warnNonPresent = (target, key) => { diff --git a/test/unit/features/filter/filter.spec.js b/test/unit/features/filter/filter.spec.js index 82c57a3d62e..854ea575064 100644 --- a/test/unit/features/filter/filter.spec.js +++ b/test/unit/features/filter/filter.spec.js @@ -194,4 +194,11 @@ describe('Filters', () => { it('support template string', () => { expect(parseFilters('`a | ${b}c` | d')).toBe('_f("d")(`a | ${b}c`)') }) + + it('bigint support', () => { + const vm = new Vue({ + template: `
{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}
` + }).$mount() + expect(vm.$el.textContent).toBe('6000000010000000') + }) }) From fdfb563b9292cd5bc5f47d495aad496d7a3fbc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 22:26:12 +0800 Subject: [PATCH 7/8] feat(compiler): Allow BigInt usage in templates (issue #11126) --- src/core/instance/proxy.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/instance/proxy.js b/src/core/instance/proxy.js index 423d58788d9..fe36baed8ad 100644 --- a/src/core/instance/proxy.js +++ b/src/core/instance/proxy.js @@ -6,16 +6,12 @@ import { warn, makeMap, isNative } from '../util/index' let initProxy if (process.env.NODE_ENV !== 'production') { - const supportBigInt = - (typeof window !== 'undefined' && typeof window.BigInt === 'function') || - (typeof global !== 'undefined' && typeof global.BigInt === 'function') - const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require,' + // for Webpack/Browserify - (supportBigInt ? 'BigInt' : '') // for BigInt support issue #11126 + 'BigInt' // for BigInt support issue #11126 ) const warnNonPresent = (target, key) => { From 4241f12055275b6687de417e33b6d44a0999c55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= Date: Thu, 27 Feb 2020 23:25:20 +0800 Subject: [PATCH 8/8] feat(compiler): Allow BigInt usage in templates (issue #11126) --- src/core/instance/proxy.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/instance/proxy.js b/src/core/instance/proxy.js index fe36baed8ad..b1884f7118c 100644 --- a/src/core/instance/proxy.js +++ b/src/core/instance/proxy.js @@ -9,9 +9,8 @@ if (process.env.NODE_ENV !== 'production') { const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + - 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + - 'require,' + // for Webpack/Browserify - 'BigInt' // for BigInt support issue #11126 + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + + 'require' // for Webpack/Browserify ) const warnNonPresent = (target, key) => {