2019-09-26 23:51:04 +08:00
|
|
|
import { baseCompile as compile } from '../src'
|
2019-09-25 11:01:57 +08:00
|
|
|
import { SourceMapConsumer, RawSourceMap } from 'source-map'
|
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
describe('compiler: integration tests', () => {
|
2019-09-26 07:17:45 +08:00
|
|
|
const source = `
|
2019-09-27 02:55:53 +08:00
|
|
|
<div id="foo" :class="bar.baz">
|
|
|
|
{{ world.burn() }}
|
2019-09-26 07:17:45 +08:00
|
|
|
<div v-if="ok">yes</div>
|
|
|
|
<template v-else>no</template>
|
2019-09-26 10:29:37 +08:00
|
|
|
<div v-for="(value, index) in list"><span>{{ value + index }}</span></div>
|
2019-09-26 07:17:45 +08:00
|
|
|
</div>
|
|
|
|
`.trim()
|
2019-09-25 11:01:57 +08:00
|
|
|
|
2019-09-26 22:13:46 +08:00
|
|
|
interface Pos {
|
|
|
|
line: number
|
|
|
|
column: number
|
|
|
|
name?: string
|
|
|
|
}
|
|
|
|
|
|
|
|
function getPositionInCode(
|
|
|
|
code: string,
|
|
|
|
token: string,
|
|
|
|
expectName: string | boolean = false
|
|
|
|
): Pos {
|
2019-09-26 10:29:37 +08:00
|
|
|
const generatedOffset = code.indexOf(token)
|
|
|
|
let line = 1
|
|
|
|
let lastNewLinePos = -1
|
|
|
|
for (let i = 0; i < generatedOffset; i++) {
|
|
|
|
if (code.charCodeAt(i) === 10 /* newline char code */) {
|
|
|
|
line++
|
|
|
|
lastNewLinePos = i
|
|
|
|
}
|
|
|
|
}
|
2019-09-26 22:13:46 +08:00
|
|
|
const res: Pos = {
|
2019-09-26 10:29:37 +08:00
|
|
|
line,
|
|
|
|
column:
|
|
|
|
lastNewLinePos === -1
|
|
|
|
? generatedOffset
|
|
|
|
: generatedOffset - lastNewLinePos - 1
|
|
|
|
}
|
2019-09-26 22:13:46 +08:00
|
|
|
if (expectName) {
|
|
|
|
res.name = typeof expectName === 'string' ? expectName : token
|
|
|
|
}
|
|
|
|
return res
|
2019-09-26 10:29:37 +08:00
|
|
|
}
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
test('function mode', async () => {
|
|
|
|
const { code, map } = compile(source, {
|
|
|
|
sourceMap: true,
|
|
|
|
filename: `foo.vue`
|
2019-09-26 07:17:45 +08:00
|
|
|
})
|
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`const { createVNode: _createVNode, toString: _toString, renderList: _renderList } = _Vue`
|
|
|
|
)
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
expect(map!.sources).toEqual([`foo.vue`])
|
|
|
|
expect(map!.sourcesContent).toEqual([source])
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
const consumer = await new SourceMapConsumer(map as RawSourceMap)
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `id`))
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `"foo"`))
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `class=`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `bar`))
|
|
|
|
|
2019-09-27 02:55:53 +08:00
|
|
|
// without prefixIdentifiers: true, identifiers inside compound expressions
|
|
|
|
// are mapped to closest parent expression.
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `bar`))
|
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `world`))
|
2019-09-27 02:55:53 +08:00
|
|
|
).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`))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `ok`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `list`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `value`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `index`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
2019-09-27 02:55:53 +08:00
|
|
|
).toMatchObject(getPositionInCode(source, `value + index`))
|
2019-09-26 07:17:45 +08:00
|
|
|
})
|
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
test('function mode w/ prefixIdentifiers: true', async () => {
|
|
|
|
const { code, map } = compile(source, {
|
|
|
|
sourceMap: true,
|
|
|
|
filename: `foo.vue`,
|
|
|
|
prefixIdentifiers: true
|
2019-09-26 07:17:45 +08:00
|
|
|
})
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(code).toMatch(`const { createVNode, toString, renderList } = Vue`)
|
|
|
|
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
expect(map!.sources).toEqual([`foo.vue`])
|
|
|
|
expect(map!.sourcesContent).toEqual([source])
|
|
|
|
|
|
|
|
const consumer = await new SourceMapConsumer(map as RawSourceMap)
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `id`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `"foo"`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `class=`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `bar`))
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `bar`, true))
|
2019-09-27 02:55:53 +08:00
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `baz`))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
|
2019-09-27 02:55:53 +08:00
|
|
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(
|
|
|
|
getPositionInCode(code, `_ctx.world`, `world`)
|
|
|
|
)
|
2019-09-27 02:55:53 +08:00
|
|
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `burn()`))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `ok`))
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `ok`, true))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `list`))
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `list`, true))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `value`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `index`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `value + index`))
|
2019-09-26 07:17:45 +08:00
|
|
|
})
|
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
test('module mode', async () => {
|
|
|
|
const { code, map } = compile(source, {
|
|
|
|
mode: 'module',
|
|
|
|
sourceMap: true,
|
|
|
|
filename: `foo.vue`
|
2019-09-26 07:17:45 +08:00
|
|
|
})
|
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`import { createVNode, toString, renderList } from "vue"`
|
|
|
|
)
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
expect(map!.sources).toEqual([`foo.vue`])
|
|
|
|
expect(map!.sourcesContent).toEqual([source])
|
2019-09-26 07:17:45 +08:00
|
|
|
|
2019-09-26 10:29:37 +08:00
|
|
|
const consumer = await new SourceMapConsumer(map as RawSourceMap)
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `id`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `"foo"`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `class=`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `bar`))
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `bar`, true))
|
2019-09-27 02:55:53 +08:00
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `baz`))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
|
2019-09-27 02:55:53 +08:00
|
|
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
2019-09-26 10:29:37 +08:00
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(
|
|
|
|
getPositionInCode(code, `_ctx.world`, `world`)
|
|
|
|
)
|
2019-09-27 02:55:53 +08:00
|
|
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `burn()`))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `ok`))
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `ok`, true))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `list`))
|
|
|
|
expect(
|
2019-09-26 22:13:46 +08:00
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `list`, true))
|
2019-09-26 10:29:37 +08:00
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `value`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `index`))
|
|
|
|
|
|
|
|
expect(
|
|
|
|
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
|
|
|
).toMatchObject(getPositionInCode(source, `value + index`))
|
|
|
|
})
|
|
|
|
})
|