Merge branch 'master' into tests

pull/4886/head
pushkine 5 years ago
commit deab67bb04

@ -2,6 +2,7 @@
## Unreleased ## Unreleased
* Update `<select>` with `bind:value` when the available `<option>`s change ([#1764](https://github.com/sveltejs/svelte/issues/1764))
* Fix inconsistencies when setting a two-way bound `<input>` to `undefined` ([#3569](https://github.com/sveltejs/svelte/issues/3569)) * Fix inconsistencies when setting a two-way bound `<input>` to `undefined` ([#3569](https://github.com/sveltejs/svelte/issues/3569))
* Fix resize listening on certain older browsers ([#4752](https://github.com/sveltejs/svelte/issues/4752)) * Fix resize listening on certain older browsers ([#4752](https://github.com/sveltejs/svelte/issues/4752))
* Add `a11y-no-onchange` warning ([#4788](https://github.com/sveltejs/svelte/pull/4788)) * Add `a11y-no-onchange` warning ([#4788](https://github.com/sveltejs/svelte/pull/4788))

@ -77,6 +77,9 @@ npm install && npm run update
npm run dev npm run dev
``` ```
### Is svelte.dev down?
Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402).
## License ## License

2337
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -13,14 +13,12 @@
"store", "store",
"animate", "animate",
"transition", "transition",
"interpolate",
"easing", "easing",
"motion", "motion",
"svelte", "svelte",
"README.md" "README.md"
], ],
"engines": {
"node": ">= 8"
},
"types": "types/runtime/index.d.ts", "types": "types/runtime/index.d.ts",
"scripts": { "scripts": {
"test": "mocha", "test": "mocha",
@ -76,25 +74,25 @@
"@types/puppeteer": "1.3.0", "@types/puppeteer": "1.3.0",
"@typescript-eslint/eslint-plugin": "^1.13.0", "@typescript-eslint/eslint-plugin": "^1.13.0",
"@typescript-eslint/parser": "^2.1.0", "@typescript-eslint/parser": "^2.1.0",
"acorn": "^7.1.0", "acorn": "^7.2.0",
"agadoo": "^1.1.0", "agadoo": "^2.0.0",
"c8": "^5.0.1", "c8": "^7.1.2",
"code-red": "0.1.1", "code-red": "0.1.1",
"codecov": "^3.5.0", "codecov": "^3.6.5",
"css-tree": "1.0.0-alpha22", "css-tree": "1.0.0-alpha22",
"eslint": "^6.3.0", "eslint": "^6.3.0",
"eslint-plugin-import": "^2.18.2", "eslint-plugin-import": "^2.18.2",
"eslint-plugin-svelte3": "^2.7.3", "eslint-plugin-svelte3": "^2.7.3",
"estree-walker": "^1.0.0", "estree-walker": "^2.0.1",
"is-reference": "^1.1.4", "is-reference": "^1.1.4",
"jsdom": "^15.1.1", "jsdom": "^16.2.2",
"kleur": "^3.0.3", "kleur": "^3.0.3",
"locate-character": "^2.0.5", "locate-character": "^2.0.5",
"magic-string": "^0.25.3", "magic-string": "^0.25.3",
"mocha": "^6.2.0", "mocha": "^7.1.2",
"periscopic": "^2.0.1", "periscopic": "^2.0.1",
"puppeteer": "^1.19.0", "puppeteer": "^3.1.0",
"rollup": "^1.27.14", "rollup": "^2.10.5",
"source-map": "^0.7.3", "source-map": "^0.7.3",
"source-map-support": "^0.5.13", "source-map-support": "^0.5.13",
"tslib": "^1.10.0", "tslib": "^1.10.0",

@ -65,7 +65,7 @@ export default [
}), }),
ts_plugin, ts_plugin,
{ {
writeBundle(bundle) { writeBundle(_options, bundle) {
if (dir === 'internal') { if (dir === 'internal') {
const mod = bundle['index.mjs']; const mod = bundle['index.mjs'];
if (mod) { if (mod) {

@ -121,6 +121,9 @@ An element or component can have multiple spread attributes, interspersed with r
<input {...$$restProps}> <input {...$$restProps}>
``` ```
> The `value` attribute of an `input` element or its children `option` elements must not be set with spread attributes when using `bind:group` or `bind:checked`. Svelte needs to be able to see the element's `value` directly in the markup in these cases so that it can link it to the bound variable.
--- ---
### Text expressions ### Text expressions

@ -521,7 +521,7 @@ $: $size = big ? 100 : 10;
### `svelte/transition` ### `svelte/transition`
The `svelte/transition` module exports six functions: `fade`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](docs#transition_fn). The `svelte/transition` module exports seven functions: `fade`, `blur`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](docs#transition_fn).
#### `fade` #### `fade`

@ -1,5 +0,0 @@
---
question: Is svelte.dev down?
---
Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402).

@ -87,7 +87,7 @@ export default class BindingWrapper {
const update_conditions: any[] = this.needs_lock ? [x`!${lock}`] : []; const update_conditions: any[] = this.needs_lock ? [x`!${lock}`] : [];
const mount_conditions: any[] = []; const mount_conditions: any[] = [];
const dependency_array = [...this.node.expression.dependencies]; const dependency_array = Array.from(this.get_dependencies());
if (dependency_array.length > 0) { if (dependency_array.length > 0) {
update_conditions.push(block.renderer.dirty(dependency_array)); update_conditions.push(block.renderer.dirty(dependency_array));

@ -13,10 +13,7 @@ function try_require(file) {
} }
function normalize_warning(warning) { function normalize_warning(warning) {
warning.frame = warning.frame warning.frame = warning.frame.replace(/^\n/, '').replace(/^\t+/gm, '').replace(/\s+$/gm, '');
.replace(/^\n/, '')
.replace(/^\t+/gm, '')
.replace(/\s+$/gm, '');
delete warning.filename; delete warning.filename;
delete warning.toString; delete warning.toString;
delete warning.start; delete warning.start;
@ -29,7 +26,7 @@ function create(code) {
const fn = new Function('module', 'exports', 'require', code); const fn = new Function('module', 'exports', 'require', code);
const module = { exports: {} }; const module = { exports: {} };
fn(module, module.exports, id => { fn(module, module.exports, (id) => {
if (id === 'svelte') return require('../../index.js'); if (id === 'svelte') return require('../../index.js');
if (id.startsWith('svelte/')) return require(id.replace('svelte', '../../')); if (id.startsWith('svelte/')) return require(id.replace('svelte', '../../'));
@ -61,15 +58,9 @@ describe('css', () => {
const expected_warnings = (config.warnings || []).map(normalize_warning); const expected_warnings = (config.warnings || []).map(normalize_warning);
const dom = svelte.compile( const dom = svelte.compile(input, Object.assign(config.compileOptions || {}, { format: 'cjs' }));
input,
Object.assign(config.compileOptions || {}, { format: 'cjs' })
);
const ssr = svelte.compile( const ssr = svelte.compile(input, Object.assign(config.compileOptions || {}, { format: 'cjs', generate: 'ssr' }));
input,
Object.assign(config.compileOptions || {}, { format: 'cjs', generate: 'ssr' })
);
assert.equal(dom.css.code, ssr.css.code); assert.equal(dom.css.code, ssr.css.code);
@ -82,10 +73,10 @@ describe('css', () => {
writeFileSync(`${__dirname}/samples/${dir}/_actual.css`, dom.css.code); writeFileSync(`${__dirname}/samples/${dir}/_actual.css`, dom.css.code);
const expected = { const expected = {
html: read(`${__dirname}/samples/${dir}/expected.html`), html: read(`${__dirname}/samples/${dir}/expected.html`),
css: read(`${__dirname}/samples/${dir}/expected.css`) css: read(`${__dirname}/samples/${dir}/expected.css`),
}; };
const actual_css = dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'); const actual_css = dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => ($1 ? m : 'svelte-xyz'));
try { try {
assert.equal(actual_css, expected.css); assert.equal(actual_css, expected.css);
} catch (error) { } catch (error) {
@ -140,7 +131,9 @@ describe('css', () => {
// ssr // ssr
try { try {
const actual_ssr = ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'); const actual_ssr = ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) =>
$1 ? m : 'svelte-xyz'
);
assert.htmlEqual(actual_ssr, expected.html); assert.htmlEqual(actual_ssr, expected.html);
} catch (err) { } catch (err) {
console.log(ssr.js.code); console.log(ssr.js.code);

@ -53,7 +53,7 @@ describe('custom-elements', function () {
await browser.close(); await browser.close();
}); });
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach((dir) => {
if (dir[0] === '.') return; if (dir[0] === '.') return;
const solo = /\.solo$/.test(dir); const solo = /\.solo$/.test(dir);
@ -94,9 +94,9 @@ describe('custom-elements', function () {
}, },
}, },
virtual({ virtual({
assert assert,
}) }),
] ],
}); });
const result = await bundle.generate({ format: 'iife', name: 'test' }); const result = await bundle.generate({ format: 'iife', name: 'test' });
@ -108,7 +108,7 @@ describe('custom-elements', function () {
console[type](...args); console[type](...args);
}); });
page.on('error', error => { page.on('error', (error) => {
console.log('>>> an error happened'); console.log('>>> an error happened');
console.error(error); console.error(error);
}); });

@ -47,8 +47,8 @@ export function tryToReadFile(file) {
export function cleanRequireCache() { export function cleanRequireCache() {
Object.keys(require.cache) Object.keys(require.cache)
.filter(x => x.endsWith('.svelte')) .filter((x) => x.endsWith('.svelte'))
.forEach(file => delete require.cache[file]); .forEach((file) => delete require.cache[file]);
} }
const virtualConsole = new jsdom.VirtualConsole(); const virtualConsole = new jsdom.VirtualConsole();
@ -68,7 +68,7 @@ for (const key of Object.getOwnPropertyNames(global)) {
} }
// implement mock scroll // implement mock scroll
window.scrollTo = function(pageXOffset, pageYOffset) { window.scrollTo = function (pageXOffset, pageYOffset) {
window.pageXOffset = pageXOffset; window.pageXOffset = pageXOffset;
window.pageYOffset = pageYOffset; window.pageYOffset = pageYOffset;
}; };
@ -89,11 +89,11 @@ function cleanChildren(node: Element) {
return a.name < b.name ? -1 : 1; return a.name < b.name ? -1 : 1;
}); });
attributes.forEach(attr => { attributes.forEach((attr) => {
node.removeAttribute(attr.name); node.removeAttribute(attr.name);
}); });
attributes.forEach(attr => { attributes.forEach((attr) => {
node.setAttribute(attr.name, attr.value); node.setAttribute(attr.name, attr.value);
}); });
@ -148,12 +148,8 @@ export function normalizeHtml(window, html) {
export function setupHtmlEqual() { export function setupHtmlEqual() {
const window = env(); const window = env();
assert.htmlEqual = (actual, expected, message) => { assert.htmlEqual = function (actual, expected, message) {
assert.deepEqual( assert.deepEqual(normalizeHtml(window, actual), normalizeHtml(window, expected), message);
normalizeHtml(window, actual),
normalizeHtml(window, expected),
message
);
}; };
} }
@ -179,24 +175,20 @@ export function addLineNumbers(code) {
.map((line, i) => { .map((line, i) => {
i = String(i + 1); i = String(i + 1);
while (i.length < 3) i = ` ${i}`; while (i.length < 3) i = ` ${i}`;
return colors.gray(` ${i}: `) + line.replace(/^\t+/, (match) => match.split('\t').join(' '));
return (
colors.gray(` ${i}: `) +
line.replace(/^\t+/, match => match.split('\t').join(' '))
);
}) })
.join('\n'); .join('\n');
} }
export function showOutput(cwd, options = {}, compile = svelte.compile) { export function showOutput(cwd, options = {}, compile = svelte.compile) {
glob('**/*.svelte', { cwd }).forEach(file => { glob('**/*.svelte', { cwd }).forEach((file) => {
if (file[0] === '_') return; if (file[0] === '_') return;
try { try {
const { js } = compile( const { js } = compile(
fs.readFileSync(`${cwd}/${file}`, 'utf-8'), fs.readFileSync(`${cwd}/${file}`, 'utf-8'),
Object.assign(options, { Object.assign(options, {
filename: file filename: file,
}) })
); );
@ -226,13 +218,13 @@ export function useFakeTimers() {
return { return {
flush() { flush() {
callbacks.forEach(fn => fn()); callbacks.forEach((fn) => fn());
callbacks.splice(0, callbacks.length); callbacks.splice(0, callbacks.length);
}, },
removeFakeTimers() { removeFakeTimers() {
callbacks.splice(0, callbacks.length); callbacks.splice(0, callbacks.length);
global.setTimeout = original_set_timeout; global.setTimeout = original_set_timeout;
} },
}; };
} }

@ -12,13 +12,13 @@ describe('hydration', () => {
before(() => { before(() => {
const svelte = loadSvelte(); const svelte = loadSvelte();
require.extensions['.svelte'] = function(module, filename) { require.extensions['.svelte'] = function (module, filename) {
const options = Object.assign( const options = Object.assign(
{ {
filename, filename,
hydratable: true, hydratable: true,
format: 'cjs', format: 'cjs',
sveltePath sveltePath,
}, },
compileOptions compileOptions
); );
@ -75,7 +75,7 @@ describe('hydration', () => {
const component = new SvelteComponent({ const component = new SvelteComponent({
target, target,
hydrate: true, hydrate: true,
props: config.props props: config.props,
}); });
try { try {
@ -112,18 +112,19 @@ describe('hydration', () => {
} }
} catch (err) { } catch (err) {
showOutput(cwd, { showOutput(cwd, {
hydratable: true hydratable: true,
}); });
throw err; throw err;
} }
if (config.show) showOutput(cwd, { if (config.show)
hydratable: true showOutput(cwd, {
}); hydratable: true,
});
}); });
} }
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach((dir) => {
runTest(dir, null); runTest(dir, null);
}); });
}); });

@ -23,7 +23,7 @@ describe('motion', () => {
it('sets immediately when duration is 0', () => { it('sets immediately when duration is 0', () => {
const size = tweened(0); const size = tweened(0);
size.set(100, { duration : 0 }); size.set(100, { duration: 0 });
assert.equal(get(size), 100); assert.equal(get(size), 100);
}); });
}); });

@ -23,9 +23,12 @@ describe('parser', () => {
const expectedError = tryToLoadJson(`${__dirname}/samples/${dir}/error.json`); const expectedError = tryToLoadJson(`${__dirname}/samples/${dir}/error.json`);
try { try {
const { ast } = svelte.compile(input, Object.assign(options, { const { ast } = svelte.compile(
generate: false input,
})); Object.assign(options, {
generate: false,
})
);
fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.json`, JSON.stringify(ast, null, '\t')); fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.json`, JSON.stringify(ast, null, '\t'));

@ -0,0 +1,34 @@
export default {
props: {
items: [],
selected: 'two'
},
html: `
<select></select>
<p>selected: two</p>
`,
ssrHtml: `
<select value="two"></select>
<p>selected: two</p>
`,
test({ assert, component, target }) {
component.items = [ 'one', 'two', 'three' ];
const options = target.querySelectorAll('option');
assert.ok(!options[0].selected);
assert.ok(options[1].selected);
assert.ok(!options[2].selected);
assert.htmlEqual(target.innerHTML, `
<select>
<option value='one'>one</option>
<option value='two'>two</option>
<option value='three'>three</option>
</select>
<p>selected: two</p>
`);
}
};

@ -0,0 +1,12 @@
<script>
export let selected;
export let items;
</script>
<select bind:value={selected}>
{#each items as item}
<option>{item}</option>
{/each}
</select>
<p>selected: {selected || 'nothing'}</p>

@ -16,9 +16,9 @@ import { assert } from "../test";
function tryToReadFile(file) { function tryToReadFile(file) {
try { try {
return fs.readFileSync(file, "utf-8"); return fs.readFileSync(file, 'utf-8');
} catch (err) { } catch (err) {
if (err.code !== "ENOENT") throw err; if (err.code !== 'ENOENT') throw err;
return null; return null;
} }
} }
@ -26,15 +26,15 @@ function tryToReadFile(file) {
const sveltePath = process.cwd().split("\\").join("/"); const sveltePath = process.cwd().split("\\").join("/");
let compile = null; let compile = null;
describe("ssr", () => { describe('ssr', () => {
before(() => { before(() => {
compile = loadSvelte(true).compile; compile = loadSvelte(true).compile;
return setupHtmlEqual(); return setupHtmlEqual();
}); });
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach((dir) => {
if (dir[0] === ".") return; if (dir[0] === '.') return;
const config = loadConfig(`${__dirname}/samples/${dir}/_config.js`); const config = loadConfig(`${__dirname}/samples/${dir}/_config.js`);
@ -45,7 +45,7 @@ describe("ssr", () => {
const show = /\.show/.test(dir); const show = /\.show/.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');
} }
(skip ? it.skip : solo ? it.only : it)(dir, () => { (skip ? it.skip : solo ? it.only : it)(dir, () => {
@ -60,13 +60,13 @@ describe("ssr", () => {
format: "cjs", format: "cjs",
}; };
require("../../register")(compileOptions); require('../../register')(compileOptions);
try { try {
const Component = require(`${dir}/main.svelte`).default; const Component = require(`${dir}/main.svelte`).default;
const expectedHtml = tryToReadFile(`${dir}/_expected.html`); const expectedHtml = tryToReadFile(`${dir}/_expected.html`);
const expectedCss = tryToReadFile(`${dir}/_expected.css`) || ""; const expectedCss = tryToReadFile(`${dir}/_expected.css`) || '';
const props = tryToLoadJson(`${dir}/data.json`) || undefined; const props = tryToLoadJson(`${dir}/data.json`) || undefined;
@ -105,10 +105,7 @@ describe("ssr", () => {
fs.writeFileSync(`${dir}/_actual-head.html`, head); fs.writeFileSync(`${dir}/_actual-head.html`, head);
try { try {
assert.htmlEqual( assert.htmlEqual(head, fs.readFileSync(`${dir}/_expected-head.html`, 'utf-8'));
head,
fs.readFileSync(`${dir}/_expected-head.html`, 'utf-8')
);
} catch (error) { } catch (error) {
if (shouldUpdateExpected()) { if (shouldUpdateExpected()) {
fs.writeFileSync(`${dir}/_expected-head.html`, head); fs.writeFileSync(`${dir}/_expected-head.html`, head);
@ -129,15 +126,15 @@ describe("ssr", () => {
}); });
// duplicate client-side tests, as far as possible // duplicate client-side tests, as far as possible
fs.readdirSync("test/runtime/samples").forEach(dir => { fs.readdirSync('test/runtime/samples').forEach((dir) => {
if (dir[0] === ".") return; if (dir[0] === '.') return;
const config = loadConfig(`./runtime/samples/${dir}/_config.js`); const config = loadConfig(`./runtime/samples/${dir}/_config.js`);
const solo = config.solo || /\.solo/.test(dir); const solo = config.solo || /\.solo/.test(dir);
const skip = config.skip || /\.skip/.test(dir); const skip = config.skip || /\.skip/.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');
} }
if (config.skip_if_ssr) return; if (config.skip_if_ssr) return;
@ -156,7 +153,7 @@ describe("ssr", () => {
format: "cjs" format: "cjs"
}; };
require("../../register")(compileOptions); require('../../register')(compileOptions);
glob("**/*.svelte", { cwd }).forEach((file) => { glob("**/*.svelte", { cwd }).forEach((file) => {
if (file[0] === "_") return; if (file[0] === "_") return;
@ -171,13 +168,10 @@ describe("ssr", () => {
mkdirp(dir); mkdirp(dir);
try { try {
const { js } = compile( const { js } = compile(fs.readFileSync(`${cwd}/${file}`, 'utf-8'), {
fs.readFileSync(`${cwd}/${file}`, 'utf-8'), ...compileOptions,
{ filename: file,
...compileOptions, });
filename: file
}
);
fs.writeFileSync(out, js.code); fs.writeFileSync(out, js.code);
} catch (err) { } catch (err) {
@ -190,7 +184,7 @@ describe("ssr", () => {
const Component = require(`../runtime/samples/${dir}/main.svelte`).default; const Component = require(`../runtime/samples/${dir}/main.svelte`).default;
const { html } = Component.render(config.props, { const { html } = Component.render(config.props, {
store: (config.store !== true) && config.store store: config.store !== true && config.store,
}); });
if (config.ssrHtml) { if (config.ssrHtml) {

Loading…
Cancel
Save