pull/4742/head
pushkine 5 years ago
parent eaf599f910
commit 7e33e110d1

@ -9,8 +9,10 @@ internal_exports.ts
# output files # output files
animate/*.js animate/*.js
esing/*.js easing/*.js
environment/*.js
internal/*.js internal/*.js
interpolate/*.js
motion/*.js motion/*.js
store/*.js store/*.js
transition/*.js transition/*.js

32
.gitignore vendored

@ -2,32 +2,42 @@
.DS_Store .DS_Store
.nyc_output .nyc_output
.vscode .vscode
node_modules node_modules
*.map
/src/compiler/compile/internal_exports.ts /src/compiler/compile/internal_exports.ts
/compiler.d.ts
/compiler.*js /animate
/index.*js
/internal
/dev /dev
/store
/easing /easing
/environment
/internal
/interpolate /interpolate
/motion /motion
/store
/transition /transition
/animate
/types
*.map
/compiler.d.ts
/compiler.*js
/index.*js
/scratch/ /scratch/
/coverage/ /coverage/
/coverage.lcov /coverage.lcov
/yarn-error.log
_actual*.*
_output
/test/*/samples/_ /test/*/samples/_
/test/sourcemaps/samples/*/output.js /test/sourcemaps/samples/*/output.js
/test/sourcemaps/samples/*/output.js.map /test/sourcemaps/samples/*/output.js.map
/test/sourcemaps/samples/*/output.css /test/sourcemaps/samples/*/output.css
/test/sourcemaps/samples/*/output.css.map /test/sourcemaps/samples/*/output.css.map
/yarn-error.log
_actual*.*
_output
/types
/site/cypress/screenshots/ /site/cypress/screenshots/
/site/__sapper__/ /site/__sapper__/

@ -2,11 +2,13 @@
Object.defineProperty(exports, '__esModule', { value: true }); Object.defineProperty(exports, '__esModule', { value: true });
function noop() {}
const is_browser = typeof window !== 'undefined'; const is_browser = typeof window !== 'undefined';
const is_iframe = is_browser && window.self !== window.top; const is_iframe = /*#__PURE__*/ is_browser && window.self !== window.top;
const is_cors = const is_cors =
is_iframe && is_iframe &&
(() => { /*#__PURE__*/ (() => {
try { try {
if (window.parent) void window.parent.document; if (window.parent) void window.parent.document;
return false; return false;
@ -16,9 +18,28 @@ const is_cors =
})(); })();
const has_Symbol = typeof Symbol === 'function'; const has_Symbol = typeof Symbol === 'function';
const globals = is_browser ? window : typeof globalThis !== 'undefined' ? globalThis : global; const globals = is_browser ? window : typeof globalThis !== 'undefined' ? globalThis : global;
const resolved_promise = Promise.resolve();
exports.now = /*#__PURE__*/ is_browser ? performance.now.bind(performance) : Date.now.bind(Date);
exports.raf = /*#__PURE__*/ is_browser ? requestAnimationFrame : noop;
exports.framerate = 1000 / 60;
exports.raf((t1) => {
exports.raf((d) => {
const f24 = 1000 / 24,
f144 = 1000 / 144;
exports.framerate = (d = d - t1) > f144 ? f144 : d < f24 ? f24 : d;
});
});
/* tests only */
const test$set_now = (fn) => void (exports.now = fn);
const test$set_raf = (fn) => void (exports.raf = fn);
exports.globals = globals; exports.globals = globals;
exports.has_Symbol = has_Symbol; exports.has_Symbol = has_Symbol;
exports.is_browser = is_browser; exports.is_browser = is_browser;
exports.is_cors = is_cors; exports.is_cors = is_cors;
exports.is_iframe = is_iframe; exports.is_iframe = is_iframe;
exports.resolved_promise = resolved_promise;
exports.test$set_now = test$set_now;
exports.test$set_raf = test$set_raf;

@ -1,8 +1,10 @@
function noop() {}
const is_browser = typeof window !== 'undefined'; const is_browser = typeof window !== 'undefined';
const is_iframe = is_browser && window.self !== window.top; const is_iframe = /*#__PURE__*/ is_browser && window.self !== window.top;
const is_cors = const is_cors =
is_iframe && is_iframe &&
(() => { /*#__PURE__*/ (() => {
try { try {
if (window.parent) void window.parent.document; if (window.parent) void window.parent.document;
return false; return false;
@ -12,5 +14,21 @@ const is_cors =
})(); })();
const has_Symbol = typeof Symbol === 'function'; const has_Symbol = typeof Symbol === 'function';
const globals = is_browser ? window : typeof globalThis !== 'undefined' ? globalThis : global; const globals = is_browser ? window : typeof globalThis !== 'undefined' ? globalThis : global;
const resolved_promise = Promise.resolve();
let now = /*#__PURE__*/ is_browser ? performance.now.bind(performance) : Date.now.bind(Date);
let raf = /*#__PURE__*/ is_browser ? requestAnimationFrame : noop;
let framerate = 1000 / 60;
raf((t1) => {
raf((d) => {
const f24 = 1000 / 24,
f144 = 1000 / 144;
framerate = (d = d - t1) > f144 ? f144 : d < f24 ? f24 : d;
});
});
/* tests only */
const test$set_now = (fn) => void (now = fn);
const test$set_raf = (fn) => void (raf = fn);
export { globals, has_Symbol, is_browser, is_cors, is_iframe }; export { framerate, globals, has_Symbol, is_browser, is_cors, is_iframe, now, raf, resolved_promise, test$set_now, test$set_raf };

@ -5,16 +5,19 @@
"module": "index.mjs", "module": "index.mjs",
"main": "index", "main": "index",
"files": [ "files": [
"animate",
"dev",
"easing",
"environment",
"internal",
"interpolate",
"motion",
"store",
"transition",
"types", "types",
"compiler.*", "compiler.*",
"register.js", "register.js",
"index.*", "index.*",
"internal",
"store",
"animate",
"transition",
"easing",
"motion",
"svelte", "svelte",
"README.md" "README.md"
], ],

@ -15,14 +15,19 @@ const ts_plugin = is_publish
// documented in src/ambient.ts // documented in src/ambient.ts
const globals = (name) => const globals = (name) =>
replace({ name === 'compiler'
'var __DEV__: boolean': 'var rollup_removes_this', ? replace({
'__DEV__': name === 'dev', 'var __VERSION__: string': 'var rollup_removes_this',
'var __TEST__: boolean': 'var rollup_removes_this', '__VERSION__': `"${pkg.version}"`,
'__TEST__': name === 'test', })
'var __VERSION__: string': 'var rollup_removes_this', : replace({
'__VERSION__': `"${pkg.version}"`, 'var __DEV__: boolean': 'var rollup_removes_this',
}); '__DEV__': name === 'dev',
'var __TEST__: boolean': 'var rollup_removes_this',
'__TEST__': name === 'test',
'var __VERSION__: string': 'var rollup_removes_this',
'__VERSION__': `"${pkg.version}"`,
});
/** /**
* *
*/ */

@ -53,5 +53,3 @@ declare var __VERSION__: string;
* instead of relying on hacks * instead of relying on hacks
*/ */
declare var __TEST__: boolean; declare var __TEST__: boolean;
declare var global: any;

@ -181,24 +181,29 @@ export default class Component {
injected: true, injected: true,
referenced: true, referenced: true,
}); });
} else if (name[0] === '$') { } else {
this.add_var({ if (!name) {
name, console.log(name);
injected: true, }
referenced: true, if (name[0] === '$') {
mutated: true, this.add_var({
writable: true, name,
}); injected: true,
referenced: true,
mutated: true,
writable: true,
});
const subscribable_name = name.slice(1); const subscribable_name = name.slice(1);
const variable = this.var_lookup.get(subscribable_name); const variable = this.var_lookup.get(subscribable_name);
if (variable) { if (variable) {
variable.referenced = true; variable.referenced = true;
variable.subscribable = true; variable.subscribable = true;
}
} else {
this.used_names.add(name);
} }
} else {
this.used_names.add(name);
} }
} }

@ -36,14 +36,14 @@ export default function create_module(
throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`); throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`);
} }
function edit_source(source, sveltePath) { const edit_source = (source, sveltePath) => (/^svelte\/?/.test(source) ? source.replace('svelte', sveltePath) : source);
return source === 'svelte' || source.startsWith('svelte/') ? source.replace('svelte', sveltePath) : source;
}
function get_internal_globals( function get_internal_globals(
globals: Array<{ name: string; alias: Identifier }>, globals: Array<{ name: string; alias: Identifier }>,
helpers: Array<{ name: string; alias: Identifier }> helpers: Array<{ name: string; alias: Identifier }>
) { ) {
// TODO : internal_globals is too aggressive
// see output https://svelte.dev/repl/1623b8b2ff604d7ca6e794343d976ae6
return ( return (
globals.length > 0 && { globals.length > 0 && {
type: 'VariableDeclaration', type: 'VariableDeclaration',

@ -68,7 +68,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
} }
export default function compile(source: string, options: CompileOptions = {}) { export default function compile(source: string, options: CompileOptions = {}) {
options = { generate: 'dom', dev: false, ...options }; options = { generate: 'dom', dev: null, ...options };
const stats = new Stats(); const stats = new Stats();
const warnings = []; const warnings = [];

@ -30,7 +30,7 @@ export default class Expression {
scope: Scope; scope: Scope;
scope_map: WeakMap<Node, Scope>; scope_map: WeakMap<Node, Scope>;
declarations: Array<(Node | Node[])> = []; declarations: Array<Node | Node[]> = [];
uses_context = false; uses_context = false;
manipulated: Node; manipulated: Node;
@ -40,8 +40,8 @@ export default class Expression {
// TODO revert to direct property access in prod? // TODO revert to direct property access in prod?
Object.defineProperties(this, { Object.defineProperties(this, {
component: { component: {
value: component value: component,
} },
}); });
this.node = info; this.node = info;
@ -79,12 +79,13 @@ export default class Expression {
if (name[0] === '$' && template_scope.names.has(name.slice(1))) { if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
component.error(node, { component.error(node, {
code: `contextual-store`, code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)` message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`,
}); });
} }
if (template_scope.is_let(name)) { if (template_scope.is_let(name)) {
if (!function_expression) { // TODO should this be `!lazy` ? if (!function_expression) {
// TODO should this be `!lazy` ?
contextual_dependencies.add(name); contextual_dependencies.add(name);
dependencies.add(name); dependencies.add(name);
} }
@ -97,7 +98,7 @@ export default class Expression {
const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index; const is_index = owner.type === 'EachBlock' && owner.key && name === owner.index;
if (!lazy || is_index) { if (!lazy || is_index) {
template_scope.dependencies_for_name.get(name).forEach(name => dependencies.add(name)); template_scope.dependencies_for_name.get(name).forEach((name) => dependencies.add(name));
} }
} else { } else {
if (!lazy) { if (!lazy) {
@ -118,9 +119,7 @@ export default class Expression {
if (function_expression) { if (function_expression) {
if (node.type === 'AssignmentExpression') { if (node.type === 'AssignmentExpression') {
deep = node.left.type === 'MemberExpression'; deep = node.left.type === 'MemberExpression';
names = deep names = deep ? [get_object(node.left).name] : extract_names(node.left);
? [get_object(node.left).name]
: extract_names(node.left);
} else if (node.type === 'UpdateExpression') { } else if (node.type === 'UpdateExpression') {
const { name } = get_object(node.argument); const { name } = get_object(node.argument);
names = [name]; names = [name];
@ -128,9 +127,10 @@ export default class Expression {
} }
if (names) { if (names) {
names.forEach(name => { names.forEach((name) => {
if (!name) return;
if (template_scope.names.has(name)) { if (template_scope.names.has(name)) {
template_scope.dependencies_for_name.get(name).forEach(name => { template_scope.dependencies_for_name.get(name).forEach((name) => {
const variable = component.var_lookup.get(name); const variable = component.var_lookup.get(name);
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true; if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
}); });
@ -152,12 +152,12 @@ export default class Expression {
if (node === function_expression) { if (node === function_expression) {
function_expression = null; function_expression = null;
} }
} },
}); });
} }
dynamic_dependencies() { dynamic_dependencies() {
return Array.from(this.dependencies).filter(name => { return Array.from(this.dependencies).filter((name) => {
if (this.template_scope.is_let(name)) return true; if (this.template_scope.is_let(name)) return true;
if (is_reserved_keyword(name)) return true; if (is_reserved_keyword(name)) return true;
@ -172,13 +172,7 @@ export default class Expression {
// multiple times // multiple times
if (this.manipulated) return this.manipulated; if (this.manipulated) return this.manipulated;
const { const { component, declarations, scope_map: map, template_scope, owner } = this;
component,
declarations,
scope_map: map,
template_scope,
owner
} = this;
let scope = this.scope; let scope = this.scope;
let function_expression; let function_expression;
@ -206,7 +200,7 @@ export default class Expression {
if (template_scope.names.has(name)) { if (template_scope.names.has(name)) {
contextual_dependencies.add(name); contextual_dependencies.add(name);
template_scope.dependencies_for_name.get(name).forEach(dependency => { template_scope.dependencies_for_name.get(name).forEach((dependency) => {
dependencies.add(dependency); dependencies.add(dependency);
}); });
} else { } else {
@ -238,9 +232,7 @@ export default class Expression {
if (map.has(node)) scope = scope.parent; if (map.has(node)) scope = scope.parent;
if (node === function_expression) { if (node === function_expression) {
const id = component.get_unique_name( const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
sanitize(get_function_name(node, owner))
);
const declaration = b`const ${id} = ${node}`; const declaration = b`const ${id} = ${node}`;
@ -254,28 +246,24 @@ export default class Expression {
name: id.name, name: id.name,
internal: true, internal: true,
hoistable: true, hoistable: true,
referenced: true referenced: true,
}); });
} } else if (contextual_dependencies.size === 0) {
else if (contextual_dependencies.size === 0) {
// function can be hoisted inside the component init // function can be hoisted inside the component init
component.partly_hoisted.push(declaration); component.partly_hoisted.push(declaration);
block.renderer.add_to_context(id.name); block.renderer.add_to_context(id.name);
this.replace(block.renderer.reference(id)); this.replace(block.renderer.reference(id));
} } else {
else {
// we need a combo block/init recipe // we need a combo block/init recipe
const deps = Array.from(contextual_dependencies); const deps = Array.from(contextual_dependencies);
(node as FunctionExpression).params = [ (node as FunctionExpression).params = [
...deps.map(name => ({ type: 'Identifier', name } as Identifier)), ...deps.map((name) => ({ type: 'Identifier', name } as Identifier)),
...(node as FunctionExpression).params ...(node as FunctionExpression).params,
]; ];
const context_args = deps.map(name => block.renderer.reference(name)); const context_args = deps.map((name) => block.renderer.reference(name));
component.partly_hoisted.push(declaration); component.partly_hoisted.push(declaration);
@ -318,10 +306,10 @@ export default class Expression {
const names = new Set(extract_names(assignee)); const names = new Set(extract_names(assignee));
const traced: Set<string> = new Set(); const traced: Set<string> = new Set();
names.forEach(name => { names.forEach((name) => {
const dependencies = template_scope.dependencies_for_name.get(name); const dependencies = template_scope.dependencies_for_name.get(name);
if (dependencies) { if (dependencies) {
dependencies.forEach(name => traced.add(name)); dependencies.forEach((name) => traced.add(name));
} else { } else {
traced.add(name); traced.add(name);
} }
@ -329,12 +317,12 @@ export default class Expression {
this.replace(invalidate(block.renderer, scope, node, traced)); this.replace(invalidate(block.renderer, scope, node, traced));
} }
} },
}); });
if (declarations.length > 0) { if (declarations.length > 0) {
block.maintain_context = true; block.maintain_context = true;
declarations.forEach(declaration => { declarations.forEach((declaration) => {
block.chunks.init.push(declaration); block.chunks.init.push(declaration);
}); });
} }

@ -230,6 +230,8 @@ export default class Block {
get_contents(key?: any) { get_contents(key?: any) {
const { dev, version } = this.renderer.options; const { dev, version } = this.renderer.options;
let k;
for (k in this.chunks) this.chunks[k] = this.chunks[k].filter(Boolean);
if (this.has_outros) { if (this.has_outros) {
this.add_variable({ type: 'Identifier', name: '#current' }); this.add_variable({ type: 'Identifier', name: '#current' });
@ -420,17 +422,17 @@ export default class Block {
} }
has_content(): boolean { has_content(): boolean {
return ( return !!(
!!this.first || this.first ||
this.event_listeners.length > 0 || this.event_listeners.length ||
this.chunks.intro.length > 0 || this.chunks.intro.length ||
this.chunks.outro.length > 0 || this.chunks.outro.length ||
this.chunks.create.length > 0 || this.chunks.create.length ||
this.chunks.hydrate.length > 0 || this.chunks.hydrate.length ||
this.chunks.claim.length > 0 || this.chunks.claim.length ||
this.chunks.mount.length > 0 || this.chunks.mount.length ||
this.chunks.update.length > 0 || this.chunks.update.length ||
this.chunks.destroy.length > 0 || this.chunks.destroy.length ||
this.has_animation this.has_animation
); );
} }
@ -472,13 +474,13 @@ export default class Block {
this.chunks.destroy.push(b`${dispose}();`); this.chunks.destroy.push(b`${dispose}();`);
} else { } else {
this.chunks.mount.push(b` this.chunks.mount.push(b`
if (#remount) for(let #i=0;#i<${dispose}.length;#i++){ ${dispose}[#i];} if (#remount) for(let #i=0;#i<${dispose}.length;#i++){ ${dispose}[#i](); }
${dispose} = [ ${dispose} = [
${this.event_listeners} ${this.event_listeners}
]; ];
`); `);
this.chunks.destroy.push(b`for(let #i=0;#i<${dispose}.length;#i++){ ${dispose}[#i];}`); this.chunks.destroy.push(b`for(let #i=0;#i<${dispose}.length;#i++){ ${dispose}[#i](); }`);
} }
} }
} }

@ -55,9 +55,6 @@ export default class EachBlockWrapper extends Wrapper {
each_block_value: Identifier; each_block_value: Identifier;
get_each_context: Identifier; get_each_context: Identifier;
iterations: Identifier; iterations: Identifier;
fixed_length: number;
data_length: string;
view_length: string;
}; };
context_props: Array<Node | Node[]>; context_props: Array<Node | Node[]>;
@ -92,7 +89,6 @@ export default class EachBlockWrapper extends Wrapper {
type: 'each', type: 'each',
// @ts-ignore todo: probably error // @ts-ignore todo: probably error
key: node.key as string, key: node.key as string,
bindings: new Map(block.bindings), bindings: new Map(block.bindings),
}); });
@ -103,42 +99,16 @@ export default class EachBlockWrapper extends Wrapper {
? { type: 'Identifier', name: this.node.index } ? { type: 'Identifier', name: this.node.index }
: renderer.component.get_unique_name(`${this.node.context}_index`); : renderer.component.get_unique_name(`${this.node.context}_index`);
const fixed_length =
node.expression.node.type === 'ArrayExpression' &&
node.expression.node.elements.every((element) => element.type !== 'SpreadElement')
? node.expression.node.elements.length
: null;
// hack the sourcemap, so that if data is missing the bug
// is easy to find
let c = this.node.start + 2;
while (renderer.component.source[c] !== 'e') c += 1;
const start = renderer.component.locate(c);
const end = { line: start.line, column: start.column + 4 };
const length = {
type: 'Identifier',
name: 'length',
loc: { start, end },
};
const each_block_value = renderer.component.get_unique_name(`${this.var.name}_value`);
const iterations = block.get_unique_name(`${this.var.name}_blocks`);
renderer.add_to_context(each_block_value.name, true);
renderer.add_to_context(this.index_name.name, true);
this.vars = { this.vars = {
create_each_block: this.block.name, create_each_block: this.block.name,
each_block_value, each_block_value: renderer.component.get_unique_name(`${this.var.name}_value`),
get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`), get_each_context: renderer.component.get_unique_name(`get_${this.var.name}_context`),
iterations, iterations: block.get_unique_name(`${this.var.name}_blocks`),
// optimisation for array literal
fixed_length,
data_length: fixed_length === null ? x`${each_block_value}.${length}` : fixed_length,
view_length: fixed_length === null ? x`${iterations}.length` : fixed_length,
}; };
renderer.add_to_context(this.vars.each_block_value.name, true);
renderer.add_to_context(this.index_name.name, true);
const store = const store =
node.expression.node.type === 'Identifier' && node.expression.node.name[0] === '$' node.expression.node.type === 'Identifier' && node.expression.node.name[0] === '$'
? node.expression.node.name.slice(1) ? node.expression.node.name.slice(1)
@ -182,7 +152,8 @@ export default class EachBlockWrapper extends Wrapper {
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
if (this.fragment.nodes.length === 0) return; if (this.fragment.nodes.length === 0) return;
const __DEV__ = this.renderer.options.dev;
const { each_block_value, iterations: each_block } = this.vars;
const { renderer } = this; const { renderer } = this;
const { component } = renderer; const { component } = renderer;
@ -193,20 +164,17 @@ export default class EachBlockWrapper extends Wrapper {
); );
if (this.node.has_binding) if (this.node.has_binding)
this.context_props.push( this.context_props.push(b`child_ctx[${renderer.context_lookup.get(each_block_value.name).index}] = list;`);
b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`
);
if (this.node.has_binding || this.node.index) if (this.node.has_binding || this.node.index)
this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`); this.context_props.push(b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`);
const snippet = this.node.expression.manipulate(block); const snippet = this.node.expression.manipulate(block);
block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`); block.chunks.init.push(b`let ${each_block_value} = ${snippet};`);
if (this.renderer.options.dev) { if (__DEV__) {
block.chunks.init.push(b`@validate_each_argument(${this.vars.each_block_value});`); block.chunks.init.push(b`@validate_each_argument(${each_block_value});`);
} }
// TODO which is better — Object.create(array) or array.slice()?
renderer.blocks.push(b` renderer.blocks.push(b`
function ${this.vars.get_each_context}(#ctx, list, i) { function ${this.vars.get_each_context}(#ctx, list, i) {
const child_ctx = #ctx.slice(); const child_ctx = #ctx.slice();
@ -246,11 +214,7 @@ export default class EachBlockWrapper extends Wrapper {
} }
if (this.block.has_intro_method || this.block.has_outro_method) { if (this.block.has_intro_method || this.block.has_outro_method) {
block.chunks.intro.push(b` block.chunks.intro.push(for_loop(each_block, (item) => b`@transition_in(${item});`));
for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
@transition_in(${this.vars.iterations}[#i]);
}
`);
} }
if (needs_anchor) { if (needs_anchor) {
@ -260,20 +224,18 @@ export default class EachBlockWrapper extends Wrapper {
if (this.else) { if (this.else) {
const each_block_else = component.get_unique_name(`${this.var.name}_else`); const each_block_else = component.get_unique_name(`${this.var.name}_else`);
block.chunks.init.push(b`let ${each_block_else} = null;`);
// TODO neaten this up... will end up with an empty line in the block // TODO neaten this up... will end up with an empty line in the block
block.chunks.init.push(b` block.chunks.init.push(
if (!${this.vars.data_length}) { b`let ${each_block_else} = null;`,
${each_block_else} = ${this.else.block.name}(#ctx); b`if (!${each_block_value}.length) {
} ${each_block_else} = ${this.else.block.name}(#ctx);
`); }`
);
block.chunks.create.push(b` block.chunks.create.push(b`
if (${each_block_else}) { if (${each_block_else}) {
${each_block_else}.c(); ${each_block_else}.c();
} }`);
`);
if (this.renderer.options.hydratable) { if (this.renderer.options.hydratable) {
block.chunks.claim.push(b` block.chunks.claim.push(b`
@ -288,40 +250,37 @@ export default class EachBlockWrapper extends Wrapper {
${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node}); ${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
} }
`); `);
const no_each_else = x`!${each_block_value}.length`;
const update_else = b`${each_block_else}.p(#ctx, #dirty);`;
const destroy_else = b`${each_block_else}.d(1);${each_block_else} = null;`;
const create_else = b`
${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c();
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});`;
if (this.else.block.has_update_method) { this.updates.push(
this.updates.push(b` $if({
if (!${this.vars.data_length} && ${each_block_else}) { if: each_block_else,
${each_block_else}.p(#ctx, #dirty); true: $if({
} else if (!${this.vars.data_length}) { if: no_each_else,
${each_block_else} = ${this.else.block.name}(#ctx); true: update_else,
${each_block_else}.c(); false: destroy_else,
${each_block_else}.m(${update_mount_node}, ${update_anchor_node}); }),
} else if (${each_block_else}) { false: $if({
${each_block_else}.d(1); if: no_each_else,
${each_block_else} = null; true: create_else,
} }),
`); })
} else { );
this.updates.push(b`
if (${this.vars.data_length}) {
if (${each_block_else}) {
${each_block_else}.d(1);
${each_block_else} = null;
}
} else if (!${each_block_else}) {
${each_block_else} = ${this.else.block.name}(#ctx);
${each_block_else}.c();
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
}
`);
}
block.chunks.destroy.push(b` block.chunks.destroy.push(b`
if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'}); if (${each_block_else}){
${each_block_else}.d(${parent_node ? '' : 'detaching'});
}
`); `);
} }
this.updates = this.updates.filter(Boolean);
if (this.updates.length) { if (this.updates.length) {
block.chunks.update.push(b` block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(all_dependencies))}) { if (${block.renderer.dirty(Array.from(all_dependencies))}) {
@ -356,104 +315,76 @@ export default class EachBlockWrapper extends Wrapper {
update_anchor_node: Identifier; update_anchor_node: Identifier;
update_mount_node: Identifier; update_mount_node: Identifier;
}) { }) {
const { create_each_block, iterations, data_length, view_length } = this.vars; const __DEV__ = this.renderer.options.dev;
const {
create_each_block,
iterations: each_block,
each_block_value,
get_each_context: each_context_getter,
} = this.vars;
const get_key = block.get_unique_name('get_key'); const for_each_block = (fn) => for_loop(each_block, fn);
const key_getter = block.get_unique_name('get_key');
const lookup = block.get_unique_name(`${this.var.name}_lookup`); const lookup = block.get_unique_name(`${this.var.name}_lookup`);
block.add_variable(iterations, x`[]`); block.add_variable(each_block, x`[]`);
block.add_variable(lookup, x`new @_Map()`); block.add_variable(lookup, x`new @_Map()`);
if (this.fragment.nodes[0].is_dom_node()) { if (this.fragment.nodes[0].is_dom_node()) this.block.first = this.fragment.nodes[0].var;
this.block.first = this.fragment.nodes[0].var; else
} else { this.block.add_element(
this.block.first = this.block.get_unique_name('first'); (this.block.first = this.block.get_unique_name('first')),
this.block.add_element(this.block.first, x`@empty()`, parent_nodes && x`@empty()`, null); x`@empty()`,
} parent_nodes && x`@empty()`,
null
block.chunks.init.push(b` );
const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
${
this.renderer.options.dev &&
b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`
}
for (let #i = 0; #i < ${data_length}; #i += 1) {
let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
let key = ${get_key}(child_ctx);
${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
}
`);
block.chunks.create.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].c();
}
`);
if (parent_nodes && this.renderer.options.hydratable) { const validate_each_keys =
block.chunks.claim.push(b` __DEV__ && b`@validate_each_keys(#ctx, ${each_block_value}, ${each_context_getter}, ${key_getter});`;
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].l(${parent_nodes}); const validate_each_argument = __DEV__ && b`@validate_each_argument(${each_block_value});`;
}
`); block.chunks.init.push(
} b`const ${key_getter} = (#ctx) => ${this.node.key.manipulate(block)};`,
validate_each_keys,
for_loop(
each_block_value,
(_, index) => b`
const #child_ctx = ${each_context_getter}(#ctx, ${each_block_value}, ${index});
const #key = ${key_getter}(#child_ctx);
${lookup}.set(#key, (${each_block}[${index}] = ${create_each_block}(#key, #child_ctx)));`
)
);
block.chunks.mount.push(b` block.chunks.create.push(for_each_block((block) => b`${block}.c();`));
for (let #i = 0; #i < ${view_length}; #i += 1) { if (parent_nodes && this.renderer.options.hydratable)
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node}); block.chunks.claim.push(for_each_block((block) => b`${block}.l(${parent_nodes});`));
} block.chunks.mount.push(for_each_block((block) => b`${block}.m(${initial_mount_node}, ${initial_anchor_node});`));
`);
const dynamic = this.block.has_update_method; const dynamic = this.block.has_update_method;
const has_animation = this.node.has_animation || null;
// const destroy = this.node.has_animation const { has_outros } = this.block;
// ? this.block.has_outros
// ? `@fix_and_outro_and_destroy_block`
// : `@fix_and_destroy_block`
// : this.block.has_outros
// ? `@outro_and_destroy_block`
// : `@destroy_block`;
if (this.dependencies.size) { if (this.dependencies.size) {
const transition_state = bit_state([dynamic, has_animation, has_outros]);
const update_keyed_each = (transition_out) =>
b`${each_block} = @update_keyed_each(${each_block}, #dirty, #ctx, ${transition_state}, ${key_getter}, ${each_block_value}, ${lookup}, ${update_mount_node}, ${create_each_block}, ${update_anchor_node}, ${each_context_getter}, ${transition_out});`;
const measure_animations = has_animation && b`${for_each_block((block) => b`${block}.r();`)}`;
this.updates.push( this.updates.push(
b` b`const ${each_block_value} = ${snippet};`,
const ${this.vars.each_block_value} = ${snippet}; validate_each_keys,
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}`, validate_each_argument,
this.block.group_transition_out( measure_animations,
(transition_out) => b` this.block.group_transition_out((transition_out) => update_keyed_each(transition_out)),
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1){ ${iterations}[#i].r();}`} has_animation && for_each_block((block) => b`${block}.a();`)
${
this.renderer.options.dev &&
b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`
}
${iterations} = @update_keyed_each(${iterations}, #dirty, #ctx, ${bit_state([
dynamic,
this.node.has_animation,
this.block.has_outros,
])}, ${get_key}, ${
this.vars.each_block_value
}, ${lookup}, ${update_mount_node}, ${create_each_block}, ${update_anchor_node}, ${
this.vars.get_each_context
}, ${transition_out});
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1){ ${iterations}[#i].a();}`}`
)
); );
} }
if (this.block.has_outros) { if (has_outros) block.chunks.outro.push(for_each_block((block) => b`@transition_out(${block});`));
block.chunks.outro.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
@transition_out(${iterations}[#i]);
}
`);
}
block.chunks.destroy.push(b` block.chunks.destroy.push(for_each_block((block) => b`${block}.d(${parent_node ? null : 'detaching'});`));
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].d(${parent_node ? null : 'detaching'});
}
`);
} }
render_unkeyed({ render_unkeyed({
@ -473,117 +404,109 @@ export default class EachBlockWrapper extends Wrapper {
update_anchor_node: Identifier; update_anchor_node: Identifier;
update_mount_node: Identifier; update_mount_node: Identifier;
}) { }) {
const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars; const __DEV__ = this.renderer.options.dev;
const {
block.chunks.init.push(b` create_each_block,
let ${iterations} = []; iterations: each_block,
for (let #i = 0; #i < ${data_length}; #i += 1) { each_block_value,
${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i)); get_each_context: each_context_getter,
} } = this.vars;
`); const for_each_block = (fn, opts?) => for_loop(each_block, fn, opts);
block.chunks.create.push(b` block.chunks.init.push(
for (let #i = 0; #i < ${view_length}; #i += 1) { b`let ${each_block} = [];`,
${iterations}[#i].c(); for_loop(
} each_block_value,
`); (_, index) =>
b`${each_block}[${index}] = ${create_each_block}(${each_context_getter}(#ctx, ${each_block_value}, ${index}));`
if (parent_nodes && this.renderer.options.hydratable) { )
block.chunks.claim.push(b` );
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].l(${parent_nodes});
}
`);
}
block.chunks.mount.push(b` block.chunks.create.push(for_each_block((block) => b`${block}.c();`));
for (let #i = 0; #i < ${view_length}; #i += 1) { if (parent_nodes && this.renderer.options.hydratable)
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node}); block.chunks.claim.push(for_each_block((block) => b`${block}.l(${parent_nodes});`));
} block.chunks.mount.push(for_each_block((block) => b`${block}.m(${initial_mount_node}, ${initial_anchor_node});`));
`);
if (this.dependencies.size) { if (this.dependencies.size) {
const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method); const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
const { has_update_method } = this.block;
const for_loop_body = this.block.has_update_method const start = has_update_method ? 0 : `#old_length`;
? b`
if (${iterations}[#i]) {
${iterations}[#i].p(child_ctx, #dirty);
${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`}
} else {
${iterations}[#i] = ${create_each_block}(child_ctx);
${iterations}[#i].c();
${has_transitions && b`@transition_in(${this.vars.iterations}[#i], 1);`}
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
}
`
: has_transitions
? b`
if (${iterations}[#i]) {
@transition_in(${this.vars.iterations}[#i], 1);
} else {
${iterations}[#i] = ${create_each_block}(child_ctx);
${iterations}[#i].c();
@transition_in(${this.vars.iterations}[#i], 1);
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
}
`
: b`
if (!${iterations}[#i]) {
${iterations}[#i] = ${create_each_block}(child_ctx);
${iterations}[#i].c();
${iterations}[#i].m(${update_mount_node}, ${update_anchor_node});
}
`;
const start = this.block.has_update_method ? 0 : `#old_length`;
const remove_old_blocks = this.block.group_transition_out((transition_out) =>
transition_out
? b`
for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
${transition_out}(${iterations}[#i], () => { ${iterations}[#i] = null; });
}`
: b`
for (${this.block.has_update_method ? null : x`#i = ${data_length}`};
#i < ${this.block.has_update_method ? view_length : '#old_length'};
#i += 1 ) {
${iterations}[#i].d(1);
}
${!fixed_length && b`${view_length} = ${data_length};`}
`
);
// We declare `i` as block scoped here, as the `remove_old_blocks` code // We declare `i` as block scoped here, as the `remove_old_blocks` code
// may rely on continuing where this iteration stopped. // may rely on continuing where this iteration stopped.
const update = b` this.updates.push(b`
${!this.block.has_update_method && b`const #old_length = ${this.vars.each_block_value}.length;`} ${!has_update_method && b`const #old_length = ${each_block_value}.length;`}
${this.vars.each_block_value} = ${snippet}; ${each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} ${__DEV__ && b`@validate_each_argument(${each_block_value});`}
let #i; let #i;
for (#i = ${start}; #i < ${data_length}; #i += 1) { ${for_each_block(
const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i); (block, index) => b`
const #child_ctx = ${each_context_getter}(#ctx, ${each_block_value}, ${index});
${for_loop_body} ${$if({
} if: (has_update_method || has_transitions) && block,
true: b`
${remove_old_blocks} ${has_update_method && b`${block}.p(#child_ctx, #dirty);`}
`; ${has_transitions && b`@transition_in(${block}, 1);`}
`,
this.updates.push(update); false: b`
${block} = ${create_each_block}(#child_ctx);
${block}.c();
${has_transitions && b`@transition_in(${block}, 1);`}
${block}.m(${update_mount_node}, ${update_anchor_node});
`,
})}`,
{ i: start }
)}
${this.block.group_transition_out((transition_out) =>
for_each_block(
(block) =>
transition_out ? b`${transition_out}(${block}, () => { ${block} = null; });` : b`${block}.d(1);`,
{
i: has_update_method && !transition_out ? null : x`#i = ${each_block_value}.length`,
length: has_update_method || transition_out ? x`${each_block}.length` : x`#old_length`,
}
)
)}
${each_block}.length = ${each_block_value}.length;
`);
} }
if (this.block.has_outros) { if (this.block.has_outros) {
block.chunks.outro.push(b` block.chunks.outro.push(b`
${iterations} = ${iterations}.filter(@_Boolean); ${each_block} = ${each_block}.filter(@_Boolean);
for (let #i = 0; #i < ${view_length}; #i += 1) { ${for_each_block((block) => b`@transition_out(${block})`)}`);
@transition_out(${iterations}[#i]);
}
`);
} }
block.chunks.destroy.push(b`@destroy_each(${iterations}, detaching);`); block.chunks.destroy.push(b`@destroy_each(${each_block}, detaching);`);
} }
} }
const bit_state = (arr) => arr.reduce((state, bool, index) => (bool ? (state |= 1 << index) : state), 0); const bit_state = (arr) => arr.reduce((state, bool, index) => (bool ? (state |= 1 << index) : state), 0);
const for_loop = <T>(
arr: T,
callback: (item: Node, index: Node, array: T) => Node[],
{ length = x`${arr}.length`, i = undefined } = {}
) =>
i || i === null
? b`for (${i}; #i < ${length}; #i++) { ${callback(x`${arr}[#i]`, x`#i`, arr)} }`
: b`for (let #i = 0; #i < ${length}; #i++) { ${callback(x`${arr}[#i]`, x`#i`, arr)} }`;
const $if = ({ if: condition, true: success, false: failure = null }) => {
if (condition) {
if (success) {
if (failure) {
return b`if(${condition}){ ${success} } else { ${failure} }`;
} else {
return b`if(${condition}){ ${success} }`;
}
} else if (failure) {
return b`if(!${condition}){ ${success} }`;
}
} else {
if (!failure) {
return failure;
}
}
throw new Error('Error in if_else');
};

@ -692,31 +692,28 @@ export default class ElementWrapper extends Wrapper {
add_intro(block: Block, intro: Transition, outro: Transition) { add_intro(block: Block, intro: Transition, outro: Transition) {
if (outro) { if (outro) {
const outro_var = block.alias(`${this.var.name}_outro`); const outro_var = block.alias(`${this.var.name}_outro`);
if (this.node.animation) { block.chunks.intro.push(b`
const [unfreeze_var, rect_var, stop_animation_var, animationFn, params] = run_animation(this, block);
block.chunks.intro.push(b`
if (${outro_var}){ if (${outro_var}){
${outro_var}(1); ${outro_var}(1);
if (${unfreeze_var}) {
${unfreeze_var}(), (unfreeze = undefined);
${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${animationFn}, ${params});
}
} }
`); `);
} else { }
block.chunks.intro.push(b` if (this.node.animation) {
if (${outro_var}){ const [unfreeze_var, rect_var, stop_animation_var, animationFn, params] = run_animation(this, block);
${outro_var}(1); block.chunks.intro.push(b`
} if (${unfreeze_var}) {
`); ${unfreeze_var}();
} ${unfreeze_var} = void 0;
${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${animationFn}, ${params});
}
`);
} }
if (!intro) return; if (!intro) return;
const [intro_var, node, transitionFn, params] = run_transition(this, block, intro, `intro`); const [intro_var, node, transitionFn, params] = run_transition(this, block, intro, `intro`);
block.add_variable(intro_var); block.add_variable(intro_var);
let start_intro = b`@add_render_callback(()=>{${intro_var} = @run_transition(${node}, ${transitionFn}, true, ${params});})`; let start_intro = b`${intro_var} = @run_transition(${node}, ${transitionFn}, true, ${params});`;
if (intro.is_local) start_intro = b`if (#local) ${start_intro};`; if (intro.is_local) start_intro = b`if (#local) ${start_intro};`;
block.chunks.intro.push(start_intro); block.chunks.intro.push(start_intro);
} }
@ -750,23 +747,24 @@ export default class ElementWrapper extends Wrapper {
block.add_variable(stop_animation_var, x`@noop`); block.add_variable(stop_animation_var, x`@noop`);
block.chunks.measure.push(b` block.chunks.measure.push(b`
${rect_var} = ${this.var}.getBoundingClientRect(); if(!${unfreeze_var}) ${rect_var} = ${this.var}.getBoundingClientRect();
${intro && b`if(${intro_var}) ${intro_var}();`} ${intro && b`if(${intro_var}) ${intro_var}();`}
`); `);
block.chunks.fix.push(b` block.chunks.fix.push(b`
${unfreeze_var} = @fix_position(${this.var});
${stop_animation_var}(); ${stop_animation_var}();
${outro && b`@add_transform(${this.var}, ${rect_var});`} ${unfreeze_var} = @fix_position(${this.var}, ${rect_var});
`); `);
block.chunks.animate.push(b` block.chunks.animate.push(b`
if(${unfreeze_var}) return if (${unfreeze_var}) return
${stop_animation_var}(); else {
@add_render_callback(()=>{${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${name_var}, ${params_var});}); ${stop_animation_var}();
${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${name_var}, ${params_var});
}
`); `);
block.chunks.destroy.push(b`${unfreeze_var} = undefined;`); block.chunks.destroy.push(b`${unfreeze_var} = void 0;`);
} }
add_classes(block: Block) { add_classes(block: Block) {
@ -882,7 +880,7 @@ function run_animation(element: ElementWrapper, block: Block) {
block.alias('rect'), block.alias('rect'),
block.alias('stop_animation'), block.alias('stop_animation'),
element.renderer.reference(element.node.animation.name), element.renderer.reference(element.node.animation.name),
element.node.animation.expression ? element.node.animation.expression.manipulate(block) : x`{}`, element.node.animation.expression ? element.node.animation.expression.manipulate(block) : null,
]; ];
} }
function run_transition(element: ElementWrapper, block: Block, transition: Transition, type: string) { function run_transition(element: ElementWrapper, block: Block, transition: Transition, type: string) {
@ -890,6 +888,6 @@ function run_transition(element: ElementWrapper, block: Block, transition: Trans
/* node_intro */ block.alias(`${element.var.name}_${type}`), /* node_intro */ block.alias(`${element.var.name}_${type}`),
/* node */ element.var, /* node */ element.var,
/* transitionFn */ element.renderer.reference(transition.name), /* transitionFn */ element.renderer.reference(transition.name),
/* params */ transition.expression ? transition.expression.manipulate(block) : x`{}`, /* params */ transition.expression ? transition.expression.manipulate(block) : null,
]; ];
} }

@ -1,64 +1,667 @@
import { isIdentifierStart, isIdentifierChar } from 'acorn'; import { isIdentifierStart, isIdentifierChar } from 'acorn';
import full_char_code_at from './full_char_code_at'; import full_char_code_at from './full_char_code_at';
/** source : rollup */
export const globals = new Set([ export const globals = new Set([
'global',
'__proto__',
'AbortController',
'AbortSignal',
'addEventListener',
'alert', 'alert',
'AnalyserNode',
'Animation',
'AnimationEvent',
'applicationCache',
'ApplicationCache',
'ApplicationCacheErrorEvent',
'Array', 'Array',
'ArrayBuffer',
'atob',
'Atomics',
'Attr',
'Audio',
'AudioBuffer',
'AudioBufferSourceNode',
'AudioContext',
'AudioDestinationNode',
'AudioListener',
'AudioNode',
'AudioParam',
'AudioProcessingEvent',
'AudioScheduledSourceNode',
'AudioWorkletNode',
'BarProp',
'BaseAudioContext',
'BatteryManager',
'BeforeUnloadEvent',
'BigInt',
'BigInt64Array',
'BigUint64Array',
'BiquadFilterNode',
'Blob',
'BlobEvent',
'blur',
'Boolean', 'Boolean',
'BroadcastChannel',
'btoa',
'ByteLengthQueuingStrategy',
'Cache',
'caches',
'CacheStorage',
'cancelAnimationFrame',
'cancelIdleCallback',
'CanvasCaptureMediaStreamTrack',
'CanvasGradient',
'CanvasPattern',
'CanvasRenderingContext2D',
'ChannelMergerNode',
'ChannelSplitterNode',
'CharacterData',
'clearInterval', 'clearInterval',
'clearTimeout', 'clearTimeout',
'clientInformation',
'ClipboardEvent',
'close',
'closed',
'CloseEvent',
'Comment',
'CompositionEvent',
'confirm', 'confirm',
'console', 'console',
'ConstantSourceNode',
'ConvolverNode',
'CountQueuingStrategy',
'createImageBitmap',
'Credential',
'CredentialsContainer',
'crypto',
'Crypto',
'CryptoKey',
'CSS',
'CSSConditionRule',
'CSSFontFaceRule',
'CSSGroupingRule',
'CSSImportRule',
'CSSKeyframeRule',
'CSSKeyframesRule',
'CSSMediaRule',
'CSSNamespaceRule',
'CSSPageRule',
'CSSRule',
'CSSRuleList',
'CSSStyleDeclaration',
'CSSStyleRule',
'CSSStyleSheet',
'CSSSupportsRule',
'CustomElementRegistry',
'customElements',
'CustomEvent',
'DataTransfer',
'DataTransferItem',
'DataTransferItemList',
'DataView',
'Date', 'Date',
'decodeURI', 'decodeURI',
'decodeURIComponent', 'decodeURIComponent',
'defaultstatus',
'defaultStatus',
'DelayNode',
'DeviceMotionEvent',
'DeviceOrientationEvent',
'devicePixelRatio',
'dispatchEvent',
'document', 'document',
'Document',
'DocumentFragment',
'DocumentType',
'DOMError',
'DOMException',
'DOMImplementation',
'DOMMatrix',
'DOMMatrixReadOnly',
'DOMParser',
'DOMPoint',
'DOMPointReadOnly',
'DOMQuad',
'DOMRect',
'DOMRectReadOnly',
'DOMStringList',
'DOMStringMap',
'DOMTokenList',
'DragEvent',
'DynamicsCompressorNode',
'Element',
'encodeURI', 'encodeURI',
'encodeURIComponent', 'encodeURIComponent',
'Error', 'Error',
'ErrorEvent',
'escape',
'eval',
'EvalError', 'EvalError',
'Event', 'Event',
'EventSource',
'EventTarget',
'external',
'fetch', 'fetch',
'global', 'File',
'FileList',
'FileReader',
'find',
'Float32Array',
'Float64Array',
'focus',
'FocusEvent',
'FontFace',
'FontFaceSetLoadEvent',
'FormData',
'frames',
'Function',
'GainNode',
'Gamepad',
'GamepadButton',
'GamepadEvent',
'getComputedStyle',
'getSelection',
'globalThis', 'globalThis',
'HashChangeEvent',
'hasOwnProperty',
'Headers',
'history', 'history',
'History',
'HTMLAllCollection',
'HTMLAnchorElement',
'HTMLAreaElement',
'HTMLAudioElement',
'HTMLBaseElement',
'HTMLBodyElement',
'HTMLBRElement',
'HTMLButtonElement',
'HTMLCanvasElement',
'HTMLCollection',
'HTMLContentElement',
'HTMLDataElement',
'HTMLDataListElement',
'HTMLDetailsElement',
'HTMLDialogElement',
'HTMLDirectoryElement',
'HTMLDivElement',
'HTMLDListElement',
'HTMLDocument',
'HTMLElement',
'HTMLEmbedElement',
'HTMLFieldSetElement',
'HTMLFontElement',
'HTMLFormControlsCollection',
'HTMLFormElement',
'HTMLFrameElement',
'HTMLFrameSetElement',
'HTMLHeadElement',
'HTMLHeadingElement',
'HTMLHRElement',
'HTMLHtmlElement',
'HTMLIFrameElement',
'HTMLImageElement',
'HTMLInputElement',
'HTMLLabelElement',
'HTMLLegendElement',
'HTMLLIElement',
'HTMLLinkElement',
'HTMLMapElement',
'HTMLMarqueeElement',
'HTMLMediaElement',
'HTMLMenuElement',
'HTMLMetaElement',
'HTMLMeterElement',
'HTMLModElement',
'HTMLObjectElement',
'HTMLOListElement',
'HTMLOptGroupElement',
'HTMLOptionElement',
'HTMLOptionsCollection',
'HTMLOutputElement',
'HTMLParagraphElement',
'HTMLParamElement',
'HTMLPictureElement',
'HTMLPreElement',
'HTMLProgressElement',
'HTMLQuoteElement',
'HTMLScriptElement',
'HTMLSelectElement',
'HTMLShadowElement',
'HTMLSlotElement',
'HTMLSourceElement',
'HTMLSpanElement',
'HTMLStyleElement',
'HTMLTableCaptionElement',
'HTMLTableCellElement',
'HTMLTableColElement',
'HTMLTableElement',
'HTMLTableRowElement',
'HTMLTableSectionElement',
'HTMLTemplateElement',
'HTMLTextAreaElement',
'HTMLTimeElement',
'HTMLTitleElement',
'HTMLTrackElement',
'HTMLUListElement',
'HTMLUnknownElement',
'HTMLVideoElement',
'IDBCursor',
'IDBCursorWithValue',
'IDBDatabase',
'IDBFactory',
'IDBIndex',
'IDBKeyRange',
'IDBObjectStore',
'IDBOpenDBRequest',
'IDBRequest',
'IDBTransaction',
'IDBVersionChangeEvent',
'IdleDeadline',
'IIRFilterNode',
'Image',
'ImageBitmap',
'ImageBitmapRenderingContext',
'ImageCapture',
'ImageData',
'indexedDB',
'Infinity', 'Infinity',
'InternalError', 'innerHeight',
'innerWidth',
'InputEvent',
'Int16Array',
'Int32Array',
'Int8Array',
'IntersectionObserver',
'IntersectionObserverEntry',
'Intl', 'Intl',
'isFinite', 'isFinite',
'isNaN', 'isNaN',
'isPrototypeOf',
'isSecureContext',
'JSON', 'JSON',
'KeyboardEvent',
'KeyframeEffect',
'length',
'localStorage', 'localStorage',
'location', 'location',
'Location',
'locationbar',
'Map', 'Map',
'matchMedia',
'Math', 'Math',
'MediaDeviceInfo',
'MediaDevices',
'MediaElementAudioSourceNode',
'MediaEncryptedEvent',
'MediaError',
'MediaKeyMessageEvent',
'MediaKeySession',
'MediaKeyStatusMap',
'MediaKeySystemAccess',
'MediaList',
'MediaQueryList',
'MediaQueryListEvent',
'MediaRecorder',
'MediaSettingsRange',
'MediaSource',
'MediaStream',
'MediaStreamAudioDestinationNode',
'MediaStreamAudioSourceNode',
'MediaStreamEvent',
'MediaStreamTrack',
'MediaStreamTrackEvent',
'menubar',
'MessageChannel',
'MessageEvent',
'MessagePort',
'MIDIAccess',
'MIDIConnectionEvent',
'MIDIInput',
'MIDIInputMap',
'MIDIMessageEvent',
'MIDIOutput',
'MIDIOutputMap',
'MIDIPort',
'MimeType',
'MimeTypeArray',
'MouseEvent',
'moveBy',
'moveTo',
'MutationEvent',
'MutationObserver',
'MutationRecord',
'name',
'NamedNodeMap',
'NaN', 'NaN',
'NavigationPreloadManager',
'navigator', 'navigator',
'Navigator',
'NetworkInformation',
'Node',
'NodeFilter',
'NodeIterator',
'NodeList',
'Notification',
'Number', 'Number',
'Object', 'Object',
'OfflineAudioCompletionEvent',
'OfflineAudioContext',
'offscreenBuffering',
'OffscreenCanvas',
'open',
'openDatabase',
'Option',
'origin',
'OscillatorNode',
'outerHeight',
'outerWidth',
'PageTransitionEvent',
'pageXOffset',
'pageYOffset',
'PannerNode',
'parent',
'parseFloat', 'parseFloat',
'parseInt', 'parseInt',
'process', 'Path2D',
'PaymentAddress',
'PaymentRequest',
'PaymentRequestUpdateEvent',
'PaymentResponse',
'performance',
'Performance',
'PerformanceEntry',
'PerformanceLongTaskTiming',
'PerformanceMark',
'PerformanceMeasure',
'PerformanceNavigation',
'PerformanceNavigationTiming',
'PerformanceObserver',
'PerformanceObserverEntryList',
'PerformancePaintTiming',
'PerformanceResourceTiming',
'PerformanceTiming',
'PeriodicWave',
'Permissions',
'PermissionStatus',
'personalbar',
'PhotoCapabilities',
'Plugin',
'PluginArray',
'PointerEvent',
'PopStateEvent',
'postMessage',
'Presentation',
'PresentationAvailability',
'PresentationConnection',
'PresentationConnectionAvailableEvent',
'PresentationConnectionCloseEvent',
'PresentationConnectionList',
'PresentationReceiver',
'PresentationRequest',
'print',
'ProcessingInstruction',
'ProgressEvent',
'Promise', 'Promise',
'PromiseRejectionEvent',
'prompt', 'prompt',
'propertyIsEnumerable',
'Proxy',
'PushManager',
'PushSubscription',
'PushSubscriptionOptions',
'queueMicrotask',
'RadioNodeList',
'Range',
'RangeError', 'RangeError',
'ReadableStream',
'ReferenceError', 'ReferenceError',
'Reflect',
'RegExp', 'RegExp',
'RemotePlayback',
'removeEventListener',
'Request',
'requestAnimationFrame',
'requestIdleCallback',
'resizeBy',
'ResizeObserver',
'ResizeObserverEntry',
'resizeTo',
'Response',
'RTCCertificate',
'RTCDataChannel',
'RTCDataChannelEvent',
'RTCDtlsTransport',
'RTCIceCandidate',
'RTCIceTransport',
'RTCPeerConnection',
'RTCPeerConnectionIceEvent',
'RTCRtpReceiver',
'RTCRtpSender',
'RTCSctpTransport',
'RTCSessionDescription',
'RTCStatsReport',
'RTCTrackEvent',
'screen',
'Screen',
'screenLeft',
'ScreenOrientation',
'screenTop',
'screenX',
'screenY',
'ScriptProcessorNode',
'scroll',
'scrollbars',
'scrollBy',
'scrollTo',
'scrollX',
'scrollY',
'SecurityPolicyViolationEvent',
'Selection',
'self',
'ServiceWorker',
'ServiceWorkerContainer',
'ServiceWorkerRegistration',
'sessionStorage', 'sessionStorage',
'Set', 'Set',
'setInterval', 'setInterval',
'setTimeout', 'setTimeout',
'ShadowRoot',
'SharedArrayBuffer',
'SharedWorker',
'SourceBuffer',
'SourceBufferList',
'speechSynthesis',
'SpeechSynthesisEvent',
'SpeechSynthesisUtterance',
'StaticRange',
'status',
'statusbar',
'StereoPannerNode',
'stop',
'Storage',
'StorageEvent',
'StorageManager',
'String', 'String',
'styleMedia',
'StyleSheet',
'StyleSheetList',
'SubtleCrypto',
'SVGAElement',
'SVGAngle',
'SVGAnimatedAngle',
'SVGAnimatedBoolean',
'SVGAnimatedEnumeration',
'SVGAnimatedInteger',
'SVGAnimatedLength',
'SVGAnimatedLengthList',
'SVGAnimatedNumber',
'SVGAnimatedNumberList',
'SVGAnimatedPreserveAspectRatio',
'SVGAnimatedRect',
'SVGAnimatedString',
'SVGAnimatedTransformList',
'SVGAnimateElement',
'SVGAnimateMotionElement',
'SVGAnimateTransformElement',
'SVGAnimationElement',
'SVGCircleElement',
'SVGClipPathElement',
'SVGComponentTransferFunctionElement',
'SVGDefsElement',
'SVGDescElement',
'SVGDiscardElement',
'SVGElement',
'SVGEllipseElement',
'SVGFEBlendElement',
'SVGFEColorMatrixElement',
'SVGFEComponentTransferElement',
'SVGFECompositeElement',
'SVGFEConvolveMatrixElement',
'SVGFEDiffuseLightingElement',
'SVGFEDisplacementMapElement',
'SVGFEDistantLightElement',
'SVGFEDropShadowElement',
'SVGFEFloodElement',
'SVGFEFuncAElement',
'SVGFEFuncBElement',
'SVGFEFuncGElement',
'SVGFEFuncRElement',
'SVGFEGaussianBlurElement',
'SVGFEImageElement',
'SVGFEMergeElement',
'SVGFEMergeNodeElement',
'SVGFEMorphologyElement',
'SVGFEOffsetElement',
'SVGFEPointLightElement',
'SVGFESpecularLightingElement',
'SVGFESpotLightElement',
'SVGFETileElement',
'SVGFETurbulenceElement',
'SVGFilterElement',
'SVGForeignObjectElement',
'SVGGElement',
'SVGGeometryElement',
'SVGGradientElement',
'SVGGraphicsElement',
'SVGImageElement',
'SVGLength',
'SVGLengthList',
'SVGLinearGradientElement',
'SVGLineElement',
'SVGMarkerElement',
'SVGMaskElement',
'SVGMatrix',
'SVGMetadataElement',
'SVGMPathElement',
'SVGNumber',
'SVGNumberList',
'SVGPathElement',
'SVGPatternElement',
'SVGPoint',
'SVGPointList',
'SVGPolygonElement',
'SVGPolylineElement',
'SVGPreserveAspectRatio',
'SVGRadialGradientElement',
'SVGRect',
'SVGRectElement',
'SVGScriptElement',
'SVGSetElement',
'SVGStopElement',
'SVGStringList',
'SVGStyleElement',
'SVGSVGElement',
'SVGSwitchElement',
'SVGSymbolElement',
'SVGTextContentElement',
'SVGTextElement',
'SVGTextPathElement',
'SVGTextPositioningElement',
'SVGTitleElement',
'SVGTransform',
'SVGTransformList',
'SVGTSpanElement',
'SVGUnitTypes',
'SVGUseElement',
'SVGViewElement',
'Symbol',
'SyntaxError', 'SyntaxError',
'TaskAttributionTiming',
'Text',
'TextDecoder',
'TextEncoder',
'TextEvent',
'TextMetrics',
'TextTrack',
'TextTrackCue',
'TextTrackCueList',
'TextTrackList',
'TimeRanges',
'toLocaleString',
'toolbar',
'top',
'toString',
'Touch',
'TouchEvent',
'TouchList',
'TrackEvent',
'TransitionEvent',
'TreeWalker',
'TypeError', 'TypeError',
'undefined', 'UIEvent',
'Uint16Array',
'Uint32Array',
'Uint8Array',
'Uint8ClampedArray',
'unescape',
'URIError', 'URIError',
'URL', 'URL',
'URLSearchParams',
'ValidityState',
'valueOf',
'visualViewport',
'VisualViewport',
'VTTCue',
'WaveShaperNode',
'WeakMap',
'WeakSet',
'WebAssembly',
'WebGL2RenderingContext',
'WebGLActiveInfo',
'WebGLBuffer',
'WebGLContextEvent',
'WebGLFramebuffer',
'WebGLProgram',
'WebGLQuery',
'WebGLRenderbuffer',
'WebGLRenderingContext',
'WebGLSampler',
'WebGLShader',
'WebGLShaderPrecisionFormat',
'WebGLSync',
'WebGLTexture',
'WebGLTransformFeedback',
'WebGLUniformLocation',
'WebGLVertexArrayObject',
'WebSocket',
'WheelEvent',
'window', 'window',
'Window',
'Worker',
'WritableStream',
'XMLDocument',
'XMLHttpRequest',
'XMLHttpRequestEventTarget',
'XMLHttpRequestUpload',
'XMLSerializer',
'XPathEvaluator',
'XPathExpression',
'XPathResult',
'XSLTProcessor',
]); ]);
export const reserved = new Set([ export const reserved = new Set([
'arguments',
'await', 'await',
'break', 'break',
'case', 'case',
@ -72,10 +675,8 @@ export const reserved = new Set([
'do', 'do',
'else', 'else',
'enum', 'enum',
'eval',
'export', 'export',
'extends', 'extends',
'false',
'finally', 'finally',
'for', 'for',
'function', 'function',
@ -87,7 +688,6 @@ export const reserved = new Set([
'interface', 'interface',
'let', 'let',
'new', 'new',
'null',
'package', 'package',
'private', 'private',
'protected', 'protected',
@ -98,7 +698,6 @@ export const reserved = new Set([
'switch', 'switch',
'this', 'this',
'throw', 'throw',
'true',
'try', 'try',
'typeof', 'typeof',
'var', 'var',

@ -1,8 +1,9 @@
import { noop } from '../internal/utils';
export const is_browser = typeof window !== 'undefined'; export const is_browser = typeof window !== 'undefined';
export const is_iframe = is_browser && window.self !== window.top; export const is_iframe = /*#__PURE__*/ is_browser && window.self !== window.top;
export const is_cors = export const is_cors =
is_iframe && is_iframe &&
(() => { /*#__PURE__*/ (() => {
try { try {
if (window.parent) void window.parent.document; if (window.parent) void window.parent.document;
return false; return false;
@ -12,3 +13,19 @@ export const is_cors =
})(); })();
export const has_Symbol = typeof Symbol === 'function'; export const has_Symbol = typeof Symbol === 'function';
export const globals = is_browser ? window : typeof globalThis !== 'undefined' ? globalThis : global; export const globals = is_browser ? window : typeof globalThis !== 'undefined' ? globalThis : global;
export const resolved_promise = Promise.resolve();
export let now = /*#__PURE__*/ is_browser ? performance.now.bind(performance) : Date.now.bind(Date);
export let raf = /*#__PURE__*/ is_browser ? requestAnimationFrame : noop;
export let framerate = 1000 / 60;
raf((t1) => {
raf((d) => {
const f24 = 1000 / 24,
f144 = 1000 / 144;
framerate = (d = d - t1) > f144 ? f144 : d < f24 ? f24 : d;
});
});
/* tests only */
export const test$set_now = (fn) => void (now = fn);
export const test$set_raf = (fn) => void (raf = fn);

@ -59,7 +59,7 @@ export function destroy_component({ $$ }, detaching: 0 | 1) {
if (null === $$.fragment) return; if (null === $$.fragment) return;
for (let i = 0, { on_destroy } = $$; i < on_destroy.length; i++) on_destroy[i](); for (let i = 0, { on_destroy } = $$; i < on_destroy.length; i++) on_destroy[i]();
if ($$.fragment) $$.fragment.d(detaching); if (false !== $$.fragment) $$.fragment.d(detaching);
// TODO null out other refs, including component.$$ // TODO null out other refs, including component.$$
// (need to preserve final state?) // (need to preserve final state?)

@ -9,31 +9,27 @@ export interface AnimationConfig {
tick?: (t: number, u?: number) => void; tick?: (t: number, u?: number) => void;
} }
//todo: documentation says it is DOMRect, but in IE it would be ClientRect type AnimationFn = (node: Element, { from, to }: { from: DOMRect; to: DOMRect }, params: any) => AnimationConfig;
type PositionRect = DOMRect | ClientRect;
type AnimationFn = ( export function run_animation(node: HTMLElement, from: DOMRect, fn: AnimationFn, params) {
node: Element,
{ from, to }: { from: PositionRect; to: PositionRect },
params: any
) => AnimationConfig;
export function run_animation(node: HTMLElement, from: PositionRect, fn: AnimationFn, params) {
if (!from) return noop; if (!from) return noop;
const to = node.getBoundingClientRect(); return run_transition(
if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) return noop; node,
return run_transition(node, (node, params) => fn(node, { from, to }, params), true, params); (node, params) => fn(node, { from, to: node.getBoundingClientRect() }, params),
true,
params
);
} }
export function fix_position(node: HTMLElement) { export function fix_position(node: HTMLElement, { left, top }: DOMRect) {
const { position, width, height } = getComputedStyle(node); const { position, width, height, transform } = getComputedStyle(node);
if (position === 'absolute' || position === 'fixed') return noop; if (position === 'absolute' || position === 'fixed') return noop;
const current_position = node.getBoundingClientRect();
const { position: og_position, width: og_width, height: og_height } = node.style; const { position: og_position, width: og_width, height: og_height } = node.style;
node.style.position = 'absolute'; node.style.position = 'absolute';
node.style.width = width; node.style.width = width;
node.style.height = height; node.style.height = height;
add_transform(node, current_position); const b = node.getBoundingClientRect();
node.style.transform = `${transform === 'none' ? '' : transform} translate(${left - b.left}px, ${top - b.top}px)`;
return () => { return () => {
node.style.position = og_position; node.style.position = og_position;
node.style.width = og_width; node.style.width = og_width;
@ -42,7 +38,7 @@ export function fix_position(node: HTMLElement) {
}; };
} }
export function add_transform(node: HTMLElement, a: PositionRect) { export function add_transform(node: HTMLElement, a: DOMRect) {
const b = node.getBoundingClientRect(); const b = node.getBoundingClientRect();
if (a.left !== b.left || a.top !== b.top) { if (a.left !== b.left || a.top !== b.top) {
const style = getComputedStyle(node); const style = getComputedStyle(node);

@ -1,5 +1,5 @@
import { custom_event, append, insert, detach, listen, attr } from './dom'; import { custom_event, append, insert, detach, listen, attr } from './dom';
import { now } from './environment'; import { now } from 'svelte/environment';
let inited; let inited;
export function add_location_dev$legacy(element, file, line, column, char) { export function add_location_dev$legacy(element, file, line, column, char) {
element.__svelte_meta = { element.__svelte_meta = {

@ -1,5 +1,5 @@
import { SvelteComponent } from './Component'; import { SvelteComponent } from './Component';
import { now, has_Symbol } from './environment'; import { now, has_Symbol } from 'svelte/environment';
import { dev$assert } from './dev.tools'; import { dev$assert } from './dev.tools';
export const dev$is_array_like = (arg) => export const dev$is_array_like = (arg) =>

@ -1,5 +1,5 @@
import { dev$element, dev$block } from './dev.tools'; import { dev$element, dev$block } from './dev.tools';
import { is_client, is_cors } from './environment'; import { is_cors } from 'svelte/environment';
export function append(target: Node, node: Node) { export function append(target: Node, node: Node) {
dev$element(node, `onMount`, { target }); dev$element(node, `onMount`, { target });
@ -341,18 +341,3 @@ export class HtmlTag {
this.n.forEach(detach); this.n.forEach(detach);
} }
} }
export const hasOwnProperty = Object.prototype.hasOwnProperty;
const nodeProto = Node.prototype;
export const insertBefore = nodeProto.insertBefore;
export const removeChild = nodeProto.removeChild;
export const replaceChild = nodeProto.replaceChild;
export const cloneNode = nodeProto.cloneNode;
const elementProto = Element.prototype;
export const setAttribute = elementProto.setAttribute;
export const setAttributeNS = elementProto.setAttributeNS;
export const removeAttribute = elementProto.removeAttribute;
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
export const setClassName = getOwnPropertyDescriptor(elementProto, 'className').set;
export const getStyle = getOwnPropertyDescriptor(HTMLElement.prototype, 'style').get;
export const svg_getStyle = getOwnPropertyDescriptor(SVGElement.prototype, 'style').get;

@ -1,30 +0,0 @@
import { noop } from './utils';
export const resolved_promise = Promise.resolve();
export const is_client = typeof window !== 'undefined';
export const is_iframe = !is_client && window.self !== window.top;
export const is_cors =
is_iframe &&
(() => {
try {
if (window.parent) void window.parent.document;
return false;
} catch (error) {
return true;
}
})();
export const globals = ((is_client
? window
: typeof globalThis !== 'undefined'
? globalThis
: global) as unknown) as typeof globalThis;
export const has_Symbol = typeof Symbol === 'function';
export let now = is_client ? performance.now.bind(performance) : Date.now.bind(Date);
export let raf = is_client ? requestAnimationFrame : noop;
/* tests only */
export const set_now = (fn) => void (now = fn);
export const set_raf = (fn) => void (raf = fn);

@ -5,7 +5,6 @@ export * from './dev.legacy';
export * from './dev.utils'; export * from './dev.utils';
export * from './dev.tools'; export * from './dev.tools';
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';
@ -16,3 +15,6 @@ export * from './stores';
// export * from './style_manager' // export * from './style_manager'
export * from './transitions'; export * from './transitions';
export * from './utils'; export * from './utils';
// todo; create_module.ts line 24; allow compiler to import non internal
export * from '../environment/index';

@ -1,5 +1,5 @@
import { transition_in } from './transitions'; import { transition_in } from './transitions';
export function update_keyed_each( export const update_keyed_each = (
old_blocks, old_blocks,
dirty, dirty,
ctx, ctx,
@ -12,7 +12,7 @@ export function update_keyed_each(
next, next,
get_context, get_context,
transition_out? transition_out?
) { ) => {
let o = old_blocks.length; let o = old_blocks.length;
let n = list.length; let n = list.length;
@ -54,7 +54,7 @@ export function update_keyed_each(
}; };
const destroy = (block) => { const destroy = (block) => {
if (state & 2) block.f(); if (state & 2) block.f();
if (state & 4) transition_out(block, () => lookup.delete(block.key)); if (state & 4) transition_out(block, lookup.delete.bind(lookup, block.key));
else block.d(1), lookup.delete(block.key); else block.d(1), lookup.delete(block.key);
}; };
@ -94,7 +94,7 @@ export function update_keyed_each(
while (n) insert(new_blocks[n - 1]); while (n) insert(new_blocks[n - 1]);
return new_blocks; return new_blocks;
} };
export function validate_each_keys(ctx, list, get_context, get_key) { export function validate_each_keys(ctx, list, get_context, get_key) {
const keys = new Set(); const keys = new Set();

@ -1,5 +1,4 @@
import { now, raf } from './environment'; import { now, raf, framerate } from 'svelte/environment';
import { calc_framerate, FRAME_RATE } from './style_manager';
import { noop } from './utils'; import { noop } from './utils';
type TaskCallback = (t: number) => boolean; type TaskCallback = (t: number) => boolean;
type TaskCanceller = () => void; type TaskCanceller = () => void;
@ -90,7 +89,7 @@ export const onEachFrame = (
on_stop?, on_stop?,
max_skipped_frames = 4 max_skipped_frames = 4
): TaskCanceller => { ): TaskCanceller => {
max_skipped_frames *= FRAME_RATE || calc_framerate(); max_skipped_frames *= framerate;
let lastTime = now(); let lastTime = now();
let running = true; let running = true;
const cancel = (t) => (on_stop && on_stop(t), false); const cancel = (t) => (on_stop && on_stop(t), false);

@ -1,5 +1,5 @@
import { set_current_component } from './lifecycle'; import { set_current_component } from './lifecycle';
import { resolved_promise } from './environment'; import { resolved_promise } from 'svelte/environment';
import { T$$ } from './Component'; import { T$$ } from './Component';
let update_scheduled = false; let update_scheduled = false;
@ -88,15 +88,15 @@ export const flush = () => {
update_scheduled = false; update_scheduled = false;
// measurement callbacks for animations // measurement callbacks for animations
for (i = 0; i < measure_callbacks.length; i++) { for (i = 0, j = flush_callbacks.length; i < measure_callbacks.length; i++) {
flush_callbacks.push(measure_callbacks[i]()); flush_callbacks[j++] = measure_callbacks[i]();
} }
measure_callbacks.length = i = 0; measure_callbacks.length = i = 0;
// apply styles // apply styles
// todo : remove every non style callback from flush_callbacks // todo : remove every non style callback from flush_callbacks
for (; i < flush_callbacks.length; i++) flush_callbacks[i](); for (; i < j; i++) flush_callbacks[i]();
flush_callbacks.length = 0; flush_callbacks.length = i = j = 0;
is_flushing = false; is_flushing = false;
}; };

@ -1,23 +1,10 @@
import { element } from './dom'; import { element } from './dom';
import { raf } from './environment'; import { framerate } from 'svelte/environment';
const enum SVELTE { enum SVELTE {
RULE = `__svelte_`, RULE = `__svelte_`,
STYLESHEET = `__svelte_stylesheet`, STYLESHEET = `__svelte_stylesheet`,
RULESET = `__svelte_rules`, RULESET = `__svelte_rules`,
} }
export let FRAME_RATE;
export function calc_framerate() {
const f24 = 1000 / 24,
f60 = 1000 / 60,
f144 = 1000 / 144;
raf((t1) => {
raf((d) => {
FRAME_RATE = (d = d - t1) > f144 ? f144 : d < f24 ? f24 : d;
});
});
return (FRAME_RATE = f60);
}
interface ExtendedDoc extends Document { interface ExtendedDoc extends Document {
[SVELTE.STYLESHEET]: CSSStyleSheet; [SVELTE.STYLESHEET]: CSSStyleSheet;
[SVELTE.RULESET]: Set<string>; [SVELTE.RULESET]: Set<string>;
@ -36,8 +23,9 @@ function add_rule(node): [CSSStyleSheet, Set<string>] {
} }
return [ownerDocument[SVELTE.STYLESHEET], ownerDocument[SVELTE.RULESET]]; return [ownerDocument[SVELTE.STYLESHEET], ownerDocument[SVELTE.RULESET]];
} }
// https://github.com/darkskyapp/string-hash/blob/master/index.js
function hash(str: string) { function hash(str: string) {
// darkskyapp/string-hash
let hash = 5381; let hash = 5381;
let i = str.length; let i = str.length;
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i); while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
@ -50,21 +38,23 @@ const gen = (step, css) => {
const name = SVELTE.RULE + hash(rule); const name = SVELTE.RULE + hash(rule);
return [name, `@keyframes ${name} ${rule}`]; return [name, `@keyframes ${name} ${rule}`];
}; };
export function animate_css(css: (t: number) => string, node: HTMLElement, duration: number, delay = 0) { function animate(this: HTMLElement, css: (t: number) => string, duration: number, delay = 0) {
const [name, rule] = gen(Math.max(1 / 1000, (FRAME_RATE || calc_framerate()) / duration), css); const [name, rule] = gen(Math.max(1 / 1000, framerate / duration), css);
const [stylesheet, rules] = add_rule(node); const [stylesheet, rules] = add_rule(this);
if (!rules.has(name)) { if (!rules.has(name)) {
rules.add(name); rules.add(name);
stylesheet.insertRule(rule, stylesheet.cssRules.length); stylesheet.insertRule(rule, stylesheet.cssRules.length);
} }
const previous = node.style.animation; const previous = this.style.animation;
node.style.animation = this.style.animation = `${
(previous ? previous + ', ' : '') + `${duration}ms linear ${delay}ms 1 normal both running ${name}`; previous ? `${previous}, ` : ''
} ${duration}ms linear ${delay}ms 1 normal both running ${name}`;
running_animations++; running_animations++;
return () => { return () => {
const prev = (node.style.animation || '').split(', '); const prev = (this.style.animation || '').split(', ');
const next = prev.filter((anim) => !anim.includes(name)); const next = prev.filter((anim) => !anim.includes(name));
if (prev.length !== next.length) node.style.animation = next.join(', '); if (prev.length !== next.length) this.style.animation = next.join(', ');
if (--running_animations) return; if (--running_animations) return;
active_documents.forEach(({ [SVELTE.STYLESHEET]: stylesheet, [SVELTE.RULESET]: ruleset }) => { active_documents.forEach(({ [SVELTE.STYLESHEET]: stylesheet, [SVELTE.RULESET]: ruleset }) => {
let i = stylesheet.cssRules.length; let i = stylesheet.cssRules.length;
@ -74,17 +64,4 @@ export function animate_css(css: (t: number) => string, node: HTMLElement, durat
active_documents.clear(); active_documents.clear();
}; };
} }
export function delete_rule(node: HTMLElement, name?: string) { export const animate_css = Function.prototype.call.bind(animate);
const previous = (node.style.animation || '').split(', ');
const next = previous.filter(
name
? (anim) => anim.indexOf(name) < 0 // remove specific animation
: (anim) => anim.indexOf(SVELTE.RULE) === -1 // remove all Svelte animations
);
const deleted = previous.length - next.length;
if (deleted) {
node.style.animation = next.join(', ');
running_animations -= deleted;
if (!active_documents) active_documents.clear();
}
}

@ -1,7 +1,7 @@
import { TransitionConfig } from '../transition'; import { TransitionConfig } from '../transition';
import { Fragment } from './Component'; import { Fragment } from './Component';
import { custom_event } from './dom'; import { custom_event } from './dom';
import { now } from './environment'; import { now } from 'svelte/environment';
import { setFrameTimeout, setTweenTimeout } from './loop'; import { setFrameTimeout, setTweenTimeout } from './loop';
import { add_measure_callback } from './scheduler'; import { add_measure_callback } from './scheduler';
import { animate_css } from './style_manager'; import { animate_css } from './style_manager';
@ -99,17 +99,17 @@ export const run_transition = (
const solver = strategy === 'reverse' ? reversed : mirrored; const solver = strategy === 'reverse' ? reversed : mirrored;
const runner = (fn) => solver(fn, is_intro, easing, elapsed_ratio, 1); const runner = (fn) => solver(fn, is_intro, easing, elapsed_ratio, 1);
if (solver === mirrored) { if (solver === reversed) {
delay -= elapsed_duration;
} else if (solver === reversed) {
duration -= elapsed_duration; duration -= elapsed_duration;
} else if (solver === mirrored) {
delay -= elapsed_duration;
} }
end_time = (start_time = now() + delay) + duration; end_time = (start_time = now() + delay) + duration;
dispatch_end = startStopDispatcher(node, is_intro); dispatch_end = startStopDispatcher(node, is_intro);
if (css) cancel_css = animate_css(runner(css), node, duration, delay); if (css) cancel_css = animate_css(node, runner(css), duration, delay);
cancel_raf = tick ? setTweenTimeout(stop, end_time, runner(tick), duration) : setFrameTimeout(stop, end_time); cancel_raf = tick ? setTweenTimeout(stop, end_time, runner(tick), duration) : setFrameTimeout(stop, end_time);
}; };

@ -153,22 +153,30 @@ export function crossfade({
const dw = from.width / to.width; const dw = from.width / to.width;
const dh = from.height / to.height; const dh = from.height / to.height;
const { transform, opacity } = getComputedStyle(to_node); const { transform, opacity } = getComputedStyle(to_node);
const op = +opacity;
const prev = transform === 'none' ? '' : transform; const prev = transform === 'none' ? '' : transform;
return { return {
delay, delay,
easing, easing,
duration: run_duration(duration, Math.sqrt(dx * dx + dy * dy)), duration: run_duration(duration, Math.sqrt(dx * dx + dy * dy)),
css: (t, u) => ` css: (t, u) => `
opacity: ${t * +opacity}; opacity: ${t * op};
transform-origin: top left; transform-origin: top left;
transform: ${prev} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${t + (1 - t) * dh}); transform: ${prev} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${t + (1 - t) * dh});
`, `,
} as TransitionConfig; } as TransitionConfig;
} }
function transition(a: ElementMap, b: ElementMap, is_intro: boolean) { const transition = (a: ElementMap, b: ElementMap, is_intro: boolean) => (
return (node: Element, params: MarkedCrossFadeConfig) => { node: Element,
const key = params.key; params: MarkedCrossFadeConfig
a.set(key, node); ) => {
const key = params.key;
a.set(key, node);
if (b.has(key)) {
const from_node = b.get(key);
b.delete(key);
return crossfade(from_node, node, params);
} else {
return () => { return () => {
if (b.has(key)) { if (b.has(key)) {
const from_node = b.get(key); const from_node = b.get(key);
@ -179,8 +187,8 @@ export function crossfade({
return fallback && fallback(node, params, is_intro); return fallback && fallback(node, params, is_intro);
} }
}; };
}; }
} };
return [transition(to_send, to_receive, false), transition(to_receive, to_send, true)]; return [transition(to_send, to_receive, false), transition(to_receive, to_send, true)];
} }

@ -6,17 +6,18 @@
// target node v8+ (https://node.green/) // target node v8+ (https://node.green/)
// the only missing feature is Array.prototype.values // the only missing feature is Array.prototype.values
"lib": ["es2017"], "lib": ["ESNext"],
"target": "es2017", "target": "ESNext",
"declaration": true, "declaration": true,
"declarationDir": "types", "declarationDir": "types",
"strictBindCallApply": true,
"noEmitOnError": true, "noEmitOnError": true,
"noErrorTruncation": true, "noErrorTruncation": true,
// rollup takes care of these // rollup takes care of these
"module": "esnext", "module": "ESNext",
"moduleResolution": "node", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,

Loading…
Cancel
Save