Merge branch 'master' into IlyaSemenov-gh-2843

pull/3030/head
Richard Harris 6 years ago
commit 1ad555cc32

@ -1,9 +0,0 @@
[ignore]
<PROJECT_ROOT>/types/.*
[include]
[libs]
[options]
strip_root=true

1
.gitignore vendored

@ -4,6 +4,7 @@
node_modules node_modules
*.map *.map
/src/compiler/compile/internal-exports.ts /src/compiler/compile/internal-exports.ts
/compiler.d.ts
/compiler.*js /compiler.*js
/index.*js /index.*js
/internal /internal

1
compiler.d.ts vendored

@ -1 +0,0 @@
export * from './types/compiler';

6
package-lock.json generated

@ -49,9 +49,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "10.12.18", "version": "8.10.49",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.49.tgz",
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", "integrity": "sha512-YX30JVx0PvSmJ3Eqr74fYLGeBxD+C7vIL20ek+GGGLJeUbVYRUW3EzyAXpIRA0K8c8o0UWqR/GwEFYiFoz1T8w==",
"dev": true "dev": true
}, },
"@typescript-eslint/eslint-plugin": { "@typescript-eslint/eslint-plugin": {

@ -21,7 +21,7 @@
"engines": { "engines": {
"node": ">= 8" "node": ">= 8"
}, },
"types": "types/runtime", "types": "types/runtime/index.d.ts",
"scripts": { "scripts": {
"test": "mocha --opts mocha.opts", "test": "mocha --opts mocha.opts",
"test:unit": "mocha --require sucrase/register --recursive src/**/__test__.ts", "test:unit": "mocha --require sucrase/register --recursive src/**/__test__.ts",
@ -35,10 +35,8 @@
"dev": "rollup -cw", "dev": "rollup -cw",
"pretest": "npm run build", "pretest": "npm run build",
"posttest": "agadoo internal/index.mjs", "posttest": "agadoo internal/index.mjs",
"prepublishOnly": "export PUBLISH=true && npm test && npm run create-stubs", "prepublishOnly": "PUBLISH=true npm test",
"create-stubs": "node scripts/create-stubs.js", "tsd": "tsc -p src/compiler --emitDeclarationOnly && tsc -p src/runtime --emitDeclarationOnly",
"tsd": "tsc -p . --emitDeclarationOnly",
"typecheck": "tsc -p . --noEmit",
"lint": "eslint \"{src,test}/**/*.{ts,js}\"" "lint": "eslint \"{src,test}/**/*.{ts,js}\""
}, },
"repository": { "repository": {
@ -59,7 +57,7 @@
"homepage": "https://github.com/sveltejs/svelte#README", "homepage": "https://github.com/sveltejs/svelte#README",
"devDependencies": { "devDependencies": {
"@types/mocha": "^5.2.0", "@types/mocha": "^5.2.0",
"@types/node": "^10.5.5", "@types/node": "=8",
"@typescript-eslint/eslint-plugin": "^1.9.0", "@typescript-eslint/eslint-plugin": "^1.9.0",
"@typescript-eslint/parser": "^1.9.0", "@typescript-eslint/parser": "^1.9.0",
"acorn": "^6.1.1", "acorn": "^6.1.1",

@ -20,6 +20,8 @@ const ts_plugin = is_publish
const external = id => id.startsWith('svelte/'); const external = id => id.startsWith('svelte/');
fs.writeFileSync(`./compiler.d.ts`, `export * from './types/compiler/index';`);
export default [ export default [
/* runtime */ /* runtime */
{ {
@ -59,12 +61,22 @@ export default [
external, external,
plugins: [ plugins: [
ts_plugin, ts_plugin,
dir === 'internal' && { {
generateBundle(options, bundle) { writeBundle(bundle) {
const mod = bundle['index.mjs']; if (dir === 'internal') {
if (mod) { const mod = bundle['index.mjs'];
fs.writeFileSync('src/compiler/compile/internal-exports.ts', `// This file is automatically generated\nexport default new Set(${JSON.stringify(mod.exports)});`); if (mod) {
fs.writeFileSync('src/compiler/compile/internal-exports.ts', `// This file is automatically generated\nexport default new Set(${JSON.stringify(mod.exports)});`);
}
} }
fs.writeFileSync(`${dir}/package.json`, JSON.stringify({
main: './index',
module: './index.mjs',
types: './index.d.ts'
}, null, ' '));
fs.writeFileSync(`${dir}/index.d.ts`, `export * from '../types/runtime/${dir}/index';`);
} }
} }
] ]

@ -1,12 +0,0 @@
const fs = require('fs');
fs.readdirSync('src/runtime')
.filter(dir => fs.statSync(`src/runtime/${dir}`).isDirectory())
.forEach(dir => {
fs.writeFileSync(`${dir}/package.json`, JSON.stringify({
main: './index',
module: './index.mjs'
}, null, ' '));
fs.writeFileSync(`${dir}/index.d.ts`, `export * from '../types/runtime/${dir}/index.d.ts';`);
});

@ -43,10 +43,12 @@
} }
function remove() { function remove() {
people = [...people.slice(0, i), ...people.slice(i + 1)]; // Remove selected person from the source array (people), not the filtered array
const index = people.indexOf(selected);
people = [...people.slice(0, index), ...people.slice(index + 1)];
first = last = ''; first = last = '';
i = Math.min(i, people.length - 1); i = Math.min(i, filteredPeople.length - 2);
} }
function reset_inputs(person) { function reset_inputs(person) {

@ -1,6 +1,6 @@
<script> <script>
import { comicSans, link } from './styles.js'; import { comicSans, link } from './styles.js';
import Hero from './Hero.html'; import Hero from './Hero.svelte';
</script> </script>
<Hero/> <Hero/>

@ -1,4 +1,6 @@
import { css } from 'emotion/dist/emotion.umd.min.js'; import emotion from 'emotion/dist/emotion.umd.min.js';
const { css } = emotion;
const brand = '#74D900'; const brand = '#74D900';
@ -30,4 +32,4 @@ export const link = css`
text-decoration: none; text-decoration: none;
background: ${brand}; background: ${brand};
} }
`; `;

@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

@ -1,19 +0,0 @@
describe('Sapper template app', () => {
beforeEach(() => {
cy.visit('/')
});
it('has the correct <h1>', () => {
cy.contains('h1', 'Great success!')
});
it('navigates to /about', () => {
cy.get('nav a').contains('about').click();
cy.url().should('include', '/about');
});
it('navigates to /blog', () => {
cy.get('nav a').contains('blog').click();
cy.url().should('include', '/blog');
});
});

@ -1,17 +0,0 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

@ -1,25 +0,0 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

@ -1,20 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

@ -1362,9 +1362,9 @@
} }
}, },
"@sveltejs/svelte-repl": { "@sveltejs/svelte-repl": {
"version": "0.1.7", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.7.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.8.tgz",
"integrity": "sha512-/023rff9mUtF+RqRbYUbMCwAMcvxkWc97Q8i+77G3LUVQSR44TR84lvdsnCHJwj1C+RhF/Npncd2GJSskRmgbQ==", "integrity": "sha512-RSKsuiQE3DrdT7B7DNhd5DK+DkYGLT5m6Ugchxc8iN+5v/hfVTbeNb+KJtItXLpDxiYdbb0HIiQPEdy0M+HThw==",
"dev": true, "dev": true,
"requires": { "requires": {
"codemirror": "^5.45.0", "codemirror": "^5.45.0",

@ -7,13 +7,9 @@
"copy-workers": "rm -rf static/workers && cp -r node_modules/@sveltejs/svelte-repl/workers static", "copy-workers": "rm -rf static/workers && cp -r node_modules/@sveltejs/svelte-repl/workers static",
"migrate": "node-pg-migrate -r dotenv/config", "migrate": "node-pg-migrate -r dotenv/config",
"sapper": "npm run copy-workers && sapper build --legacy", "sapper": "npm run copy-workers && sapper build --legacy",
"update_shimport": "cp node_modules/shimport/index.js __sapper__/build/client/shimport@0.0.14.js",
"update": "node scripts/update_template.js && node scripts/get-contributors.js", "update": "node scripts/update_template.js && node scripts/get-contributors.js",
"start": "node __sapper__/build", "start": "node __sapper__/build",
"cy:run": "cypress run", "test": "mocha -r esm test/**",
"cy:open": "cypress open",
"test": "run-p --race dev cy:run",
"testsrc": "mocha -r esm test/**",
"deploy": "make deploy" "deploy": "make deploy"
}, },
"dependencies": { "dependencies": {
@ -39,7 +35,7 @@
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.0.4", "@sveltejs/site-kit": "^1.0.4",
"@sveltejs/svelte-repl": "^0.1.7", "@sveltejs/svelte-repl": "^0.1.8",
"degit": "^2.1.3", "degit": "^2.1.3",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"eslint-plugin-svelte3": "^1.0.0", "eslint-plugin-svelte3": "^1.0.0",

@ -1,4 +1,4 @@
import { assign } from '../../runtime/internal/index'; import { assign } from '../../runtime/internal/utils';
import Stats from '../Stats'; import Stats from '../Stats';
import parse from '../parse/index'; import parse from '../parse/index';
import render_dom from './render-dom/index'; import render_dom from './render-dom/index';

@ -610,7 +610,7 @@ export default class Element extends Node {
} else if ( } else if (
name === 'text' || name === 'text' ||
name === 'html' name === 'html'
){ ) {
const contenteditable = this.attributes.find( const contenteditable = this.attributes.find(
(attribute: Attribute) => attribute.name === 'contenteditable' (attribute: Attribute) => attribute.name === 'contenteditable'
); );
@ -626,7 +626,7 @@ export default class Element extends Node {
message: `'contenteditable' attribute cannot be dynamic if element uses two-way binding` message: `'contenteditable' attribute cannot be dynamic if element uses two-way binding`
}); });
} }
} else if (name !== 'this') { } else if (name !== 'this') {
component.error(binding, { component.error(binding, {
code: `invalid-binding`, code: `invalid-binding`,
message: `'${binding.name}' is not a valid binding` message: `'${binding.name}' is not a valid binding`

@ -12,7 +12,7 @@ export default class Text extends Node {
super(component, parent, scope, info); super(component, parent, scope, info);
this.data = info.data; this.data = info.data;
if (!component.component_options.preserveWhitespace && !/\S/.test(info.data)) { if (!component.component_options.preserveWhitespace && !/[\S\u00A0]/.test(info.data)) {
let node = parent; let node = parent;
while (node) { while (node) {
if (node.type === 'Element' && node.name === 'pre') { if (node.type === 'Element' && node.name === 'pre') {

@ -224,79 +224,20 @@ export default class AttributeWrapper {
} }
} }
// source: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes // source: https://html.spec.whatwg.org/multipage/indices.html
const attribute_lookup = { const attribute_lookup = {
accept: { applies_to: ['form', 'input'] },
'accept-charset': { property_name: 'acceptCharset', applies_to: ['form'] },
accesskey: { property_name: 'accessKey' },
action: { applies_to: ['form'] },
align: {
applies_to: [
'applet',
'caption',
'col',
'colgroup',
'hr',
'iframe',
'img',
'table',
'tbody',
'td',
'tfoot',
'th',
'thead',
'tr',
],
},
allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] }, allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
alt: { applies_to: ['applet', 'area', 'img', 'input'] }, allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
async: { applies_to: ['script'] }, async: { applies_to: ['script'] },
autocomplete: { applies_to: ['form', 'input'] },
autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] }, autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
autoplay: { applies_to: ['audio', 'video'] }, autoplay: { applies_to: ['audio', 'video'] },
autosave: { applies_to: ['input'] }, checked: { applies_to: ['input'] },
bgcolor: {
property_name: 'bgColor',
applies_to: [
'body',
'col',
'colgroup',
'marquee',
'table',
'tbody',
'tfoot',
'td',
'th',
'tr',
],
},
border: { applies_to: ['img', 'object', 'table'] },
buffered: { applies_to: ['audio', 'video'] },
challenge: { applies_to: ['keygen'] },
charset: { applies_to: ['meta', 'script'] },
checked: { applies_to: ['command', 'input'] },
cite: { applies_to: ['blockquote', 'del', 'ins', 'q'] },
class: { property_name: 'className' },
code: { applies_to: ['applet'] },
codebase: { property_name: 'codeBase', applies_to: ['applet'] },
color: { applies_to: ['basefont', 'font', 'hr'] },
cols: { applies_to: ['textarea'] },
colspan: { property_name: 'colSpan', applies_to: ['td', 'th'] },
content: { applies_to: ['meta'] },
contenteditable: { property_name: 'contentEditable' },
contextmenu: {},
controls: { applies_to: ['audio', 'video'] }, controls: { applies_to: ['audio', 'video'] },
coords: { applies_to: ['area'] },
data: { applies_to: ['object'] },
datetime: { property_name: 'dateTime', applies_to: ['del', 'ins', 'time'] },
default: { applies_to: ['track'] }, default: { applies_to: ['track'] },
defer: { applies_to: ['script'] }, defer: { applies_to: ['script'] },
dir: {},
dirname: { property_name: 'dirName', applies_to: ['input', 'textarea'] },
disabled: { disabled: {
applies_to: [ applies_to: [
'button', 'button',
'command',
'fieldset', 'fieldset',
'input', 'input',
'keygen', 'keygen',
@ -306,119 +247,21 @@ const attribute_lookup = {
'textarea', 'textarea',
], ],
}, },
download: { applies_to: ['a', 'area'] }, formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
draggable: {},
dropzone: {},
enctype: { applies_to: ['form'] },
for: { property_name: 'htmlFor', applies_to: ['label', 'output'] },
formaction: { applies_to: ['input', 'button'] },
headers: { applies_to: ['td', 'th'] },
height: {
applies_to: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
},
hidden: {}, hidden: {},
high: { applies_to: ['meter'] },
href: { applies_to: ['a', 'area', 'base', 'link'] },
hreflang: { applies_to: ['a', 'area', 'link'] },
'http-equiv': { property_name: 'httpEquiv', applies_to: ['meta'] },
icon: { applies_to: ['command'] },
id: {},
indeterminate: { applies_to: ['input'] }, indeterminate: { applies_to: ['input'] },
ismap: { property_name: 'isMap', applies_to: ['img'] }, ismap: { property_name: 'isMap', applies_to: ['img'] },
itemprop: {}, loop: { applies_to: ['audio', 'bgsound', 'video'] },
keytype: { applies_to: ['keygen'] },
kind: { applies_to: ['track'] },
label: { applies_to: ['track'] },
lang: {},
language: { applies_to: ['script'] },
loop: { applies_to: ['audio', 'bgsound', 'marquee', 'video'] },
low: { applies_to: ['meter'] },
manifest: { applies_to: ['html'] },
max: { applies_to: ['input', 'meter', 'progress'] },
maxlength: { property_name: 'maxLength', applies_to: ['input', 'textarea'] },
media: { applies_to: ['a', 'area', 'link', 'source', 'style'] },
method: { applies_to: ['form'] },
min: { applies_to: ['input', 'meter'] },
multiple: { applies_to: ['input', 'select'] }, multiple: { applies_to: ['input', 'select'] },
muted: { applies_to: ['audio', 'video'] }, muted: { applies_to: ['audio', 'video'] },
name: { nomodule: { property_name: 'noModule', applies_to: ['script'] },
applies_to: [
'button',
'form',
'fieldset',
'iframe',
'input',
'keygen',
'object',
'output',
'select',
'textarea',
'map',
'meta',
'param',
],
},
novalidate: { property_name: 'noValidate', applies_to: ['form'] }, novalidate: { property_name: 'noValidate', applies_to: ['form'] },
open: { applies_to: ['details'] }, open: { applies_to: ['details', 'dialog'] },
optimum: { applies_to: ['meter'] }, playsinline: { property_name: 'playsInline', applies_to: ['video'] },
pattern: { applies_to: ['input'] },
ping: { applies_to: ['a', 'area'] },
placeholder: { applies_to: ['input', 'textarea'] },
poster: { applies_to: ['video'] },
preload: { applies_to: ['audio', 'video'] },
radiogroup: { applies_to: ['command'] },
readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] }, readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
rel: { applies_to: ['a', 'area', 'link'] },
required: { applies_to: ['input', 'select', 'textarea'] }, required: { applies_to: ['input', 'select', 'textarea'] },
reversed: { applies_to: ['ol'] }, reversed: { applies_to: ['ol'] },
rows: { applies_to: ['textarea'] },
rowspan: { property_name: 'rowSpan', applies_to: ['td', 'th'] },
sandbox: { applies_to: ['iframe'] },
scope: { applies_to: ['th'] },
scoped: { applies_to: ['style'] },
seamless: { applies_to: ['iframe'] },
selected: { applies_to: ['option'] }, selected: { applies_to: ['option'] },
shape: { applies_to: ['a', 'area'] },
size: { applies_to: ['input', 'select'] },
sizes: { applies_to: ['link', 'img', 'source'] },
span: { applies_to: ['col', 'colgroup'] },
spellcheck: {},
src: {
applies_to: [
'audio',
'embed',
'iframe',
'img',
'input',
'script',
'source',
'track',
'video',
],
},
srcdoc: { applies_to: ['iframe'] },
srclang: { applies_to: ['track'] },
srcset: { applies_to: ['img'] },
start: { applies_to: ['ol'] },
step: { applies_to: ['input'] },
style: { property_name: 'style.cssText' },
summary: { applies_to: ['table'] },
tabindex: { property_name: 'tabIndex' },
target: { applies_to: ['a', 'area', 'base', 'form'] },
title: {},
type: {
applies_to: [
'button',
'command',
'embed',
'object',
'script',
'source',
'style',
'menu',
],
},
usemap: { property_name: 'useMap', applies_to: ['img', 'input', 'object'] },
value: { value: {
applies_to: [ applies_to: [
'button', 'button',
@ -432,12 +275,6 @@ const attribute_lookup = {
'textarea', 'textarea',
], ],
}, },
volume: { applies_to: ['audio', 'video'] },
playbackRate: { applies_to: ['audio', 'video'] },
width: {
applies_to: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
},
wrap: { applies_to: ['textarea'] },
}; };
Object.keys(attribute_lookup).forEach(name => { Object.keys(attribute_lookup).forEach(name => {

@ -151,12 +151,12 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
if (name === 'group') { if (name === 'group') {
// TODO server-render group bindings // TODO server-render group bindings
} else if (contenteditable && (name === 'text' || name === 'html')) { } else if (contenteditable && (name === 'text' || name === 'html')) {
const snippet = snip(expression) const snippet = snip(expression);
if (name == 'text') { if (name == 'text') {
node_contents = '${@escape(' + snippet + ')}' node_contents = '${@escape(' + snippet + ')}';
} else { } else {
// Do not escape HTML content // Do not escape HTML content
node_contents = '${' + snippet + '}' node_contents = '${' + snippet + '}';
} }
} else if (binding.name === 'value' && node.name === 'textarea') { } else if (binding.name === 'value' && node.name === 'textarea') {
const snippet = snip(expression); const snippet = snip(expression);

@ -385,6 +385,7 @@ function read_attribute(parser: Parser, unique_names: Set<string>) {
let value: any[] | true = true; let value: any[] | true = true;
if (parser.eat('=')) { if (parser.eat('=')) {
parser.allow_whitespace();
value = read_attribute_value(parser); value = read_attribute_value(parser);
end = parser.index; end = parser.index;
} else if (parser.match_regex(/["']/)) { } else if (parser.match_regex(/["']/)) {

@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"include": ["."],
"compilerOptions": {
"lib": ["es2017", "webworker"]
// TODO: remove mocha types from the whole project
// "types": ["node", "estree"]
}
}

@ -1,4 +1,5 @@
import { identity as linear, noop, now } from './utils'; import { identity as linear, noop } from './utils';
import { now } from './environment';
import { loop } from './loop'; import { loop } from './loop';
import { create_rule, delete_rule } from './style_manager'; import { create_rule, delete_rule } from './style_manager';
import { AnimationConfig } from '../animate'; import { AnimationConfig } from '../animate';

@ -0,0 +1,16 @@
export const is_client = typeof window !== 'undefined';
export let now: () => number = is_client
? () => window.performance.now()
: () => Date.now();
export let raf = cb => requestAnimationFrame(cb);
// used internally for testing
export function set_now(fn) {
now = fn;
}
export function set_raf(fn) {
raf = fn;
}

@ -1,6 +1,7 @@
export * from './animations'; export * from './animations';
export * from './await-block'; export * from './await-block';
export * from './dom'; export * from './dom';
export * from './environment';
export * from './keyed-each'; export * from './keyed-each';
export * from './lifecycle'; export * from './lifecycle';
export * from './loop'; export * from './loop';

@ -1,4 +1,4 @@
import { now, raf } from './utils'; import { now, raf } from './environment';
export interface Task { abort(): void; promise: Promise<void> } export interface Task { abort(): void; promise: Promise<void> }

@ -1,5 +1,5 @@
import { element } from './dom'; import { element } from './dom';
import { raf } from './utils'; import { raf } from './environment';
let stylesheet; let stylesheet;
let active = 0; let active = 0;

@ -1,4 +1,5 @@
import { identity as linear, is_function, noop, now, run_all } from './utils'; import { identity as linear, is_function, noop, run_all } from './utils';
import { now } from "./environment";
import { loop } from './loop'; import { loop } from './loop';
import { create_rule, delete_rule } from './style_manager'; import { create_rule, delete_rule } from './style_manager';
import { custom_event } from './dom'; import { custom_event } from './dom';

@ -87,22 +87,5 @@ export function once(fn) {
if (ran) return; if (ran) return;
ran = true; ran = true;
fn.call(this, ...args); fn.call(this, ...args);
} };
}
const is_client = typeof window !== 'undefined';
export let now: () => number = is_client
? () => window.performance.now()
: () => Date.now();
export let raf = is_client ? requestAnimationFrame : noop;
// used internally for testing
export function set_now(fn) {
now = fn;
}
export function set_raf(fn) {
raf = fn;
} }

@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.json",
"include": ["."],
"compilerOptions": {
"lib": ["es2015", "dom", "dom.iterable"],
"target": "es2015",
"types": [],
"baseUrl": ".",
"paths": {
"svelte/*": ["*"]
}
}
}

@ -1,6 +1,7 @@
/* generated by Svelte vX.Y.Z */ /* generated by Svelte vX.Y.Z */
import { import {
SvelteComponent, SvelteComponent,
attr,
detach, detach,
element, element,
init, init,
@ -16,7 +17,7 @@ function create_fragment(ctx) {
c() { c() {
a = element("a"); a = element("a");
a.textContent = "Test"; a.textContent = "Test";
a.href = "#"; attr(a, "href", "#");
}, },
m(target, anchor) { m(target, anchor) {

@ -2,6 +2,7 @@
import { import {
SvelteComponent, SvelteComponent,
append, append,
attr,
detach, detach,
element, element,
init, init,
@ -26,7 +27,7 @@ function create_fragment(ctx) {
c() { c() {
p = element("p"); p = element("p");
t = text(ctx.foo); t = text(ctx.foo);
p.className = "svelte-1a7i8ec"; attr(p, "class", "svelte-1a7i8ec");
}, },
m(target, anchor) { m(target, anchor) {

@ -2,6 +2,7 @@
import { import {
SvelteComponent, SvelteComponent,
append, append,
attr,
detach, detach,
element, element,
init, init,
@ -23,7 +24,7 @@ function create_fragment(ctx) {
return { return {
c() { c() {
div = element("div"); div = element("div");
div.className = "svelte-1slhpfn"; attr(div, "class", "svelte-1slhpfn");
}, },
m(target, anchor) { m(target, anchor) {

@ -2,6 +2,7 @@
import { import {
SvelteComponent, SvelteComponent,
append, append,
attr,
destroy_each, destroy_each,
detach, detach,
detach_after, detach_after,
@ -39,8 +40,8 @@ function create_each_block(ctx) {
t5 = text(" ago:"); t5 = text(" ago:");
t6 = space(); t6 = space();
raw_before = element('noscript'); raw_before = element('noscript');
span.className = "meta"; attr(span, "class", "meta");
div.className = "comment"; attr(div, "class", "comment");
}, },
m(target, anchor) { m(target, anchor) {

@ -1,6 +1,7 @@
/* generated by Svelte vX.Y.Z */ /* generated by Svelte vX.Y.Z */
import { import {
SvelteComponent, SvelteComponent,
attr,
detach, detach,
element, element,
init, init,
@ -17,7 +18,7 @@ function create_fragment(ctx) {
c() { c() {
a = element("a"); a = element("a");
a.textContent = "this should not navigate to example.com"; a.textContent = "this should not navigate to example.com";
a.href = "https://example.com"; attr(a, "href", "https://example.com");
dispose = listen(a, "touchstart", touchstart_handler); dispose = listen(a, "touchstart", touchstart_handler);
}, },

@ -2,6 +2,7 @@
import { import {
SvelteComponent, SvelteComponent,
append, append,
attr,
detach, detach,
element, element,
init, init,
@ -16,10 +17,10 @@ function create_fragment(ctx) {
c() { c() {
meta0 = element("meta"); meta0 = element("meta");
meta1 = element("meta"); meta1 = element("meta");
meta0.name = "twitter:creator"; attr(meta0, "name", "twitter:creator");
meta0.content = "@sveltejs"; attr(meta0, "content", "@sveltejs");
meta1.name = "twitter:title"; attr(meta1, "name", "twitter:title");
meta1.content = "Svelte"; attr(meta1, "content", "Svelte");
}, },
m(target, anchor) { m(target, anchor) {

@ -1,6 +1,7 @@
/* generated by Svelte vX.Y.Z */ /* generated by Svelte vX.Y.Z */
import { import {
SvelteComponent, SvelteComponent,
attr,
detach, detach,
element, element,
init, init,
@ -18,8 +19,8 @@ function create_fragment(ctx) {
div0 = element("div"); div0 = element("div");
t = space(); t = space();
div1 = element("div"); div1 = element("div");
div0.style.cssText = ctx.style; attr(div0, "style", ctx.style);
div1.style.cssText = div1_style_value = "" + ctx.key + ": " + ctx.value; attr(div1, "style", div1_style_value = "" + ctx.key + ": " + ctx.value);
}, },
m(target, anchor) { m(target, anchor) {
@ -30,11 +31,11 @@ function create_fragment(ctx) {
p(changed, ctx) { p(changed, ctx) {
if (changed.style) { if (changed.style) {
div0.style.cssText = ctx.style; attr(div0, "style", ctx.style);
} }
if ((changed.key || changed.value) && div1_style_value !== (div1_style_value = "" + ctx.key + ": " + ctx.value)) { if ((changed.key || changed.value) && div1_style_value !== (div1_style_value = "" + ctx.key + ": " + ctx.value)) {
div1.style.cssText = div1_style_value; attr(div1, "style", div1_style_value);
} }
}, },

@ -0,0 +1 @@
<button on:click= {foo}>Click</button>

@ -0,0 +1,39 @@
{
"html": {
"start": 0,
"end": 38,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 38,
"type": "Element",
"name": "button",
"attributes": [
{
"start": 8,
"end": 23,
"type": "EventHandler",
"name": "click",
"modifiers": [],
"expression": {
"type": "Identifier",
"start": 19,
"end": 22,
"name": "foo"
}
}
],
"children": [
{
"start": 24,
"end": 29,
"type": "Text",
"raw": "Click",
"data": "Click"
}
]
}
]
}
}

@ -4,7 +4,7 @@ export default {
}, },
html: ` html: `
<editor><b>world</b></editor> <editor contenteditable="true"><b>world</b></editor>
<p>hello <b>world</b></p> <p>hello <b>world</b></p>
`, `,
@ -19,24 +19,24 @@ export default {
el.innerHTML = 'every<span>body</span>'; el.innerHTML = 'every<span>body</span>';
// No updates to data yet // No updates to data yet
assert.htmlEqual(target.innerHTML, ` assert.htmlEqual(target.innerHTML, `
<editor>every<span>body</span></editor> <editor contenteditable="true">every<span>body</span></editor>
<p>hello <b>world</b></p> <p>hello <b>world</b></p>
`); `);
// Handle user input // Handle user input
const event = new window.Event('input'); const event = new window.Event('input');
await el.dispatchEvent(event); await el.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, ` assert.htmlEqual(target.innerHTML, `
<editor>every<span>body</span></editor> <editor contenteditable="true">every<span>body</span></editor>
<p>hello every<span>body</span></p> <p>hello every<span>body</span></p>
`); `);
component.name = 'good<span>bye</span>'; component.name = 'good<span>bye</span>';
assert.equal(el.innerHTML, 'good<span>bye</span>'); assert.equal(el.innerHTML, 'good<span>bye</span>');
assert.htmlEqual(target.innerHTML, ` assert.htmlEqual(target.innerHTML, `
<editor>good<span>bye</span></editor> <editor contenteditable="true">good<span>bye</span></editor>
<p>hello good<span>bye</span></p> <p>hello good<span>bye</span></p>
`); `);
}, },

@ -4,7 +4,7 @@ export default {
}, },
html: ` html: `
<editor>world</editor> <editor contenteditable="true">world</editor>
<p>hello world</p> <p>hello world</p>
`, `,
@ -23,14 +23,14 @@ export default {
await el.dispatchEvent(event); await el.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, ` assert.htmlEqual(target.innerHTML, `
<editor>everybody</editor> <editor contenteditable="true">everybody</editor>
<p>hello everybody</p> <p>hello everybody</p>
`); `);
component.name = 'goodbye'; component.name = 'goodbye';
assert.equal(el.textContent, 'goodbye'); assert.equal(el.textContent, 'goodbye');
assert.htmlEqual(target.innerHTML, ` assert.htmlEqual(target.innerHTML, `
<editor>goodbye</editor> <editor contenteditable="true">goodbye</editor>
<p>hello goodbye</p> <p>hello goodbye</p>
`); `);
}, },

@ -0,0 +1,19 @@
export default {
html: `<div>&nbsp;hello</div>
<div>&nbsp;hello&nbsp;&nbsp;</div>
<div>&nbsp;hello&nbsp; &nbsp;hello</div>`,
test({ assert, component, target }) {
var divList = target.querySelectorAll('div')
assert.equal( divList[0].textContent.charCodeAt( 0 ), 160 );
assert.equal( divList[1].textContent.charCodeAt( 0 ), 160 );
assert.equal( divList[1].textContent.charCodeAt( 6 ), 160 );
assert.equal( divList[1].textContent.charCodeAt( 7 ), 160 );
assert.equal( divList[2].textContent.charCodeAt( 0 ), 160 );
assert.equal( divList[2].textContent.charCodeAt( 6 ), 160 );
assert.equal( divList[2].textContent.charCodeAt( 7 ), 32 );//normal space
assert.equal( divList[2].textContent.charCodeAt( 8 ), 160 );
}
};

@ -0,0 +1,7 @@
<script>
let name = 'hello';
</script>
<div>&nbsp;{name}</div>
<div>&nbsp;{name}&nbsp;&nbsp;</div>
<div>&nbsp;{name}&nbsp; &nbsp;{name}</div>

@ -1,5 +1,5 @@
export default { export default {
html: '<div></div>', html: `<div draggable='false'></div>`,
ssrHtml: '<div foo=1></div>' ssrHtml: `<div foo='1' draggable='false'></div>`,
}; };

@ -3,10 +3,11 @@
export let foo = 1; export let foo = 1;
export let bar; export let bar;
export let _class;
onMount(() => { onMount(() => {
foo = undefined; foo = undefined;
}); });
</script> </script>
<div {foo} {bar}></div> <div {foo} {bar} class={_class} draggable='false'></div>

@ -1,2 +0,0 @@
div.svelte-bzh57p{color:red}
div.svelte-4yw8vx{color:green}

@ -0,0 +1,10 @@
{
"extends": "../tsconfig.json",
"include": ["."],
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noEmit": true
}
}

@ -1,33 +1,30 @@
{ {
"include": [],
"compilerOptions": { "compilerOptions": {
"target": "es2015", "rootDir": "src",
"module": "es6",
// target node v8+ (https://node.green/)
// the only missing feature is Array.prototype.values
"lib": ["es2017"],
"target": "es2017",
"declaration": true, "declaration": true,
"declarationDir": "types", "declarationDir": "types",
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmitOnError": true, "noEmitOnError": true,
"lib": [ "noErrorTruncation": true,
"es5",
"es6", // rollup takes care of these
"dom", "module": "esnext",
"es2015"
],
"importHelpers": true,
"moduleResolution": "node", "moduleResolution": "node",
"baseUrl": ".", "resolveJsonModule": true,
"paths": { "allowSyntheticDefaultImports": true,
"svelte/internal": ["./src/runtime/internal/index"],
"svelte/easing": ["./src/runtime/easing/index"], // TODO: error all the things
"svelte/motion": ["./src/runtime/motion/index"], //"strict": true,
"svelte/store": ["./src/runtime/store/index"] "noImplicitThis": true,
}, "noUnusedLocals": true,
"typeRoots": [ "noUnusedParameters": true
"node_modules/@types" }
]
},
"include": [
"src/**/*"
]
} }

Loading…
Cancel
Save