Merge pull request #683 from sveltejs/gh-681

hack sourcemap to mitigate confusion caused by missing data for each block
pull/689/merge
Rich Harris 7 years ago committed by GitHub
commit 71daf4fc2f

@ -20,11 +20,19 @@ export default function visitEachBlock(
? block.getUniqueName(`${each_block}_anchor`) ? block.getUniqueName(`${each_block}_anchor`)
: (node.next && node.next._state.name) || 'null'; : (node.next && node.next._state.name) || 'null';
// hack the sourcemap, so that if data is missing the bug
// is easy to find
let c = node.start + 3;
while (generator.source[c] !== 'e') c += 1;
generator.code.overwrite(c, c + 4, 'length');
const length = `[✂${c}-${c+4}✂]`;
const mountOrIntro = node._block.hasIntroMethod ? 'intro' : 'mount'; const mountOrIntro = node._block.hasIntroMethod ? 'intro' : 'mount';
const vars = { const vars = {
each_block, each_block,
create_each_block, create_each_block,
each_block_value, each_block_value,
length,
iterations, iterations,
params, params,
anchor, anchor,
@ -62,7 +70,7 @@ export default function visitEachBlock(
// TODO neaten this up... will end up with an empty line in the block // TODO neaten this up... will end up with an empty line in the block
block.builders.init.addBlock(deindent` block.builders.init.addBlock(deindent`
if ( !${each_block_value}.length ) { if ( !${each_block_value}.${length} ) {
${each_block_else} = ${node.else._block.name}( ${params}, #component ); ${each_block_else} = ${node.else._block.name}( ${params}, #component );
${each_block_else}.create(); ${each_block_else}.create();
} }
@ -79,9 +87,9 @@ export default function visitEachBlock(
if (node.else._block.hasUpdateMethod) { if (node.else._block.hasUpdateMethod) {
block.builders.update.addBlock(deindent` block.builders.update.addBlock(deindent`
if ( !${each_block_value}.length && ${each_block_else} ) { if ( !${each_block_value}.${length} && ${each_block_else} ) {
${each_block_else}.update( changed, ${params} ); ${each_block_else}.update( changed, ${params} );
} else if ( !${each_block_value}.length ) { } else if ( !${each_block_value}.${length} ) {
${each_block_else} = ${node.else._block.name}( ${params}, #component ); ${each_block_else} = ${node.else._block.name}( ${params}, #component );
${each_block_else}.create(); ${each_block_else}.create();
${each_block_else}.${mountOrIntro}( ${parentNode}, ${anchor} ); ${each_block_else}.${mountOrIntro}( ${parentNode}, ${anchor} );
@ -93,7 +101,7 @@ export default function visitEachBlock(
`); `);
} else { } else {
block.builders.update.addBlock(deindent` block.builders.update.addBlock(deindent`
if ( ${each_block_value}.length ) { if ( ${each_block_value}.${length} ) {
if ( ${each_block_else} ) { if ( ${each_block_else} ) {
${each_block_else}.unmount(); ${each_block_else}.unmount();
${each_block_else}.destroy(); ${each_block_else}.destroy();
@ -137,6 +145,7 @@ function keyed(
each_block, each_block,
create_each_block, create_each_block,
each_block_value, each_block_value,
length,
params, params,
anchor, anchor,
mountOrIntro, mountOrIntro,
@ -168,7 +177,7 @@ function keyed(
} }
block.builders.init.addBlock(deindent` block.builders.init.addBlock(deindent`
for ( var #i = 0; #i < ${each_block_value}.length; #i += 1 ) { for ( var #i = 0; #i < ${each_block_value}.${length}; #i += 1 ) {
var ${key} = ${each_block_value}[#i].${node.key}; var ${key} = ${each_block_value}[#i].${node.key};
var ${iteration} = ${lookup}[${key}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key} ); var ${iteration} = ${lookup}[${key}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key} );
@ -268,7 +277,7 @@ function keyed(
var discard_pile = []; var discard_pile = [];
for ( #i = 0; #i < ${each_block_value}.length; #i += 1 ) { for ( #i = 0; #i < ${each_block_value}.${length}; #i += 1 ) {
var ${key} = ${each_block_value}[#i].${node.key}; var ${key} = ${each_block_value}[#i].${node.key};
var ${iteration} = ${lookup}[${key}]; var ${iteration} = ${lookup}[${key}];
@ -357,6 +366,7 @@ function unkeyed(
{ {
create_each_block, create_each_block,
each_block_value, each_block_value,
length,
iterations, iterations,
params, params,
anchor, anchor,
@ -366,7 +376,7 @@ function unkeyed(
block.builders.init.addBlock(deindent` block.builders.init.addBlock(deindent`
var ${iterations} = []; var ${iterations} = [];
for ( var #i = 0; #i < ${each_block_value}.length; #i += 1 ) { for ( var #i = 0; #i < ${each_block_value}.${length}; #i += 1 ) {
${iterations}[#i] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component ); ${iterations}[#i] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component );
} }
`); `);
@ -453,14 +463,14 @@ function unkeyed(
${iterations}[#i].unmount(); ${iterations}[#i].unmount();
${iterations}[#i].destroy(); ${iterations}[#i].destroy();
} }
${iterations}.length = ${each_block_value}.length; ${iterations}.length = ${each_block_value}.${length};
`; `;
block.builders.update.addBlock(deindent` block.builders.update.addBlock(deindent`
var ${each_block_value} = ${snippet}; var ${each_block_value} = ${snippet};
if ( ${condition} ) { if ( ${condition} ) {
for ( var #i = ${start}; #i < ${each_block_value}.length; #i += 1 ) { for ( var #i = ${start}; #i < ${each_block_value}.${length}; #i += 1 ) {
${forLoopBody} ${forLoopBody}
} }

@ -1,7 +1,7 @@
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import assert from "assert"; import assert from "assert";
import { svelte, exists } from "../helpers.js"; import { svelte } from "../helpers.js";
import { SourceMapConsumer } from "source-map"; import { SourceMapConsumer } from "source-map";
import { getLocator } from "locate-character"; import { getLocator } from "locate-character";
@ -9,7 +9,8 @@ describe("sourcemaps", () => {
fs.readdirSync("test/sourcemaps/samples").forEach(dir => { fs.readdirSync("test/sourcemaps/samples").forEach(dir => {
if (dir[0] === ".") return; if (dir[0] === ".") return;
const solo = exists(`test/sourcemaps/samples/${dir}/solo`); // add .solo to a sample directory name to only run that test
const solo = /\.solo/.test(dir);
if (solo && process.env.CI) { if (solo && process.env.CI) {
throw new Error("Forgot to remove `solo: true` from test"); throw new Error("Forgot to remove `solo: true` from test");

@ -0,0 +1,3 @@
{{#each foo as bar}}
<span>{{bar}}</span>
{{/each}}

@ -0,0 +1,17 @@
export function test ({ assert, smc, locateInSource, locateInGenerated }) {
const expected = locateInSource( 'each' );
const loc = locateInGenerated( 'length' );
const actual = smc.originalPositionFor({
line: loc.line + 1,
column: loc.column
});
assert.deepEqual( actual, {
source: 'input.html',
name: null,
line: expected.line + 1,
column: expected.column
});
}
Loading…
Cancel
Save