From bfecf2cdce10ac36682e28ad9a81553ac81fa6da Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 5 Oct 2019 17:18:25 -0400 Subject: [PATCH] refactor(compiler): use symbols for runtime helpers --- .../__snapshots__/codegen.spec.ts.snap | 37 +++---- .../__snapshots__/compile.spec.ts.snap | 4 +- .../compiler-core/__tests__/codegen.spec.ts | 74 ++++++++++---- packages/compiler-core/__tests__/testUtils.ts | 2 +- .../compiler-core/__tests__/transform.spec.ts | 16 +-- .../transforms/transformElement.spec.ts | 76 +++++++-------- .../transforms/transformSlotOutlet.spec.ts | 22 ++--- .../__tests__/transforms/vBind.spec.ts | 6 +- .../__tests__/transforms/vFor.spec.ts | 34 +++---- .../__tests__/transforms/vIf.spec.ts | 32 +++--- .../__tests__/transforms/vSlot.spec.ts | 6 +- packages/compiler-core/src/ast.ts | 53 ++++++++-- packages/compiler-core/src/codegen.ts | 97 ++++++++++++++----- packages/compiler-core/src/index.ts | 5 +- .../compiler-core/src/runtimeConstants.ts | 21 ---- packages/compiler-core/src/runtimeHelpers.ts | 64 ++++++++++++ packages/compiler-core/src/transform.ts | 37 +++++-- .../src/transforms/hoistStatic.ts | 6 +- .../src/transforms/transformElement.ts | 29 ++---- .../src/transforms/transformSlotOutlet.ts | 2 +- .../compiler-core/src/transforms/vBind.ts | 6 +- packages/compiler-core/src/transforms/vFor.ts | 2 +- packages/compiler-core/src/transforms/vIf.ts | 8 +- .../compiler-core/src/transforms/vSlot.ts | 2 +- packages/compiler-core/src/utils.ts | 9 +- packages/shared/src/index.ts | 1 + 26 files changed, 420 insertions(+), 231 deletions(-) delete mode 100644 packages/compiler-core/src/runtimeConstants.ts create mode 100644 packages/compiler-core/src/runtimeHelpers.ts diff --git a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap index ec0e3e8b586..4e70c5918b6 100644 --- a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap @@ -17,15 +17,15 @@ exports[`compiler: codegen Element (callExpression + objectExpression + arrayExp " return function render() { with (this) { - return createVNode(\\"div\\", { + return _createVNode(\\"div\\", { id: \\"foo\\", [prop]: bar, [foo + bar]: bar }, [ - createVNode(\\"p\\", { \\"some-key\\": \\"foo\\" }) + _createVNode(\\"p\\", { \\"some-key\\": \\"foo\\" }) ], [ foo, - createVNode(\\"p\\") + _createVNode(\\"p\\") ]) } }" @@ -40,6 +40,19 @@ return function render() { }" `; +exports[`compiler: codegen assets 1`] = ` +" +return function render() { + with (this) { + const _component_Foo = _resolveComponent(\\"Foo\\") + const _component_barbaz = _resolveComponent(\\"bar-baz\\") + const _directive_my_dir = _resolveDirective(\\"my_dir\\") + + return null + } +}" +`; + exports[`compiler: codegen comment 1`] = ` " return function render() { @@ -72,7 +85,7 @@ exports[`compiler: codegen function mode preamble 1`] = ` return function render() { with (this) { - const { helperOne: _helperOne, helperTwo: _helperTwo } = _Vue + const { createVNode: _createVNode, resolveDirective: _resolveDirective } = _Vue return null } @@ -80,7 +93,7 @@ return function render() { `; exports[`compiler: codegen function mode preamble w/ prefixIdentifiers: true 1`] = ` -"const { helperOne, helperTwo } = Vue +"const { createVNode, resolveDirective } = Vue return function render() { const _ctx = this @@ -119,7 +132,7 @@ return function render() { `; exports[`compiler: codegen module mode preamble 1`] = ` -"import { helperOne, helperTwo } from \\"vue\\" +"import { createVNode, resolveDirective } from \\"vue\\" export default function render() { const _ctx = this @@ -135,18 +148,6 @@ return function render() { }" `; -exports[`compiler: codegen statements 1`] = ` -" -return function render() { - with (this) { - const a = 1 - const b = 2 - - return null - } -}" -`; - exports[`compiler: codegen static text 1`] = ` " return function render() { diff --git a/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap index d9ade929bac..5975fc392f5 100644 --- a/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap @@ -56,13 +56,13 @@ export default function render() { id: \\"foo\\", class: _ctx.bar.baz }, [ - _toString(_ctx.world.burn()), + toString(_ctx.world.burn()), (openBlock(), (_ctx.ok) ? createBlock(\\"div\\", { key: 0 }, \\"yes\\") : createBlock(Fragment, { key: 1 }, [\\"no\\"])), (openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => { return (openBlock(), createBlock(\\"div\\", null, [ - createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */) + createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */) ])) }), 128 /* UNKEYED_FRAGMENT */)) ], 2 /* CLASS */)) diff --git a/packages/compiler-core/__tests__/codegen.spec.ts b/packages/compiler-core/__tests__/codegen.spec.ts index 49311c8f313..d881bea48fd 100644 --- a/packages/compiler-core/__tests__/codegen.spec.ts +++ b/packages/compiler-core/__tests__/codegen.spec.ts @@ -13,15 +13,23 @@ import { createCallExpression, createConditionalExpression } from '../src' -import { CREATE_VNODE, COMMENT, TO_STRING } from '../src/runtimeConstants' +import { + CREATE_VNODE, + COMMENT, + TO_STRING, + RESOLVE_DIRECTIVE, + helperNameMap, + RESOLVE_COMPONENT +} from '../src/runtimeHelpers' import { createElementWithCodegen } from './testUtils' function createRoot(options: Partial = {}): RootNode { return { type: NodeTypes.ROOT, children: [], - imports: [], - statements: [], + helpers: [], + components: [], + directives: [], hoists: [], codegenNode: undefined, loc: locStub, @@ -32,45 +40,69 @@ function createRoot(options: Partial = {}): RootNode { describe('compiler: codegen', () => { test('module mode preamble', () => { const root = createRoot({ - imports: [`helperOne`, `helperTwo`] + helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE] }) const { code } = generate(root, { mode: 'module' }) - expect(code).toMatch(`import { helperOne, helperTwo } from "vue"`) + expect(code).toMatch( + `import { ${helperNameMap[CREATE_VNODE]}, ${ + helperNameMap[RESOLVE_DIRECTIVE] + } } from "vue"` + ) expect(code).toMatchSnapshot() }) test('function mode preamble', () => { const root = createRoot({ - imports: [`helperOne`, `helperTwo`] + helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE] }) const { code } = generate(root, { mode: 'function' }) expect(code).toMatch(`const _Vue = Vue`) expect(code).toMatch( - `const { helperOne: _helperOne, helperTwo: _helperTwo } = _Vue` + `const { ${helperNameMap[CREATE_VNODE]}: _${ + helperNameMap[CREATE_VNODE] + }, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${ + helperNameMap[RESOLVE_DIRECTIVE] + } } = _Vue` ) expect(code).toMatchSnapshot() }) test('function mode preamble w/ prefixIdentifiers: true', () => { const root = createRoot({ - imports: [`helperOne`, `helperTwo`] + helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE] }) const { code } = generate(root, { mode: 'function', prefixIdentifiers: true }) expect(code).not.toMatch(`const _Vue = Vue`) - expect(code).toMatch(`const { helperOne, helperTwo } = Vue`) + expect(code).toMatch( + `const { ${helperNameMap[CREATE_VNODE]}, ${ + helperNameMap[RESOLVE_DIRECTIVE] + } } = Vue` + ) expect(code).toMatchSnapshot() }) - test('statements', () => { + test('assets', () => { const root = createRoot({ - statements: [`const a = 1`, `const b = 2`] + components: [`Foo`, `bar-baz`], + directives: [`my_dir`] }) const { code } = generate(root, { mode: 'function' }) - expect(code).toMatch(`const a = 1\n`) - expect(code).toMatch(`const b = 2\n`) + expect(code).toMatch( + `const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n` + ) + expect(code).toMatch( + `const _component_barbaz = _${ + helperNameMap[RESOLVE_COMPONENT] + }("bar-baz")\n` + ) + expect(code).toMatch( + `const _directive_my_dir = _${ + helperNameMap[RESOLVE_DIRECTIVE] + }("my_dir")\n` + ) expect(code).toMatchSnapshot() }) @@ -122,7 +154,7 @@ describe('compiler: codegen', () => { codegenNode: createInterpolation(`hello`, locStub) }) ) - expect(code).toMatch(`return _${TO_STRING}(hello)`) + expect(code).toMatch(`return _${helperNameMap[TO_STRING]}(hello)`) expect(code).toMatchSnapshot() }) @@ -136,7 +168,11 @@ describe('compiler: codegen', () => { } }) ) - expect(code).toMatch(`return _${CREATE_VNODE}(_${COMMENT}, 0, "foo")`) + expect(code).toMatch( + `return _${helperNameMap[CREATE_VNODE]}(_${ + helperNameMap[COMMENT] + }, 0, "foo")` + ) expect(code).toMatchSnapshot() }) @@ -155,7 +191,7 @@ describe('compiler: codegen', () => { ]) }) ) - expect(code).toMatch(`return _ctx.foo + _${TO_STRING}(bar)`) + expect(code).toMatch(`return _ctx.foo + _${helperNameMap[TO_STRING]}(bar)`) expect(code).toMatchSnapshot() }) @@ -264,15 +300,15 @@ describe('compiler: codegen', () => { }) ) expect(code).toMatch(` - return ${CREATE_VNODE}("div", { + return _${helperNameMap[CREATE_VNODE]}("div", { id: "foo", [prop]: bar, [foo + bar]: bar }, [ - ${CREATE_VNODE}("p", { "some-key": "foo" }) + _${helperNameMap[CREATE_VNODE]}("p", { "some-key": "foo" }) ], [ foo, - ${CREATE_VNODE}("p") + _${helperNameMap[CREATE_VNODE]}("p") ])`) expect(code).toMatchSnapshot() }) diff --git a/packages/compiler-core/__tests__/testUtils.ts b/packages/compiler-core/__tests__/testUtils.ts index cc061d87de7..1ad6820010f 100644 --- a/packages/compiler-core/__tests__/testUtils.ts +++ b/packages/compiler-core/__tests__/testUtils.ts @@ -6,7 +6,7 @@ import { Namespaces, ElementTypes } from '../src' -import { CREATE_VNODE } from '../src/runtimeConstants' +import { CREATE_VNODE } from '../src/runtimeHelpers' import { isString } from '@vue/shared' const leadingBracketRE = /^\[/ diff --git a/packages/compiler-core/__tests__/transform.spec.ts b/packages/compiler-core/__tests__/transform.spec.ts index 076fa37a835..6f778e15615 100644 --- a/packages/compiler-core/__tests__/transform.spec.ts +++ b/packages/compiler-core/__tests__/transform.spec.ts @@ -15,7 +15,7 @@ import { CREATE_BLOCK, FRAGMENT, RENDER_SLOT -} from '../src/runtimeConstants' +} from '../src/runtimeHelpers' import { transformIf } from '../src/transforms/vIf' import { transformFor } from '../src/transforms/vFor' import { transformElement } from '../src/transforms/transformElement' @@ -225,14 +225,14 @@ describe('compiler: transform', () => { test('should inject toString helper for interpolations', () => { const ast = parse(`{{ foo }}`) transform(ast, {}) - expect(ast.imports).toContain(TO_STRING) + expect(ast.helpers).toContain(TO_STRING) }) test('should inject createVNode and Comment for comments', () => { const ast = parse(``) transform(ast, {}) - expect(ast.imports).toContain(CREATE_VNODE) - expect(ast.imports).toContain(COMMENT) + expect(ast.helpers).toContain(CREATE_VNODE) + expect(ast.helpers).toContain(COMMENT) }) describe('root codegenNode', () => { @@ -256,11 +256,11 @@ describe('compiler: transform', () => { expressions: [ { type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${OPEN_BLOCK}` + callee: OPEN_BLOCK }, { type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${CREATE_BLOCK}`, + callee: CREATE_BLOCK, arguments: args } ] @@ -277,7 +277,7 @@ describe('compiler: transform', () => { expect(ast.codegenNode).toMatchObject({ codegenNode: { type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${RENDER_SLOT}` + callee: RENDER_SLOT } }) }) @@ -326,7 +326,7 @@ describe('compiler: transform', () => { const ast = transformWithCodegen(`
`) expect(ast.codegenNode).toMatchObject( createBlockMatcher([ - `_${FRAGMENT}`, + FRAGMENT, `null`, [ { type: NodeTypes.ELEMENT, tag: `div` }, diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index 37dfec292c3..d82f87ab242 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -12,7 +12,7 @@ import { RESOLVE_DIRECTIVE, APPLY_DIRECTIVES, TO_HANDLERS -} from '../../src/runtimeConstants' +} from '../../src/runtimeHelpers' import { CallExpression, NodeTypes, @@ -52,13 +52,13 @@ function parseWithElementTransform( describe('compiler: element transform', () => { test('import + resolve component', () => { const { root } = parseWithElementTransform(``) - expect(root.imports).toContain(RESOLVE_COMPONENT) - expect(root.statements[0]).toMatch(`${RESOLVE_COMPONENT}("Foo")`) + expect(root.helpers).toContain(RESOLVE_COMPONENT) + expect(root.components).toContain(`Foo`) }) test('static props', () => { const { node } = parseWithElementTransform(`
`) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments).toMatchObject([ `"div"`, createObjectMatcher({ @@ -70,7 +70,7 @@ describe('compiler: element transform', () => { test('props + children', () => { const { node } = parseWithElementTransform(`
`) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments).toMatchObject([ `"div"`, createObjectMatcher({ @@ -81,7 +81,7 @@ describe('compiler: element transform', () => { type: NodeTypes.ELEMENT, tag: 'span', codegenNode: { - callee: `_${CREATE_VNODE}`, + callee: CREATE_VNODE, arguments: [`"span"`] } } @@ -91,7 +91,7 @@ describe('compiler: element transform', () => { test('0 placeholder for children with no props', () => { const { node } = parseWithElementTransform(`
`) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments).toMatchObject([ `"div"`, `null`, @@ -100,7 +100,7 @@ describe('compiler: element transform', () => { type: NodeTypes.ELEMENT, tag: 'span', codegenNode: { - callee: `_${CREATE_VNODE}`, + callee: CREATE_VNODE, arguments: [`"span"`] } } @@ -111,8 +111,8 @@ describe('compiler: element transform', () => { test('v-bind="obj"', () => { const { root, node } = parseWithElementTransform(`
`) // single v-bind doesn't need mergeProps - expect(root.imports).not.toContain(MERGE_PROPS) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(root.helpers).not.toContain(MERGE_PROPS) + expect(node.callee).toBe(CREATE_VNODE) // should directly use `obj` in props position expect(node.arguments[1]).toMatchObject({ type: NodeTypes.SIMPLE_EXPRESSION, @@ -124,11 +124,11 @@ describe('compiler: element transform', () => { const { root, node } = parseWithElementTransform( `
` ) - expect(root.imports).toContain(MERGE_PROPS) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(root.helpers).toContain(MERGE_PROPS) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments[1]).toMatchObject({ type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${MERGE_PROPS}`, + callee: MERGE_PROPS, arguments: [ createObjectMatcher({ id: 'foo' @@ -145,11 +145,11 @@ describe('compiler: element transform', () => { const { root, node } = parseWithElementTransform( `
` ) - expect(root.imports).toContain(MERGE_PROPS) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(root.helpers).toContain(MERGE_PROPS) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments[1]).toMatchObject({ type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${MERGE_PROPS}`, + callee: MERGE_PROPS, arguments: [ { type: NodeTypes.SIMPLE_EXPRESSION, @@ -166,11 +166,11 @@ describe('compiler: element transform', () => { const { root, node } = parseWithElementTransform( `
` ) - expect(root.imports).toContain(MERGE_PROPS) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(root.helpers).toContain(MERGE_PROPS) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments[1]).toMatchObject({ type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${MERGE_PROPS}`, + callee: MERGE_PROPS, arguments: [ createObjectMatcher({ id: 'foo' @@ -190,18 +190,18 @@ describe('compiler: element transform', () => { const { root, node } = parseWithElementTransform( `
` ) - expect(root.imports).toContain(MERGE_PROPS) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(root.helpers).toContain(MERGE_PROPS) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments[1]).toMatchObject({ type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${MERGE_PROPS}`, + callee: MERGE_PROPS, arguments: [ createObjectMatcher({ id: 'foo' }), { type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${TO_HANDLERS}`, + callee: TO_HANDLERS, arguments: [ { type: NodeTypes.SIMPLE_EXPRESSION, @@ -220,18 +220,18 @@ describe('compiler: element transform', () => { const { root, node } = parseWithElementTransform( `
` ) - expect(root.imports).toContain(MERGE_PROPS) - expect(node.callee).toBe(`_${CREATE_VNODE}`) + expect(root.helpers).toContain(MERGE_PROPS) + expect(node.callee).toBe(CREATE_VNODE) expect(node.arguments[1]).toMatchObject({ type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${MERGE_PROPS}`, + callee: MERGE_PROPS, arguments: [ createObjectMatcher({ id: 'foo' }), { type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${TO_HANDLERS}`, + callee: TO_HANDLERS, arguments: [ { type: NodeTypes.SIMPLE_EXPRESSION, @@ -249,7 +249,7 @@ describe('compiler: element transform', () => { test('should handle plain