Skip to content

Commit ffe040a

Browse files
authored
Merge pull request #491 from sveltejs/misc-fixes
Misc fixes
2 parents fc31d39 + 86413ef commit ffe040a

File tree

20 files changed

+397
-64
lines changed

20 files changed

+397
-64
lines changed

src/generators/Generator.js

+7-8
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default class Generator {
4040
// allow compiler to deconflict user's `import { get } from 'whatever'` and
4141
// Svelte's builtin `import { get, ... } from 'svelte/shared.js'`;
4242
this.importedNames = new Set();
43-
this._aliases = new Map();
43+
this.aliases = new Map();
4444
this._usedNames = new Set( [ name ] );
4545
}
4646

@@ -54,12 +54,11 @@ export default class Generator {
5454
}
5555

5656
alias ( name ) {
57-
if ( this._aliases.has( name ) ) {
58-
return this._aliases.get( name );
57+
if ( !this.aliases.has( name ) ) {
58+
this.aliases.set( name, this.getUniqueName( name ) );
5959
}
60-
const alias = this.getUniqueName( name );
61-
this._aliases.set( name, alias );
62-
return alias;
60+
61+
return this.aliases.get( name );
6362
}
6463

6564
contextualise ( block, expression, context, isEventHandler ) {
@@ -151,7 +150,7 @@ export default class Generator {
151150
};
152151
}
153152

154-
findDependencies ( contextDependencies, expression ) {
153+
findDependencies ( contextDependencies, indexes, expression ) {
155154
if ( expression._dependencies ) return expression._dependencies;
156155

157156
let scope = annotateWithScopes( expression );
@@ -170,7 +169,7 @@ export default class Generator {
170169

171170
if ( contextDependencies.has( name ) ) {
172171
dependencies.push( ...contextDependencies.get( name ) );
173-
} else {
172+
} else if ( !indexes.has( name ) ) {
174173
dependencies.push( name );
175174
}
176175

src/generators/dom/Block.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default class Block {
2929
destroy: new CodeBuilder()
3030
};
3131

32+
this.aliases = new Map();
3233
this.getUniqueName = this.generator.getUniqueNameMaker( options.params );
3334

3435
// unique names
@@ -61,6 +62,14 @@ export default class Block {
6162
}
6263
}
6364

65+
alias ( name ) {
66+
if ( !this.aliases.has( name ) ) {
67+
this.aliases.set( name, this.getUniqueName( name ) );
68+
}
69+
70+
return this.aliases.get( name );
71+
}
72+
6473
child ( options ) {
6574
return new Block( Object.assign( {}, this, options, { parent: this } ) );
6675
}
@@ -75,7 +84,7 @@ export default class Block {
7584
}
7685

7786
findDependencies ( expression ) {
78-
return this.generator.findDependencies( this.contextDependencies, expression );
87+
return this.generator.findDependencies( this.contextDependencies, this.indexes, expression );
7988
}
8089

8190
mount ( name, parentNode ) {

src/generators/dom/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default function dom ( parsed, source, options ) {
4343

4444
const { computations, hasJs, templateProperties, namespace } = generator.parseJs();
4545

46-
const block = preprocess( generator, parsed.html.children );
46+
const block = preprocess( generator, parsed.html );
4747

4848
const state = {
4949
namespace,

src/generators/dom/preprocess.js

+55-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Block from './Block.js';
2+
import { trimStart, trimEnd } from '../../utils/trim.js';
23

34
function isElseIf ( node ) {
45
return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
@@ -23,7 +24,7 @@ const preprocessors = {
2324
});
2425

2526
blocks.push( node._block );
26-
preprocessChildren( generator, node._block, node.children );
27+
preprocessChildren( generator, node._block, node );
2728

2829
if ( node._block.dependencies.size > 0 ) {
2930
dynamic = true;
@@ -38,7 +39,7 @@ const preprocessors = {
3839
});
3940

4041
blocks.push( node.else._block );
41-
preprocessChildren( generator, node.else._block, node.else.children );
42+
preprocessChildren( generator, node.else._block, node.else );
4243

4344
if ( node.else._block.dependencies.size > 0 ) {
4445
dynamic = true;
@@ -97,7 +98,7 @@ const preprocessors = {
9798
});
9899

99100
generator.blocks.push( node._block );
100-
preprocessChildren( generator, node._block, node.children );
101+
preprocessChildren( generator, node._block, node );
101102
block.addDependencies( node._block.dependencies );
102103
node._block.hasUpdateMethod = node._block.dependencies.size > 0;
103104

@@ -107,7 +108,7 @@ const preprocessors = {
107108
});
108109

109110
generator.blocks.push( node.else._block );
110-
preprocessChildren( generator, node.else._block, node.else.children );
111+
preprocessChildren( generator, node.else._block, node.else );
111112
node.else._block.hasUpdateMethod = node.else._block.dependencies.size > 0;
112113
}
113114
},
@@ -131,35 +132,56 @@ const preprocessors = {
131132

132133
const isComponent = generator.components.has( node.name ) || node.name === ':Self';
133134

134-
if ( isComponent ) {
135-
const name = block.getUniqueName( ( node.name === ':Self' ? generator.name : node.name ).toLowerCase() );
135+
if ( node.children.length ) {
136+
if ( isComponent ) {
137+
const name = block.getUniqueName( ( node.name === ':Self' ? generator.name : node.name ).toLowerCase() );
136138

137-
node._block = block.child({
138-
name: generator.getUniqueName( `create_${name}_yield_fragment` )
139-
});
139+
node._block = block.child({
140+
name: generator.getUniqueName( `create_${name}_yield_fragment` )
141+
});
140142

141-
generator.blocks.push( node._block );
142-
preprocessChildren( generator, node._block, node.children );
143-
block.addDependencies( node._block.dependencies );
144-
node._block.hasUpdateMethod = node._block.dependencies.size > 0;
145-
}
143+
generator.blocks.push( node._block );
144+
preprocessChildren( generator, node._block, node );
145+
block.addDependencies( node._block.dependencies );
146+
node._block.hasUpdateMethod = node._block.dependencies.size > 0;
147+
}
146148

147-
else {
148-
preprocessChildren( generator, block, node.children );
149+
else {
150+
preprocessChildren( generator, block, node );
151+
}
149152
}
150153
}
151154
};
152155

153156
preprocessors.RawMustacheTag = preprocessors.MustacheTag;
154157

155-
function preprocessChildren ( generator, block, children ) {
156-
children.forEach( child => {
158+
function preprocessChildren ( generator, block, node ) {
159+
// glue text nodes together
160+
const cleaned = [];
161+
let lastChild;
162+
163+
node.children.forEach( child => {
164+
if ( child.type === 'Comment' ) return;
165+
166+
if ( child.type === 'Text' && lastChild && lastChild.type === 'Text' ) {
167+
lastChild.data += child.data;
168+
lastChild.end = child.end;
169+
} else {
170+
cleaned.push( child );
171+
}
172+
173+
lastChild = child;
174+
});
175+
176+
node.children = cleaned;
177+
178+
cleaned.forEach( child => {
157179
const preprocess = preprocessors[ child.type ];
158180
if ( preprocess ) preprocess( generator, block, child );
159181
});
160182
}
161183

162-
export default function preprocess ( generator, children ) {
184+
export default function preprocess ( generator, node ) {
163185
const block = new Block({
164186
generator,
165187
name: generator.alias( 'create_main_fragment' ),
@@ -177,8 +199,21 @@ export default function preprocess ( generator, children ) {
177199
});
178200

179201
generator.blocks.push( block );
180-
preprocessChildren( generator, block, children );
202+
preprocessChildren( generator, block, node );
181203
block.hasUpdateMethod = block.dependencies.size > 0;
182204

205+
// trim leading and trailing whitespace from the top level
206+
const firstChild = node.children[0];
207+
if ( firstChild && firstChild.type === 'Text' ) {
208+
firstChild.data = trimStart( firstChild.data );
209+
if ( !firstChild.data ) node.children.shift();
210+
}
211+
212+
const lastChild = node.children[ node.children.length - 1 ];
213+
if ( lastChild && lastChild.type === 'Text' ) {
214+
lastChild.data = trimEnd( lastChild.data );
215+
if ( !lastChild.data ) node.children.pop();
216+
}
217+
183218
return block;
184219
}

src/generators/dom/visitors/Comment.js

-3
This file was deleted.

src/generators/dom/visitors/EachBlock.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default function visitEachBlock ( generator, block, state, node ) {
77
const create_each_block = node._block.name;
88
const each_block_value = node._block.listName;
99
const iterations = block.getUniqueName( `${each_block}_iterations` );
10-
const i = block.getUniqueName( `i` );
10+
const i = block.alias( `i` );
1111
const params = block.params.join( ', ' );
1212
const anchor = block.getUniqueName( `${each_block}_anchor` );
1313

@@ -188,7 +188,7 @@ function unkeyed ( generator, block, state, node, snippet, { create_each_block,
188188
` );
189189

190190
const dependencies = block.findDependencies( node.expression );
191-
const allDependencies = new Set( block.dependencies );
191+
const allDependencies = new Set( node._block.dependencies );
192192
dependencies.forEach( dependency => {
193193
allDependencies.add( dependency );
194194
});

src/generators/dom/visitors/IfBlock.js

+62-9
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,73 @@ function visitChildren ( generator, block, state, node ) {
4444
}
4545

4646
export default function visitIfBlock ( generator, block, state, node ) {
47-
const params = block.params.join( ', ' );
4847
const name = generator.getUniqueName( `if_block` );
49-
const getBlock = block.getUniqueName( `get_block` );
50-
const current_block = block.getUniqueName( `current_block` );
48+
const anchor = generator.getUniqueName( `${name}_anchor` );
49+
const params = block.params.join( ', ' );
50+
51+
const vars = { name, anchor, params };
52+
53+
block.createAnchor( anchor, state.parentNode );
5154

5255
const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) );
5356
const dynamic = branches.some( branch => branch.dynamic );
5457

55-
const anchor = `${name}_anchor`;
56-
block.createAnchor( anchor, state.parentNode );
58+
if ( node.else ) {
59+
compound( generator, block, state, node, branches, dynamic, vars );
60+
} else {
61+
simple( generator, block, state, node, branches[0], dynamic, vars );
62+
}
63+
64+
block.builders.destroy.addLine(
65+
`if ( ${name} ) ${name}.destroy( ${state.parentNode ? 'false' : 'detach'} );`
66+
);
67+
}
68+
69+
function simple ( generator, block, state, node, branch, dynamic, { name, anchor, params } ) {
70+
block.builders.create.addBlock( deindent`
71+
var ${name} = ${branch.condition} && ${branch.block}( ${params}, ${block.component} );
72+
` );
73+
74+
const isToplevel = !state.parentNode;
75+
76+
if ( isToplevel ) {
77+
block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` );
78+
} else {
79+
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, ${anchor} );` );
80+
}
81+
82+
if ( dynamic ) {
83+
block.builders.update.addBlock( deindent`
84+
if ( ${branch.condition} ) {
85+
if ( ${name} ) {
86+
${name}.update( changed, ${params} );
87+
} else {
88+
${name} = ${branch.block}( ${params}, ${block.component} );
89+
${name}.mount( ${anchor}.parentNode, ${anchor} );
90+
}
91+
} else if ( ${name} ) {
92+
${name}.destroy( true );
93+
${name} = null;
94+
}
95+
` );
96+
} else {
97+
block.builders.update.addBlock( deindent`
98+
if ( ${branch.condition} ) {
99+
if ( !${name} ) {
100+
${name} = ${branch.block}( ${params}, ${block.component} );
101+
${name}.mount( ${anchor}.parentNode, ${anchor} );
102+
}
103+
} else if ( ${name} ) {
104+
${name}.destroy( true );
105+
${name} = null;
106+
}
107+
` );
108+
}
109+
}
110+
111+
function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) {
112+
const getBlock = block.getUniqueName( `get_block` );
113+
const current_block = block.getUniqueName( `current_block` );
57114

58115
block.builders.create.addBlock( deindent`
59116
function ${getBlock} ( ${params} ) {
@@ -93,8 +150,4 @@ export default function visitIfBlock ( generator, block, state, node ) {
93150
}
94151
` );
95152
}
96-
97-
block.builders.destroy.addLine(
98-
`if ( ${name} ) ${name}.destroy( ${isToplevel ? 'detach' : 'false'} );`
99-
);
100153
}

src/generators/dom/visitors/index.js

-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import Comment from './Comment.js';
21
import EachBlock from './EachBlock.js';
32
import Element from './Element/Element.js';
43
import IfBlock from './IfBlock.js';
@@ -8,7 +7,6 @@ import Text from './Text.js';
87
import YieldTag from './YieldTag.js';
98

109
export default {
11-
Comment,
1210
EachBlock,
1311
Element,
1412
IfBlock,

src/parse/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { locate } from 'locate-character';
22
import fragment from './state/fragment.js';
3-
import { whitespace } from './patterns.js';
4-
import { trimStart, trimEnd } from './utils/trim.js';
3+
import { whitespace } from '../utils/patterns.js';
4+
import { trimStart, trimEnd } from '../utils/trim.js';
55
import getCodeFrame from '../utils/getCodeFrame.js';
66
import hash from './utils/hash.js';
77

src/parse/state/mustache.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import readExpression from '../read/expression.js';
2-
import { whitespace } from '../patterns.js';
3-
import { trimStart, trimEnd } from '../utils/trim.js';
2+
import { whitespace } from '../../utils/patterns.js';
3+
import { trimStart, trimEnd } from '../../utils/trim.js';
44

55
const validIdentifier = /[a-zA-Z_$][a-zA-Z0-9_$]*/;
66

src/parse/state/tag.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import readExpression from '../read/expression.js';
22
import readScript from '../read/script.js';
33
import readStyle from '../read/style.js';
44
import { readEventHandlerDirective, readBindingDirective } from '../read/directives.js';
5-
import { trimStart, trimEnd } from '../utils/trim.js';
5+
import { trimStart, trimEnd } from '../../utils/trim.js';
66
import { decodeCharacterReferences } from '../utils/html.js';
77
import isVoidElementName from '../../utils/isVoidElementName.js';
88

src/utils/CodeBuilder.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default class CodeBuilder {
1616
this.result += `\n\t${line}`;
1717
} else {
1818
if ( this.lastCondition ) {
19-
this.result += `\n}`;
19+
this.result += `\n}\n\n`;
2020
}
2121

2222
this.result += `if ( ${condition} ) {\n\t${line}`;
File renamed without changes.

src/parse/utils/trim.js src/utils/trim.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { whitespace } from '../patterns.js';
1+
import { whitespace } from './patterns.js';
22

33
export function trimStart ( str ) {
44
let i = 0;

0 commit comments

Comments
 (0)