const { createVNode: _createVNode, toString: _toString, renderList: _renderList } = _Vue
return _createVNode(\\"div\\", {
id: \\"foo\\",
- class: bar
+ class: bar.baz
}, [
- _toString(world),
+ _toString(world.burn()),
ok
? _createVNode(\\"div\\", 0, \\"yes\\")
: \\"no\\",
}"
`;
-exports[`compiler: integration tests function mode 2`] = `
-Object {
- "mappings": ";;;;WAAA,oBAAA;MAAK,IAAG;MAAO,OAAO;;gBACpB;MACW;UAAX,uBAAe;UACE;MACjB,YAA8B,OAAjB,OAAO;eAApB,wBAAoC,kCAAM",
- "names": Array [],
- "sources": Array [
- "foo.vue",
- ],
- "sourcesContent": Array [
- "<div id=\\"foo\\" :class=\\"bar\\">
- {{ world }}
- <div v-if=\\"ok\\">yes</div>
- <template v-else>no</template>
- <div v-for=\\"(value, index) in list\\"><span>{{ value + index }}</span></div>
-</div>",
- ],
- "version": 3,
-}
-`;
-
exports[`compiler: integration tests function mode w/ prefixIdentifiers: true 1`] = `
"const { createVNode, toString, renderList } = Vue
const _ctx = this
return createVNode(\\"div\\", {
id: \\"foo\\",
- class: _ctx.bar
+ class: _ctx.bar.baz
}, [
- toString(_ctx.world),
+ toString(_ctx.world.burn()),
(_ctx.ok)
? createVNode(\\"div\\", 0, \\"yes\\")
: \\"no\\",
}"
`;
-exports[`compiler: integration tests function mode w/ prefixIdentifiers: true 2`] = `
-Object {
- "mappings": ";;;;SAAA,mBAAA;IAAK,IAAG;IAAO,OAAOA;;aACpBC;KACWC;QAAX,sBAAe;QACE;IACjB,WAA8BC,YAAjB,OAAO;aAApB,uBAAoC,gCAAS,QAAQ",
- "names": Array [
- "bar",
- "world",
- "ok",
- "list",
- ],
- "sources": Array [
- "foo.vue",
- ],
- "sourcesContent": Array [
- "<div id=\\"foo\\" :class=\\"bar\\">
- {{ world }}
- <div v-if=\\"ok\\">yes</div>
- <template v-else>no</template>
- <div v-for=\\"(value, index) in list\\"><span>{{ value + index }}</span></div>
-</div>",
- ],
- "version": 3,
-}
-`;
-
exports[`compiler: integration tests module mode 1`] = `
"import { createVNode, toString, renderList } from \\"vue\\"
const _ctx = this
return createVNode(\\"div\\", {
id: \\"foo\\",
- class: _ctx.bar
+ class: _ctx.bar.baz
}, [
- _toString(_ctx.world),
+ _toString(_ctx.world.burn()),
(_ctx.ok)
? createVNode(\\"div\\", 0, \\"yes\\")
: \\"no\\",
"isStatic": false,
"loc": Object {
"end": Object {
- "column": 20,
+ "column": 18,
"line": 1,
- "offset": 19,
+ "offset": 17,
},
- "source": "{{a < b}}",
+ "source": "a < b",
"start": Object {
- "column": 11,
+ "column": 13,
"line": 1,
- "offset": 10,
+ "offset": 12,
},
},
"type": 4,
"isStatic": false,
"loc": Object {
"end": Object {
- "column": 23,
+ "column": 21,
"line": 1,
- "offset": 22,
+ "offset": 20,
},
- "source": "{{'</div>'}}",
+ "source": "'</div>'",
"start": Object {
- "column": 11,
+ "column": 13,
"line": 1,
- "offset": 10,
+ "offset": 12,
},
},
"type": 4,
"isStatic": true,
"loc": Object {
"end": Object {
- "column": 5,
+ "column": 3,
"line": 1,
- "offset": 4,
+ "offset": 2,
},
- "source": "{{}}",
+ "source": "",
"start": Object {
- "column": 1,
+ "column": 3,
"line": 1,
- "offset": 0,
+ "offset": 2,
},
},
"type": 4,
"line": 1,
"offset": 32,
},
- "source": "\\"{ some: condition }\\"",
+ "source": "{ some: condition }",
"start": Object {
"column": 14,
"line": 1,
"line": 2,
"offset": 70,
},
- "source": "\\"{ color: 'red' }\\"",
+ "source": "{ color: 'red' }",
"start": Object {
"column": 18,
"line": 2,
"line": 2,
"offset": 70,
},
- "source": "\\"{ color: 'red' }\\"",
+ "source": "{ color: 'red' }",
"start": Object {
"column": 20,
"line": 2,
"line": 1,
"offset": 32,
},
- "source": "\\"{ some: condition }\\"",
+ "source": "{ some: condition }",
"start": Object {
"column": 14,
"line": 1,
describe('compiler: integration tests', () => {
const source = `
-<div id="foo" :class="bar">
- {{ world }}
+<div id="foo" :class="bar.baz">
+ {{ world.burn() }}
<div v-if="ok">yes</div>
<template v-else>no</template>
<div v-for="(value, index) in list"><span>{{ value + index }}</span></div>
)
expect(code).toMatchSnapshot()
- expect(map).toMatchSnapshot()
expect(map!.sources).toEqual([`foo.vue`])
expect(map!.sourcesContent).toEqual([source])
consumer.originalPositionFor(getPositionInCode(code, `bar`))
).toMatchObject(getPositionInCode(source, `bar`))
+ // without prefixIdentifiers: true, identifiers inside compound expressions
+ // are mapped to closest parent expression.
+ expect(
+ consumer.originalPositionFor(getPositionInCode(code, `baz`))
+ ).toMatchObject(getPositionInCode(source, `bar`))
+
expect(
consumer.originalPositionFor(getPositionInCode(code, `world`))
- ).toMatchObject(getPositionInCode(source, `{{ world }}`))
+ ).toMatchObject(getPositionInCode(source, `world`))
+
+ // without prefixIdentifiers: true, identifiers inside compound expressions
+ // are mapped to closest parent expression.
+ expect(
+ consumer.originalPositionFor(getPositionInCode(code, `burn()`))
+ ).toMatchObject(getPositionInCode(source, `world`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `ok`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
- ).toMatchObject(getPositionInCode(source, `{{ value + index }}`))
+ ).toMatchObject(getPositionInCode(source, `value + index`))
})
test('function mode w/ prefixIdentifiers: true', async () => {
expect(code).toMatch(`const { createVNode, toString, renderList } = Vue`)
expect(code).toMatchSnapshot()
- expect(map).toMatchSnapshot()
expect(map!.sources).toEqual([`foo.vue`])
expect(map!.sourcesContent).toEqual([source])
expect(
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
).toMatchObject(getPositionInCode(source, `bar`, true))
+ expect(
+ consumer.originalPositionFor(getPositionInCode(code, `baz`))
+ ).toMatchObject(getPositionInCode(source, `baz`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
- ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
+ ).toMatchObject(getPositionInCode(source, `world`, `world`))
expect(
consumer.originalPositionFor(
getPositionInCode(code, `_ctx.world`, `world`)
)
- ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
+ ).toMatchObject(getPositionInCode(source, `world`, `world`))
+
+ expect(
+ consumer.originalPositionFor(getPositionInCode(code, `burn()`))
+ ).toMatchObject(getPositionInCode(source, `burn()`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `ok`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
).toMatchObject(getPositionInCode(source, `bar`, true))
+ expect(
+ consumer.originalPositionFor(getPositionInCode(code, `baz`))
+ ).toMatchObject(getPositionInCode(source, `baz`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
- ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
+ ).toMatchObject(getPositionInCode(source, `world`, `world`))
expect(
consumer.originalPositionFor(
getPositionInCode(code, `_ctx.world`, `world`)
)
- ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
+ ).toMatchObject(getPositionInCode(source, `world`, `world`))
+
+ expect(
+ consumer.originalPositionFor(getPositionInCode(code, `burn()`))
+ ).toMatchObject(getPositionInCode(source, `burn()`))
expect(
consumer.originalPositionFor(getPositionInCode(code, `ok`))
isStatic: false,
isInterpolation: true,
loc: {
- start: { offset: 0, line: 1, column: 1 },
- end: { offset: 11, line: 1, column: 12 },
- source: '{{message}}'
+ start: { offset: 2, line: 1, column: 3 },
+ end: { offset: 9, line: 1, column: 10 },
+ source: 'message'
}
})
})
isStatic: false,
isInterpolation: true,
loc: {
- start: { offset: 0, line: 1, column: 1 },
- end: { offset: 9, line: 1, column: 10 },
- source: '{{ a<b }}'
+ start: { offset: 3, line: 1, column: 4 },
+ end: { offset: 6, line: 1, column: 7 },
+ source: 'a<b'
}
})
})
isStatic: false,
isInterpolation: true,
loc: {
- start: { offset: 0, line: 1, column: 1 },
- end: { offset: 9, line: 1, column: 10 },
- source: '{{ a<b }}'
+ start: { offset: 3, line: 1, column: 4 },
+ end: { offset: 6, line: 1, column: 7 },
+ source: 'a<b'
}
})
expect(interpolation2).toStrictEqual({
isStatic: false,
isInterpolation: true,
loc: {
- start: { offset: 9, line: 1, column: 10 },
- end: { offset: 18, line: 1, column: 19 },
- source: '{{ c>d }}'
+ start: { offset: 12, line: 1, column: 13 },
+ end: { offset: 15, line: 1, column: 16 },
+ source: 'c>d'
}
})
})
isStatic: false,
isInterpolation: true,
loc: {
- start: { offset: 5, line: 1, column: 6 },
- end: { offset: 19, line: 1, column: 20 },
- source: '{{ "</div>" }}'
+ start: { offset: 8, line: 1, column: 9 },
+ end: { offset: 16, line: 1, column: 17 },
+ source: '"</div>"'
}
})
})
loc: {
start: { offset: 11, line: 1, column: 12 },
end: { offset: 12, line: 1, column: 13 },
- source: '"a"'
+ source: 'a'
}
},
loc: {
offset += foo.loc.source.length
expect(foo.loc.end).toEqual({ line: 2, column: 5, offset })
- expect(bar.loc.start).toEqual({ line: 2, column: 5, offset })
+ offset += 3
+ expect(bar.loc.start).toEqual({ line: 2, column: 8, offset })
offset += bar.loc.source.length
- expect(bar.loc.end).toEqual({ line: 2, column: 14, offset })
+ expect(bar.loc.end).toEqual({ line: 2, column: 11, offset })
+ offset += 3
expect(but.loc.start).toEqual({ line: 2, column: 14, offset })
offset += but.loc.source.length
expect(but.loc.end).toEqual({ line: 2, column: 19, offset })
- expect(baz.loc.start).toEqual({ line: 2, column: 19, offset })
+ offset += 3
+ expect(baz.loc.start).toEqual({ line: 2, column: 22, offset })
offset += baz.loc.source.length
- expect(baz.loc.end).toEqual({ line: 2, column: 28, offset })
+ expect(baz.loc.end).toEqual({ line: 2, column: 25, offset })
})
describe('namedCharacterReferences option', () => {
indentLevel: number
map?: SourceMapGenerator
helper(name: string): string
- push(code: string, node?: CodegenNode): void
+ push(code: string, node?: CodegenNode, openOnly?: boolean): void
indent(): void
deindent(withoutNewLine?: boolean): void
newline(): void
helper(name) {
return prefixIdentifiers ? name : `_${name}`
},
- push(code, node?: CodegenNode) {
+ push(code, node, openOnly) {
context.code += code
if (context.map) {
if (node) {
})
}
advancePositionWithMutation(context, code)
+ if (node && !openOnly) {
+ context.map.addMapping({
+ source: context.filename,
+ original: {
+ line: node.loc.end.line,
+ column: node.loc.end.column - 1
+ },
+ generated: {
+ line: context.line,
+ column: context.column - 1
+ }
+ })
+ }
}
},
indent() {
function genFor(node: ForNode, context: CodegenContext) {
const { push, helper, indent, deindent } = context
const { source, keyAlias, valueAlias, objectIndexAlias, children } = node
- push(`${helper(RENDER_LIST)}(`, node)
+ push(`${helper(RENDER_LIST)}(`, node, true)
genExpression(source, context)
push(`, (`)
if (valueAlias) {
context: CodegenContext,
multilines = node.arguments.length > 2
) {
- context.push(node.callee + `(`, node)
+ context.push(node.callee + `(`, node, true)
multilines && context.indent()
genNodeList(node.arguments, context, multilines)
multilines && context.deindent()
const { push, indent, deindent, newline } = context
const { properties } = node
const multilines = properties.length > 1
- push(multilines ? `{` : `{ `, node)
+ push(multilines ? `{` : `{ `)
multilines && indent()
for (let i = 0; i < properties.length; i++) {
const { key, value } = properties[i]
valueLoc.start.offset++
valueLoc.start.column++
valueLoc.end = advancePositionWithClone(valueLoc.start, value.content)
+ valueLoc.source = valueLoc.source.slice(1, -1)
}
return {
return undefined
}
- const start = getCursor(context)
advanceBy(context, open.length)
- const content = parseTextData(context, closeIndex - open.length, mode).trim()
+ const start = getCursor(context)
+ const end = getCursor(context)
+ const rawContentLength = closeIndex - open.length
+ const rawContent = context.source.slice(0, rawContentLength)
+ const preTrimContent = parseTextData(context, rawContentLength, mode)
+ const content = preTrimContent.trim()
+ const startOffset = preTrimContent.indexOf(content)
+ if (startOffset > 0) {
+ advancePositionWithMutation(start, rawContent, startOffset)
+ }
+ const endOffset =
+ rawContentLength - (preTrimContent.length - content.length - startOffset)
+ advancePositionWithMutation(end, rawContent, endOffset)
advanceBy(context, close.length)
return {
type: NodeTypes.EXPRESSION,
content,
- loc: getSelection(context, start),
+ loc: getSelection(context, start, end),
isStatic: content === '',
isInterpolation: true
}
children.push(
createExpression(id.name, false, {
source,
- start: advancePositionWithClone(node.loc.start, source, id.start + 2),
- end: advancePositionWithClone(node.loc.start, source, id.end + 2)
+ start: advancePositionWithClone(node.loc.start, source, id.start - 1),
+ end: advancePositionWithClone(node.loc.start, source, id.end - 1)
})
)
if (i === ids.length - 1 && id.end - 1 < full.length) {
isStatic: false,
isInterpolation: true,
loc: {
- start: { offset: 5, line: 1, column: 6 },
- end: { offset: 19, line: 1, column: 20 },
- source: '{{ a < b }}'
+ start: { offset: 8, line: 1, column: 9 },
+ end: { offset: 16, line: 1, column: 17 },
+ source: 'a < b'
}
})
})