Merge branch 'master' into pr/5398

pull/5398/head
Conduitry 5 years ago
commit 1e9925baa9

@ -1,10 +0,0 @@
module.exports = Object.assign(
{},
require('./mocharc.js'),
{
fullTrace: true,
require: [
'source-map-support/register'
]
}
);

@ -3,3 +3,13 @@ module.exports = {
'test/test.js'
]
};
// add coverage options when running 'npx c8 mocha'
if (process.env.NODE_V8_COVERAGE) {
Object.assign(module.exports, {
fullTrace: true,
require: [
'source-map-support/register'
]
});
}

@ -1,5 +1,19 @@
# Svelte changelog
## Unreleased
* Support `_` as numeric separator ([#5407](https://github.com/sveltejs/svelte/issues/5407))
* Fix assignments to properties on store values ([#5412](https://github.com/sveltejs/svelte/issues/5412))
* Support `import.meta` in template expressions ([#5422](https://github.com/sveltejs/svelte/issues/5422))
## 3.25.1
* Fix specificity of certain styles involving a child selector ([#4795](https://github.com/sveltejs/svelte/issues/4795))
* Fix transitions that are parameterised with stores ([#5244](https://github.com/sveltejs/svelte/issues/5244))
* Fix scoping of styles involving child selector and `*` ([#5370](https://github.com/sveltejs/svelte/issues/5370))
* Fix destructuring which reassigns stores ([#5388](https://github.com/sveltejs/svelte/issues/5388))
* Fix `{#await}`s with no `{:catch}` getting stuck unresolved if the promise rejects ([#5401](https://github.com/sveltejs/svelte/issues/5401))
## 3.25.0
* Use `null` rather than `undefined` for coerced bound value of `<input type="number">` ([#1701](https://github.com/sveltejs/svelte/issues/1701))

8
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.25.0",
"version": "3.25.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -315,9 +315,9 @@
"dev": true
},
"acorn": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
"integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
"dev": true
},
"acorn-globals": {

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.25.0",
"version": "3.25.1",
"description": "Cybernetically enhanced web apps",
"module": "index.mjs",
"main": "index",
@ -23,10 +23,10 @@
},
"types": "types/runtime/index.d.ts",
"scripts": {
"test": "mocha --config .mocharc.js",
"test": "mocha",
"test:unit": "mocha --require sucrase/register --recursive src/**/__test__.ts",
"quicktest": "mocha --config .mocharc.js",
"precoverage": "c8 mocha --config .mocharc.coverage.js",
"quicktest": "mocha",
"precoverage": "c8 mocha",
"coverage": "c8 report --reporter=text-lcov > coverage.lcov && c8 report --reporter=html",
"codecov": "codecov",
"precodecov": "npm run coverage",
@ -68,7 +68,7 @@
"@types/node": "^8.10.53",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
"acorn": "^7.3.1",
"acorn": "^7.4.0",
"agadoo": "^1.1.0",
"c8": "^5.0.1",
"code-red": "^0.1.3",

@ -6,9 +6,9 @@ Rich Harris, the creator of Svelte, taught a course:
- [Frontend Masters](https://frontendmasters.com/courses/svelte/)
There are also a couple of third-party courses:
There are also a number of third-party courses:
- [Egghead](https://egghead.io/playlists/getting-started-with-svelte-3-05a8541a)
- [Udemy](https://www.udemy.com/sveltejs-the-complete-guide/)
- [Egghead](https://egghead.io/browse/frameworks/svelte)
- [Udemy](https://www.udemy.com/courses/search/?q=sveltejs+svelte)
Note that Udemy very frequently has discounts over 90%.

@ -0,0 +1,9 @@
---
question: Are there any books?
---
There are a few books:
- [Svelte Handbook](https://flaviocopes.com/page/download-svelte-handbook/) by Flavio Copes
- [Svelte 3 Up and Running](https://www.amazon.com/dp/B08D6T6BKS/) by Alessandro Segala
- [Svelte and Sapper in Action](https://www.manning.com/books/svelte-and-sapper-in-action) by R. Mark Volkmann

@ -62,7 +62,6 @@
<style>
main {
height: 100%;
position: relative;
margin: 0 auto;
/* padding: var(--nav-h) var(--side-nav) 0 var(--side-nav); */

@ -117,7 +117,7 @@
<style>
.repl-outer {
position: relative;
height: 100%;
height: calc(100vh - var(--nav-h));
--app-controls-h: 5.6rem;
--pane-controls-h: 4.2rem;
overflow: hidden;

@ -947,12 +947,6 @@ export default class Component {
const variable = component.var_lookup.get(name);
if (variable.export_name && variable.writable) {
const insert = variable.subscribable
? get_insert(variable)
: null;
parent[key].splice(index + 1, 0, insert);
declarator.id = {
type: 'ObjectPattern',
properties: [{
@ -973,7 +967,9 @@ export default class Component {
};
declarator.init = x`$$props`;
} else if (variable.subscribable) {
}
if (variable.subscribable && declarator.init) {
const insert = get_insert(variable);
parent[key].splice(index + 1, 0, ...insert);
}

@ -65,9 +65,8 @@ export default class Selector {
transform(code: MagicString, attr: string, max_amount_class_specificity_increased: number) {
const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
attr = attr.repeat(amount_class_specificity_to_increase + 1);
function encapsulate_block(block: Block) {
function encapsulate_block(block: Block, attr: string) {
let i = block.selectors.length;
while (i--) {
@ -89,15 +88,14 @@ export default class Selector {
}
}
this.blocks.forEach((block) => {
this.blocks.forEach((block, index) => {
if (block.global) {
const selector = block.selectors[0];
const first = selector.children[0];
const last = selector.children[selector.children.length - 1];
code.remove(selector.start, first.start).remove(last.end, selector.end);
}
if (block.should_encapsulate) encapsulate_block(block);
if (block.should_encapsulate) encapsulate_block(block, index === this.blocks.length - 1 ? attr.repeat(amount_class_specificity_to_increase + 1) : attr);
});
}
@ -152,7 +150,7 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
if (!block) return false;
if (!node) {
return blocks.every(block => block.global);
return block.global && blocks.every(block => block.global);
}
switch (block_might_apply_to_node(block, node)) {
@ -208,7 +206,7 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
return true;
}
function block_might_apply_to_node(block, node): BlockAppliesToNode {
function block_might_apply_to_node(block: Block, node: Element): BlockAppliesToNode {
let i = block.selectors.length;
while (i--) {

@ -34,7 +34,7 @@ export default class Transition extends Node {
}
this.expression = info.expression
? new Expression(component, this, scope, info.expression, true)
? new Expression(component, this, scope, info.expression)
: null;
}
}

@ -64,6 +64,8 @@ export default class Expression {
enter(node: any, parent: any, key: string) {
// don't manipulate shorthand props twice
if (key === 'value' && parent.shorthand) return;
// don't manipulate `import.meta`, `new.target`
if (node.type === 'MetaProperty') return this.skip();
if (map.has(node)) {
scope = map.get(node);

@ -166,12 +166,14 @@ export default class Renderer {
return member;
}
invalidate(name: string, value?) {
invalidate(name: string, value?, main_execution_context: boolean = false) {
const variable = this.component.var_lookup.get(name);
const member = this.context_lookup.get(name);
if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
return x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
return main_execution_context
? x`${`$$subscribe_${name}`}(${value || name})`
: x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
}
if (name[0] === '$' && name[1] !== '$') {

@ -31,10 +31,9 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
function get_invalidated(variable: Var, node?: Expression) {
if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
return node || x`${variable.name}`;
return node;
}
return renderer.invalidate(variable.name);
return renderer.invalidate(variable.name, undefined, main_execution_context);
}
if (head) {
@ -44,12 +43,15 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
return get_invalidated(head, node);
} else {
const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
const extra_args = tail.map(variable => get_invalidated(variable));
const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean);
const pass_value = (
!main_execution_context &&
(
extra_args.length > 0 ||
(node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
(node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'))
)
);
if (pass_value) {
@ -60,9 +62,11 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
}
let invalidate = is_store_value
? x`@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})`
? x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name})`
: !main_execution_context
? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`
: extra_args.length
? [node, ...extra_args]
: node;
if (head.subscribable && head.reassigned) {

@ -868,6 +868,10 @@ export default class ElementWrapper extends Wrapper {
block.chunks.destroy.push(b`if (detaching && ${outro_name}) ${outro_name}.end();`);
}
}
if ((intro && intro.expression && intro.expression.dependencies.size) || (outro && outro.expression && outro.expression.dependencies.size)) {
block.maintain_context = true;
}
}
add_animation(block: Block) {

@ -3,11 +3,12 @@ import * as code_red from 'code-red';
export const parse = (source: string): Node => code_red.parse(source, {
sourceType: 'module',
ecmaVersion: 11,
ecmaVersion: 12,
locations: true
});
export const parse_expression_at = (source: string, index: number): Node => code_red.parseExpressionAt(source, index, {
ecmaVersion: 11,
sourceType: 'module',
ecmaVersion: 12,
locations: true
});

@ -59,12 +59,12 @@ export function handle_promise(promise, info) {
update(info.then, 1, info.value, value);
set_current_component(null);
}, error => {
if (!info.hasCatch) {
throw error;
}
set_current_component(current_component);
update(info.catch, 2, info.error, error);
set_current_component(null);
if (!info.hasCatch) {
throw error;
}
});
// if we previously had a then/catch block, destroy it

@ -0,0 +1 @@
main.svelte-xyz button.svelte-xyz.svelte-xyz{background-color:red}main.svelte-xyz div.svelte-xyz>button.svelte-xyz{background-color:blue}

@ -0,0 +1,14 @@
<style>
main button {
background-color: red;
}
main div > button {
background-color: blue;
}
</style>
<main>
<div>
<button type="submit">Blue</button>
</div>
</main>

@ -0,0 +1,45 @@
export default {
warnings: [
{
code: "css-unused-selector",
message: 'Unused CSS selector "article > *"',
frame: `
1: <style>
2: article > * {
^
3: font-size: 36px;
4: }`,
pos: 10,
start: { character: 10, column: 1, line: 2 },
end: { character: 21, column: 12, line: 2 }
},
{
code: "css-unused-selector",
message: 'Unused CSS selector "article *"',
frame: `
4: }
5:
6: article * {
^
7: font-size: 36px;
8: }`,
pos: 49,
start: { character: 49, column: 1, line: 6 },
end: { character: 58, column: 10, line: 6 }
},
{
code: "css-unused-selector",
message: 'Unused CSS selector ".article > *"',
frame: `
8: }
9:
10: .article > * {
^
11: font-size: 48px;
12: }`,
pos: 86,
start: { character: 86, column: 1, line: 10 },
end: { character: 98, column: 13, line: 10 }
}
]
};

@ -0,0 +1 @@
div.svelte-xyz>.svelte-xyz{color:orange}

@ -0,0 +1,23 @@
<style>
article > * {
font-size: 36px;
}
article * {
font-size: 36px;
}
.article > * {
font-size: 48px;
}
div > * {
color: orange;
}
</style>
<div>
<p>
Svelte REPLs are svelte.
</p>
</div>

@ -0,0 +1,53 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
detach,
init,
insert,
noop,
safe_not_equal,
space,
text
} from "svelte/internal";
function create_fragment(ctx) {
let t0;
let t1;
let t2_value = import.meta.url + "";
let t2;
return {
c() {
t0 = text(/*url*/ ctx[0]);
t1 = space();
t2 = text(t2_value);
},
m(target, anchor) {
insert(target, t0, anchor);
insert(target, t1, anchor);
insert(target, t2, anchor);
},
p: noop,
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(t0);
if (detaching) detach(t1);
if (detaching) detach(t2);
}
};
}
function instance($$self) {
const url = import.meta.url;
return [url];
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}
export default Component;

@ -0,0 +1,6 @@
<script>
const url = import.meta.url;
</script>
{url}
{import.meta.url}

@ -39,6 +39,7 @@ export default {
})
.catch((err) => {
assert.equal(err.message, 'this error should be thrown');
assert.htmlEqual(target.innerHTML, '');
});
}
};

@ -0,0 +1,3 @@
export default {
html: `2048 2048`
};

@ -0,0 +1,5 @@
<script>
const num = 2_048;
</script>
{num} {2_048}

@ -0,0 +1,16 @@
<script>
import { writable } from 'svelte/store';
let eid = writable(1);
let foo;
let u;
let v;
let w;
[u, v, w] = [
{id: eid = writable(foo = 2), name: 'xxx'},
5,
writable(6)
];
</script>
<h1>{foo} {$eid} {u.name} {v} {$w}</h1>

@ -1,6 +1,9 @@
<script>
let foo;
let bar = (foo = 1);
function a() {
bar = (foo = 1);
}
</script>
<h1>{foo} {bar}</h1>

@ -4,6 +4,11 @@
for (let bar = (foo1 = 0); bar < 5; bar += 1) {
foo2 = foo1;
}
function a() {
for (let bar = (foo1 = 0); bar < 5; bar += 1) {
foo2 = foo1;
}
}
</script>
<h1>{foo1} {foo2}</h1>

@ -0,0 +1,32 @@
export default {
html: `
<p>a: {"foo":3,"bar":2}</p>
<p>b: {"foo":3}</p>
<button></button>
<button></button>
`,
skip_if_ssr: true,
async test({ assert, component, target, window }) {
const [btn1, btn2] = target.querySelectorAll('button');
const click = new window.MouseEvent('click');
await btn1.dispatchEvent(click);
assert.htmlEqual(target.innerHTML, `
<p>a: {"foo":4,"bar":2}</p>
<p>b: {"foo":4,"baz":0}</p>
<button></button>
<button></button>
`);
await btn2.dispatchEvent(click);
assert.htmlEqual(target.innerHTML, `
<p>a: {"foo":5,"bar":2}</p>
<p>b: {"foo":5,"qux":0}</p>
<button></button>
<button></button>
`);
}
};

@ -0,0 +1,24 @@
<script>
import { writable } from '../../../../store';
const a = writable({ foo: 1, bar: 2 });
$a.foo = 3;
const b = writable({ foo: 1, bar: 2 });
$b = { foo: 3 };
function update() {
$a.foo = $a.foo + 1;
$b = { foo: $b.foo + 1, qux: 0 };
}
</script>
<p>a: {JSON.stringify($a)}</p>
<p>b: {JSON.stringify($b)}</p>
<button on:click={() => {
$a.foo = $a.foo + 1;
$b = { foo: $b.foo + 1, baz: 0 };
}} />
<button on:click={update} />

@ -0,0 +1,3 @@
export default {
html: `31 42`
};

@ -0,0 +1,16 @@
<script>
import { writable } from 'svelte/store';
const context = {
store1: writable(31),
store2: writable(42)
};
let store1;
let store2;
({
store1,
store2
} = context);
</script>
{$store1}
{$store2}

@ -0,0 +1,15 @@
export default {
test({ assert, component, target, window, raf }) {
component.visible = true;
const div = target.querySelector('div');
assert.equal(div.value, 0);
raf.tick(200);
div.value = 'test';
component.visible = false;
assert.equal(div.value, 'test');
}
};

@ -0,0 +1,17 @@
<script>
export let visible = false;
export let value = 0;
function foo(node, params) {
return {
duration: 100,
tick: () => {
node.value = value;
}
};
}
</script>
{#if visible}
<div transition:foo={{value}}></div>
{/if}

@ -0,0 +1,6 @@
<script>
const url = import.meta.url;
</script>
{url}
{import.meta.url}
Loading…
Cancel
Save