Skip to content

Commit 82fc0f2

Browse files
authored
Merge branch 'master' into gh-654
2 parents dc97fa7 + fd77c40 commit 82fc0f2

File tree

72 files changed

+1133
-162
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1133
-162
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
src/shared
22
shared.js
3+
store.js
34
test/test.js
45
test/setup.js
56
**/_actual.js

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Svelte changelog
22

3+
## 1.43.1
4+
5+
* Fix parameterised transitions ([#962](https://github.com/sveltejs/svelte/issues/962))
6+
* Prevent boolean attributes breaking estree-walker expectations ([#961](https://github.com/sveltejs/svelte/issues/961))
7+
* Throw error on cyclical store computations ([#964](https://github.com/sveltejs/svelte/pull/964))
8+
9+
## 1.43.0
10+
11+
* Export `Store` class to manage global state ([#930](https://github.com/sveltejs/svelte/issues/930))
12+
* Recognise `aria-current` ([#953](https://github.com/sveltejs/svelte/pull/953))
13+
* Support SSR register options including `extensions` ([#939](https://github.com/sveltejs/svelte/issues/939))
14+
* Friendlier error for illegal contexts ([#934](https://github.com/sveltejs/svelte/issues/934))
15+
* Remove whitespace around `<:Window>` components ([#943](https://github.com/sveltejs/svelte/issues/943))
16+
317
## 1.42.1
418

519
* Correctly append items inside a slotted `each` block ([#932](https://github.com/sveltejs/svelte/pull/932))

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "svelte",
3-
"version": "1.42.1",
3+
"version": "1.43.1",
44
"description": "The magical disappearing UI framework",
55
"main": "compiler/svelte.js",
66
"files": [
77
"compiler",
88
"ssr",
99
"shared.js",
10+
"store.js",
1011
"README.md"
1112
],
1213
"scripts": {

src/generators/Generator.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,8 @@ function removeIndentation(
7272
// We need to tell estree-walker that it should always
7373
// look for an `else` block, otherwise it might get
7474
// the wrong idea about the shape of each/if blocks
75-
childKeys.EachBlock = [
76-
'children',
77-
'else'
78-
];
79-
80-
childKeys.IfBlock = [
81-
'children',
82-
'else'
83-
];
75+
childKeys.EachBlock = childKeys.IfBlock = ['children', 'else'];
76+
childKeys.Attribute = ['value'];
8477

8578
export default class Generator {
8679
ast: Parsed;
@@ -536,6 +529,9 @@ export default class Generator {
536529
(param: Node) =>
537530
param.type === 'AssignmentPattern' ? param.left.name : param.name
538531
);
532+
deps.forEach(dep => {
533+
this.expectedProperties.add(dep);
534+
});
539535
dependencies.set(key, deps);
540536
});
541537

@@ -762,6 +758,11 @@ export default class Generator {
762758
});
763759
this.skip();
764760
}
761+
762+
if (node.type === 'Transition' && node.expression) {
763+
node.metadata = contextualise(node.expression, contextDependencies, indexes);
764+
this.skip();
765+
}
765766
},
766767

767768
leave(node: Node, parent: Node) {

src/generators/dom/index.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,23 @@ export default function dom(
184184
const debugName = `<${generator.customElement ? generator.tag : name}>`;
185185

186186
// generate initial state object
187-
const globals = Array.from(generator.expectedProperties).filter(prop => globalWhitelist.has(prop));
187+
const expectedProperties = Array.from(generator.expectedProperties);
188+
const globals = expectedProperties.filter(prop => globalWhitelist.has(prop));
189+
const storeProps = options.store ? expectedProperties.filter(prop => prop[0] === '$') : [];
190+
188191
const initialState = [];
192+
189193
if (globals.length > 0) {
190194
initialState.push(`{ ${globals.map(prop => `${prop} : ${prop}`).join(', ')} }`);
191195
}
192196

197+
if (storeProps.length > 0) {
198+
initialState.push(`this.store._init([${storeProps.map(prop => `"${prop.slice(1)}"`)}])`);
199+
}
200+
193201
if (templateProperties.data) {
194202
initialState.push(`%data()`);
195-
} else if (globals.length === 0) {
203+
} else if (globals.length === 0 && storeProps.length === 0) {
196204
initialState.push('{}');
197205
}
198206

@@ -205,6 +213,7 @@ export default function dom(
205213
@init(this, options);
206214
${generator.usesRefs && `this.refs = {};`}
207215
this._state = @assign(${initialState.join(', ')});
216+
${storeProps.length > 0 && `this.store._add(this, [${storeProps.map(prop => `"${prop.slice(1)}"`)}]);`}
208217
${generator.metaBindings}
209218
${computations.length && `this._recompute({ ${Array.from(computationDeps).map(dep => `${dep}: 1`).join(', ')} }, this._state);`}
210219
${options.dev &&
@@ -215,7 +224,11 @@ export default function dom(
215224
${generator.bindingGroups.length &&
216225
`this._bindingGroups = [${Array(generator.bindingGroups.length).fill('[]').join(', ')}];`}
217226
218-
${templateProperties.ondestroy && `this._handlers.destroy = [%ondestroy]`}
227+
${(templateProperties.ondestroy || storeProps.length) && (
228+
`this._handlers.destroy = [${
229+
[templateProperties.ondestroy && `%ondestroy`, storeProps.length && `@removeFromStore`].filter(Boolean).join(', ')
230+
}];`
231+
)}
219232
220233
${generator.slots.size && `this._slotted = options.slots || {};`}
221234

src/generators/dom/visitors/Element/addBindings.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,19 @@ export default function addBindings(
195195

196196
const usesContext = group.bindings.some(binding => binding.handler.usesContext);
197197
const usesState = group.bindings.some(binding => binding.handler.usesState);
198+
const usesStore = group.bindings.some(binding => binding.handler.usesStore);
198199
const mutations = group.bindings.map(binding => binding.handler.mutation).filter(Boolean).join('\n');
199200

200201
const props = new Set();
202+
const storeProps = new Set();
201203
group.bindings.forEach(binding => {
202204
binding.handler.props.forEach(prop => {
203205
props.add(prop);
204206
});
207+
208+
binding.handler.storeProps.forEach(prop => {
209+
storeProps.add(prop);
210+
});
205211
}); // TODO use stringifyProps here, once indenting is fixed
206212

207213
// media bindings — awkward special case. The native timeupdate events
@@ -222,9 +228,11 @@ export default function addBindings(
222228
}
223229
${usesContext && `var context = ${node.var}._svelte;`}
224230
${usesState && `var state = #component.get();`}
231+
${usesStore && `var $ = #component.store.get();`}
225232
${needsLock && `${lock} = true;`}
226233
${mutations.length > 0 && mutations}
227-
#component.set({ ${Array.from(props).join(', ')} });
234+
${props.size > 0 && `#component.set({ ${Array.from(props).join(', ')} });`}
235+
${storeProps.size > 0 && `#component.store.set({ ${Array.from(storeProps).join(', ')} });`}
228236
${needsLock && `${lock} = false;`}
229237
}
230238
`);
@@ -307,6 +315,13 @@ function getEventHandler(
307315
dependencies: string[],
308316
value: string,
309317
) {
318+
let storeDependencies = [];
319+
320+
if (generator.options.store) {
321+
storeDependencies = dependencies.filter(prop => prop[0] === '$').map(prop => prop.slice(1));
322+
dependencies = dependencies.filter(prop => prop[0] !== '$');
323+
}
324+
310325
if (block.contexts.has(name)) {
311326
const tail = attribute.value.type === 'MemberExpression'
312327
? getTailSnippet(attribute.value)
@@ -318,8 +333,10 @@ function getEventHandler(
318333
return {
319334
usesContext: true,
320335
usesState: true,
336+
usesStore: storeDependencies.length > 0,
321337
mutation: `${list}[${index}]${tail} = ${value};`,
322-
props: dependencies.map(prop => `${prop}: state.${prop}`)
338+
props: dependencies.map(prop => `${prop}: state.${prop}`),
339+
storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`)
323340
};
324341
}
325342

@@ -336,16 +353,31 @@ function getEventHandler(
336353
return {
337354
usesContext: false,
338355
usesState: true,
356+
usesStore: storeDependencies.length > 0,
339357
mutation: `${snippet} = ${value}`,
340-
props: dependencies.map((prop: string) => `${prop}: state.${prop}`)
358+
props: dependencies.map((prop: string) => `${prop}: state.${prop}`),
359+
storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`)
341360
};
342361
}
343362

363+
let props;
364+
let storeProps;
365+
366+
if (generator.options.store && name[0] === '$') {
367+
props = [];
368+
storeProps = [`${name.slice(1)}: ${value}`];
369+
} else {
370+
props = [`${name}: ${value}`];
371+
storeProps = [];
372+
}
373+
344374
return {
345375
usesContext: false,
346376
usesState: false,
377+
usesStore: false,
347378
mutation: null,
348-
props: [`${name}: ${value}`]
379+
props,
380+
storeProps
349381
};
350382
}
351383

@@ -393,4 +425,4 @@ function isComputed(node: Node) {
393425
}
394426

395427
return false;
396-
}
428+
}

src/generators/dom/visitors/Element/addTransitions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default function addTransitions(
2121
if (intro === outro) {
2222
const name = block.getUniqueName(`${node.var}_transition`);
2323
const snippet = intro.expression
24-
? intro.expression.metadata.snippet
24+
? intro.metadata.snippet
2525
: '{}';
2626

2727
block.addVariable(name);
@@ -51,7 +51,7 @@ export default function addTransitions(
5151
if (intro) {
5252
block.addVariable(introName);
5353
const snippet = intro.expression
54-
? intro.expression.metadata.snippet
54+
? intro.metadata.snippet
5555
: '{}';
5656

5757
const fn = `%transitions-${intro.name}`; // TODO add built-in transitions?
@@ -76,7 +76,7 @@ export default function addTransitions(
7676
if (outro) {
7777
block.addVariable(outroName);
7878
const snippet = outro.expression
79-
? intro.expression.metadata.snippet
79+
? outro.metadata.snippet
8080
: '{}';
8181

8282
const fn = `%transitions-${outro.name}`;

src/generators/server-side-rendering/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,22 @@ export default function ssr(
7373
generator.stylesheet.render(options.filename, true);
7474

7575
// generate initial state object
76-
// TODO this doesn't work, because expectedProperties isn't populated
77-
const globals = Array.from(generator.expectedProperties).filter(prop => globalWhitelist.has(prop));
76+
const expectedProperties = Array.from(generator.expectedProperties);
77+
const globals = expectedProperties.filter(prop => globalWhitelist.has(prop));
78+
const storeProps = options.store ? expectedProperties.filter(prop => prop[0] === '$') : [];
79+
7880
const initialState = [];
7981
if (globals.length > 0) {
8082
initialState.push(`{ ${globals.map(prop => `${prop} : ${prop}`).join(', ')} }`);
8183
}
8284

85+
if (storeProps.length > 0) {
86+
initialState.push(`options.store._init([${storeProps.map(prop => `"${prop.slice(1)}"`)}])`);
87+
}
88+
8389
if (templateProperties.data) {
8490
initialState.push(`%data()`);
85-
} else if (globals.length === 0) {
91+
} else if (globals.length === 0 && storeProps.length === 0) {
8692
initialState.push('{}');
8793
}
8894

@@ -99,7 +105,7 @@ export default function ssr(
99105
return ${templateProperties.data ? `%data()` : `{}`};
100106
};
101107
102-
${name}.render = function(state, options) {
108+
${name}.render = function(state, options = {}) {
103109
state = Object.assign(${initialState.join(', ')});
104110
105111
${computations.map(

src/generators/server-side-rendering/visitors/Component.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ export default function visitComponent(
7979

8080
let open = `\${${expression}.render({${props}}`;
8181

82+
const options = [];
83+
if (generator.options.store) {
84+
options.push(`store: options.store`);
85+
}
86+
8287
if (node.children.length) {
8388
const appendTarget: AppendTarget = {
8489
slots: { default: '' },
@@ -95,11 +100,15 @@ export default function visitComponent(
95100
.map(name => `${name}: () => \`${appendTarget.slots[name]}\``)
96101
.join(', ');
97102

98-
open += `, { slotted: { ${slotted} } }`;
103+
options.push(`slotted: { ${slotted} }`);
99104

100105
generator.appendTargets.pop();
101106
}
102107

108+
if (options.length) {
109+
open += `, { ${options.join(', ')} }`;
110+
}
111+
103112
generator.append(open);
104113
generator.append(')}');
105114
}

0 commit comments

Comments
 (0)