compile.spec.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import { baseCompile as compile } from '../src'
  2. import { SourceMapConsumer, RawSourceMap } from 'source-map'
  3. describe('compiler: integration tests', () => {
  4. const source = `
  5. <div id="foo" :class="bar.baz">
  6. {{ world.burn() }}
  7. <div v-if="ok">yes</div>
  8. <template v-else>no</template>
  9. <div v-for="(value, index) in list"><span>{{ value + index }}</span></div>
  10. </div>
  11. `.trim()
  12. interface Pos {
  13. line: number
  14. column: number
  15. name?: string
  16. }
  17. function getPositionInCode(
  18. code: string,
  19. token: string,
  20. expectName: string | boolean = false
  21. ): Pos {
  22. const generatedOffset = code.indexOf(token)
  23. let line = 1
  24. let lastNewLinePos = -1
  25. for (let i = 0; i < generatedOffset; i++) {
  26. if (code.charCodeAt(i) === 10 /* newline char code */) {
  27. line++
  28. lastNewLinePos = i
  29. }
  30. }
  31. const res: Pos = {
  32. line,
  33. column:
  34. lastNewLinePos === -1
  35. ? generatedOffset
  36. : generatedOffset - lastNewLinePos - 1
  37. }
  38. if (expectName) {
  39. res.name = typeof expectName === 'string' ? expectName : token
  40. }
  41. return res
  42. }
  43. test('function mode', async () => {
  44. const { code, map } = compile(source, {
  45. sourceMap: true,
  46. filename: `foo.vue`
  47. })
  48. expect(code).toMatchSnapshot()
  49. expect(map!.sources).toEqual([`foo.vue`])
  50. expect(map!.sourcesContent).toEqual([source])
  51. const consumer = await new SourceMapConsumer(map as RawSourceMap)
  52. expect(
  53. consumer.originalPositionFor(getPositionInCode(code, `id`))
  54. ).toMatchObject(getPositionInCode(source, `id`))
  55. expect(
  56. consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
  57. ).toMatchObject(getPositionInCode(source, `"foo"`))
  58. expect(
  59. consumer.originalPositionFor(getPositionInCode(code, `class:`))
  60. ).toMatchObject(getPositionInCode(source, `class=`))
  61. expect(
  62. consumer.originalPositionFor(getPositionInCode(code, `bar`))
  63. ).toMatchObject(getPositionInCode(source, `bar`))
  64. // without prefixIdentifiers: true, identifiers inside compound expressions
  65. // are mapped to closest parent expression.
  66. expect(
  67. consumer.originalPositionFor(getPositionInCode(code, `baz`))
  68. ).toMatchObject(getPositionInCode(source, `bar`))
  69. expect(
  70. consumer.originalPositionFor(getPositionInCode(code, `world`))
  71. ).toMatchObject(getPositionInCode(source, `world`))
  72. // without prefixIdentifiers: true, identifiers inside compound expressions
  73. // are mapped to closest parent expression.
  74. expect(
  75. consumer.originalPositionFor(getPositionInCode(code, `burn()`))
  76. ).toMatchObject(getPositionInCode(source, `world`))
  77. expect(
  78. consumer.originalPositionFor(getPositionInCode(code, `ok`))
  79. ).toMatchObject(getPositionInCode(source, `ok`))
  80. expect(
  81. consumer.originalPositionFor(getPositionInCode(code, `list`))
  82. ).toMatchObject(getPositionInCode(source, `list`))
  83. expect(
  84. consumer.originalPositionFor(getPositionInCode(code, `value`))
  85. ).toMatchObject(getPositionInCode(source, `value`))
  86. expect(
  87. consumer.originalPositionFor(getPositionInCode(code, `index`))
  88. ).toMatchObject(getPositionInCode(source, `index`))
  89. expect(
  90. consumer.originalPositionFor(getPositionInCode(code, `value + index`))
  91. ).toMatchObject(getPositionInCode(source, `value + index`))
  92. })
  93. test('function mode w/ prefixIdentifiers: true', async () => {
  94. const { code, map } = compile(source, {
  95. sourceMap: true,
  96. filename: `foo.vue`,
  97. prefixIdentifiers: true
  98. })
  99. expect(code).toMatchSnapshot()
  100. expect(map!.sources).toEqual([`foo.vue`])
  101. expect(map!.sourcesContent).toEqual([source])
  102. const consumer = await new SourceMapConsumer(map as RawSourceMap)
  103. expect(
  104. consumer.originalPositionFor(getPositionInCode(code, `id`))
  105. ).toMatchObject(getPositionInCode(source, `id`))
  106. expect(
  107. consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
  108. ).toMatchObject(getPositionInCode(source, `"foo"`))
  109. expect(
  110. consumer.originalPositionFor(getPositionInCode(code, `class:`))
  111. ).toMatchObject(getPositionInCode(source, `class=`))
  112. expect(
  113. consumer.originalPositionFor(getPositionInCode(code, `bar`))
  114. ).toMatchObject(getPositionInCode(source, `bar`))
  115. expect(
  116. consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
  117. ).toMatchObject(getPositionInCode(source, `bar`, true))
  118. expect(
  119. consumer.originalPositionFor(getPositionInCode(code, `baz`))
  120. ).toMatchObject(getPositionInCode(source, `baz`))
  121. expect(
  122. consumer.originalPositionFor(getPositionInCode(code, `world`, true))
  123. ).toMatchObject(getPositionInCode(source, `world`, `world`))
  124. expect(
  125. consumer.originalPositionFor(
  126. getPositionInCode(code, `_ctx.world`, `world`)
  127. )
  128. ).toMatchObject(getPositionInCode(source, `world`, `world`))
  129. expect(
  130. consumer.originalPositionFor(getPositionInCode(code, `burn()`))
  131. ).toMatchObject(getPositionInCode(source, `burn()`))
  132. expect(
  133. consumer.originalPositionFor(getPositionInCode(code, `ok`))
  134. ).toMatchObject(getPositionInCode(source, `ok`))
  135. expect(
  136. consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
  137. ).toMatchObject(getPositionInCode(source, `ok`, true))
  138. expect(
  139. consumer.originalPositionFor(getPositionInCode(code, `list`))
  140. ).toMatchObject(getPositionInCode(source, `list`))
  141. expect(
  142. consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
  143. ).toMatchObject(getPositionInCode(source, `list`, true))
  144. expect(
  145. consumer.originalPositionFor(getPositionInCode(code, `value`))
  146. ).toMatchObject(getPositionInCode(source, `value`))
  147. expect(
  148. consumer.originalPositionFor(getPositionInCode(code, `index`))
  149. ).toMatchObject(getPositionInCode(source, `index`))
  150. expect(
  151. consumer.originalPositionFor(getPositionInCode(code, `value + index`))
  152. ).toMatchObject(getPositionInCode(source, `value + index`))
  153. })
  154. test('module mode', async () => {
  155. const { code, map } = compile(source, {
  156. mode: 'module',
  157. sourceMap: true,
  158. filename: `foo.vue`
  159. })
  160. expect(code).toMatchSnapshot()
  161. expect(map!.sources).toEqual([`foo.vue`])
  162. expect(map!.sourcesContent).toEqual([source])
  163. const consumer = await new SourceMapConsumer(map as RawSourceMap)
  164. expect(
  165. consumer.originalPositionFor(getPositionInCode(code, `id`))
  166. ).toMatchObject(getPositionInCode(source, `id`))
  167. expect(
  168. consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
  169. ).toMatchObject(getPositionInCode(source, `"foo"`))
  170. expect(
  171. consumer.originalPositionFor(getPositionInCode(code, `class:`))
  172. ).toMatchObject(getPositionInCode(source, `class=`))
  173. expect(
  174. consumer.originalPositionFor(getPositionInCode(code, `bar`))
  175. ).toMatchObject(getPositionInCode(source, `bar`))
  176. expect(
  177. consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
  178. ).toMatchObject(getPositionInCode(source, `bar`, true))
  179. expect(
  180. consumer.originalPositionFor(getPositionInCode(code, `baz`))
  181. ).toMatchObject(getPositionInCode(source, `baz`))
  182. expect(
  183. consumer.originalPositionFor(getPositionInCode(code, `world`, true))
  184. ).toMatchObject(getPositionInCode(source, `world`, `world`))
  185. expect(
  186. consumer.originalPositionFor(
  187. getPositionInCode(code, `_ctx.world`, `world`)
  188. )
  189. ).toMatchObject(getPositionInCode(source, `world`, `world`))
  190. expect(
  191. consumer.originalPositionFor(getPositionInCode(code, `burn()`))
  192. ).toMatchObject(getPositionInCode(source, `burn()`))
  193. expect(
  194. consumer.originalPositionFor(getPositionInCode(code, `ok`))
  195. ).toMatchObject(getPositionInCode(source, `ok`))
  196. expect(
  197. consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
  198. ).toMatchObject(getPositionInCode(source, `ok`, true))
  199. expect(
  200. consumer.originalPositionFor(getPositionInCode(code, `list`))
  201. ).toMatchObject(getPositionInCode(source, `list`))
  202. expect(
  203. consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
  204. ).toMatchObject(getPositionInCode(source, `list`, true))
  205. expect(
  206. consumer.originalPositionFor(getPositionInCode(code, `value`))
  207. ).toMatchObject(getPositionInCode(source, `value`))
  208. expect(
  209. consumer.originalPositionFor(getPositionInCode(code, `index`))
  210. ).toMatchObject(getPositionInCode(source, `index`))
  211. expect(
  212. consumer.originalPositionFor(getPositionInCode(code, `value + index`))
  213. ).toMatchObject(getPositionInCode(source, `value + index`))
  214. })
  215. })