From a22d5a3e08c91ae51a67841b97a7ba1a099a9f0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B5=B5=E8=B6=8A?= <shadowingszy@outlook.com>
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: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`
+    }).$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?= <shadowingszy@outlook.com>
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: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`
-    }).$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?= <shadowingszy@outlook.com>
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: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`
+    }).$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?= <shadowingszy@outlook.com>
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: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`
-    }).$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?= <shadowingszy@outlook.com>
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?= <shadowingszy@outlook.com>
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: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`
+    }).$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?= <shadowingszy@outlook.com>
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?= <shadowingszy@outlook.com>
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) => {