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

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

32
.gitignore vendored

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

@ -2,11 +2,13 @@
Object.defineProperty(exports, '__esModule', { value: true });
function noop() {}
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 =
is_iframe &&
(() => {
/*#__PURE__*/ (() => {
try {
if (window.parent) void window.parent.document;
return false;
@ -16,9 +18,28 @@ const is_cors =
})();
const has_Symbol = typeof Symbol === 'function';
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.has_Symbol = has_Symbol;
exports.is_browser = is_browser;
exports.is_cors = is_cors;
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_iframe = is_browser && window.self !== window.top;
const is_iframe = /*#__PURE__*/ is_browser && window.self !== window.top;
const is_cors =
is_iframe &&
(() => {
/*#__PURE__*/ (() => {
try {
if (window.parent) void window.parent.document;
return false;
@ -12,5 +14,21 @@ const is_cors =
})();
const has_Symbol = typeof Symbol === 'function';
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",
"main": "index",
"files": [
"animate",
"dev",
"easing",
"environment",
"internal",
"interpolate",
"motion",
"store",
"transition",
"types",
"compiler.*",
"register.js",
"index.*",
"internal",
"store",
"animate",
"transition",
"easing",
"motion",
"svelte",
"README.md"
],

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

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

@ -181,7 +181,11 @@ export default class Component {
injected: true,
referenced: true,
});
} else if (name[0] === '$') {
} else {
if (!name) {
console.log(name);
}
if (name[0] === '$') {
this.add_var({
name,
injected: true,
@ -201,6 +205,7 @@ export default class Component {
this.used_names.add(name);
}
}
}
alias(name: string) {
if (!this.aliases.has(name)) {

@ -36,14 +36,14 @@ export default function create_module(
throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`);
}
function edit_source(source, sveltePath) {
return source === 'svelte' || source.startsWith('svelte/') ? source.replace('svelte', sveltePath) : source;
}
const edit_source = (source, sveltePath) => (/^svelte\/?/.test(source) ? source.replace('svelte', sveltePath) : source);
function get_internal_globals(
globals: 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 (
globals.length > 0 && {
type: 'VariableDeclaration',

@ -68,7 +68,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
}
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 warnings = [];

@ -30,7 +30,7 @@ export default class Expression {
scope: Scope;
scope_map: WeakMap<Node, Scope>;
declarations: Array<(Node | Node[])> = [];
declarations: Array<Node | Node[]> = [];
uses_context = false;
manipulated: Node;
@ -40,8 +40,8 @@ export default class Expression {
// TODO revert to direct property access in prod?
Object.defineProperties(this, {
component: {
value: component
}
value: component,
},
});
this.node = info;
@ -79,12 +79,13 @@ export default class Expression {
if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
component.error(node, {
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 (!function_expression) { // TODO should this be `!lazy` ?
if (!function_expression) {
// TODO should this be `!lazy` ?
contextual_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;
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 {
if (!lazy) {
@ -118,9 +119,7 @@ export default class Expression {
if (function_expression) {
if (node.type === 'AssignmentExpression') {
deep = node.left.type === 'MemberExpression';
names = deep
? [get_object(node.left).name]
: extract_names(node.left);
names = deep ? [get_object(node.left).name] : extract_names(node.left);
} else if (node.type === 'UpdateExpression') {
const { name } = get_object(node.argument);
names = [name];
@ -128,9 +127,10 @@ export default class Expression {
}
if (names) {
names.forEach(name => {
names.forEach((name) => {
if (!name) return;
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);
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
});
@ -152,12 +152,12 @@ export default class Expression {
if (node === function_expression) {
function_expression = null;
}
}
},
});
}
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 (is_reserved_keyword(name)) return true;
@ -172,13 +172,7 @@ export default class Expression {
// multiple times
if (this.manipulated) return this.manipulated;
const {
component,
declarations,
scope_map: map,
template_scope,
owner
} = this;
const { component, declarations, scope_map: map, template_scope, owner } = this;
let scope = this.scope;
let function_expression;
@ -206,7 +200,7 @@ export default class Expression {
if (template_scope.names.has(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);
});
} else {
@ -238,9 +232,7 @@ export default class Expression {
if (map.has(node)) scope = scope.parent;
if (node === function_expression) {
const id = component.get_unique_name(
sanitize(get_function_name(node, owner))
);
const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
const declaration = b`const ${id} = ${node}`;
@ -254,28 +246,24 @@ export default class Expression {
name: id.name,
internal: 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
component.partly_hoisted.push(declaration);
block.renderer.add_to_context(id.name);
this.replace(block.renderer.reference(id));
}
else {
} else {
// we need a combo block/init recipe
const deps = Array.from(contextual_dependencies);
(node as FunctionExpression).params = [
...deps.map(name => ({ type: 'Identifier', name } as Identifier)),
...(node as FunctionExpression).params
...deps.map((name) => ({ type: 'Identifier', name } as Identifier)),
...(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);
@ -318,10 +306,10 @@ export default class Expression {
const names = new Set(extract_names(assignee));
const traced: Set<string> = new Set();
names.forEach(name => {
names.forEach((name) => {
const dependencies = template_scope.dependencies_for_name.get(name);
if (dependencies) {
dependencies.forEach(name => traced.add(name));
dependencies.forEach((name) => traced.add(name));
} else {
traced.add(name);
}
@ -329,12 +317,12 @@ export default class Expression {
this.replace(invalidate(block.renderer, scope, node, traced));
}
}
},
});
if (declarations.length > 0) {
block.maintain_context = true;
declarations.forEach(declaration => {
declarations.forEach((declaration) => {
block.chunks.init.push(declaration);
});
}

@ -230,6 +230,8 @@ export default class Block {
get_contents(key?: any) {
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) {
this.add_variable({ type: 'Identifier', name: '#current' });
@ -420,17 +422,17 @@ export default class Block {
}
has_content(): boolean {
return (
!!this.first ||
this.event_listeners.length > 0 ||
this.chunks.intro.length > 0 ||
this.chunks.outro.length > 0 ||
this.chunks.create.length > 0 ||
this.chunks.hydrate.length > 0 ||
this.chunks.claim.length > 0 ||
this.chunks.mount.length > 0 ||
this.chunks.update.length > 0 ||
this.chunks.destroy.length > 0 ||
return !!(
this.first ||
this.event_listeners.length ||
this.chunks.intro.length ||
this.chunks.outro.length ||
this.chunks.create.length ||
this.chunks.hydrate.length ||
this.chunks.claim.length ||
this.chunks.mount.length ||
this.chunks.update.length ||
this.chunks.destroy.length ||
this.has_animation
);
}
@ -472,13 +474,13 @@ export default class Block {
this.chunks.destroy.push(b`${dispose}();`);
} else {
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} = [
${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;
get_each_context: Identifier;
iterations: Identifier;
fixed_length: number;
data_length: string;
view_length: string;
};
context_props: Array<Node | Node[]>;
@ -92,7 +89,6 @@ export default class EachBlockWrapper extends Wrapper {
type: 'each',
// @ts-ignore todo: probably error
key: node.key as string,
bindings: new Map(block.bindings),
});
@ -103,42 +99,16 @@ export default class EachBlockWrapper extends Wrapper {
? { type: 'Identifier', name: this.node.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 = {
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`),
iterations,
// 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,
iterations: block.get_unique_name(`${this.var.name}_blocks`),
};
renderer.add_to_context(this.vars.each_block_value.name, true);
renderer.add_to_context(this.index_name.name, true);
const store =
node.expression.node.type === 'Identifier' && node.expression.node.name[0] === '$'
? 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) {
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 { component } = renderer;
@ -193,20 +164,17 @@ export default class EachBlockWrapper extends Wrapper {
);
if (this.node.has_binding)
this.context_props.push(
b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`
);
this.context_props.push(b`child_ctx[${renderer.context_lookup.get(each_block_value.name).index}] = list;`);
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;`);
const snippet = this.node.expression.manipulate(block);
block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`);
if (this.renderer.options.dev) {
block.chunks.init.push(b`@validate_each_argument(${this.vars.each_block_value});`);
block.chunks.init.push(b`let ${each_block_value} = ${snippet};`);
if (__DEV__) {
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`
function ${this.vars.get_each_context}(#ctx, list, i) {
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) {
block.chunks.intro.push(b`
for (let #i = 0; #i < ${this.vars.data_length}; #i += 1) {
@transition_in(${this.vars.iterations}[#i]);
}
`);
block.chunks.intro.push(for_loop(each_block, (item) => b`@transition_in(${item});`));
}
if (needs_anchor) {
@ -260,20 +224,18 @@ export default class EachBlockWrapper extends Wrapper {
if (this.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
block.chunks.init.push(b`
if (!${this.vars.data_length}) {
block.chunks.init.push(
b`let ${each_block_else} = null;`,
b`if (!${each_block_value}.length) {
${each_block_else} = ${this.else.block.name}(#ctx);
}
`);
}`
);
block.chunks.create.push(b`
if (${each_block_else}) {
${each_block_else}.c();
}
`);
}`);
if (this.renderer.options.hydratable) {
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});
}
`);
if (this.else.block.has_update_method) {
this.updates.push(b`
if (!${this.vars.data_length} && ${each_block_else}) {
${each_block_else}.p(#ctx, #dirty);
} else if (!${this.vars.data_length}) {
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});
} else if (${each_block_else}) {
${each_block_else}.d(1);
${each_block_else} = null;
}
`);
} 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});
}
`);
}
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});`;
this.updates.push(
$if({
if: each_block_else,
true: $if({
if: no_each_else,
true: update_else,
false: destroy_else,
}),
false: $if({
if: no_each_else,
true: create_else,
}),
})
);
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) {
block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
@ -356,104 +315,76 @@ export default class EachBlockWrapper extends Wrapper {
update_anchor_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 for_each_block = (fn) => for_loop(each_block, fn);
const get_key = block.get_unique_name('get_key');
const key_getter = block.get_unique_name('get_key');
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()`);
if (this.fragment.nodes[0].is_dom_node()) {
this.block.first = this.fragment.nodes[0].var;
} else {
this.block.first = this.block.get_unique_name('first');
this.block.add_element(this.block.first, x`@empty()`, parent_nodes && x`@empty()`, null);
}
block.chunks.init.push(b`
const ${get_key} = #ctx => ${this.node.key.manipulate(block)};
if (this.fragment.nodes[0].is_dom_node()) this.block.first = this.fragment.nodes[0].var;
else
this.block.add_element(
(this.block.first = this.block.get_unique_name('first')),
x`@empty()`,
parent_nodes && x`@empty()`,
null
);
${
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));
}
`);
const validate_each_keys =
__DEV__ && b`@validate_each_keys(#ctx, ${each_block_value}, ${each_context_getter}, ${key_getter});`;
block.chunks.create.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].c();
}
`);
const validate_each_argument = __DEV__ && b`@validate_each_argument(${each_block_value});`;
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.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`
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
}
`);
block.chunks.create.push(for_each_block((block) => b`${block}.c();`));
if (parent_nodes && this.renderer.options.hydratable)
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 destroy = this.node.has_animation
// ? this.block.has_outros
// ? `@fix_and_outro_and_destroy_block`
// : `@fix_and_destroy_block`
// : this.block.has_outros
// ? `@outro_and_destroy_block`
// : `@destroy_block`;
const has_animation = this.node.has_animation || null;
const { has_outros } = this.block;
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(
b`
const ${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}`,
this.block.group_transition_out(
(transition_out) => b`
${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1){ ${iterations}[#i].r();}`}
${
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();}`}`
)
b`const ${each_block_value} = ${snippet};`,
validate_each_keys,
validate_each_argument,
measure_animations,
this.block.group_transition_out((transition_out) => update_keyed_each(transition_out)),
has_animation && for_each_block((block) => b`${block}.a();`)
);
}
if (this.block.has_outros) {
block.chunks.outro.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
@transition_out(${iterations}[#i]);
}
`);
}
if (has_outros) block.chunks.outro.push(for_each_block((block) => b`@transition_out(${block});`));
block.chunks.destroy.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].d(${parent_node ? null : 'detaching'});
}
`);
block.chunks.destroy.push(for_each_block((block) => b`${block}.d(${parent_node ? null : 'detaching'});`));
}
render_unkeyed({
@ -473,117 +404,109 @@ export default class EachBlockWrapper extends Wrapper {
update_anchor_node: Identifier;
update_mount_node: Identifier;
}) {
const { create_each_block, iterations, fixed_length, data_length, view_length } = this.vars;
block.chunks.init.push(b`
let ${iterations} = [];
for (let #i = 0; #i < ${data_length}; #i += 1) {
${iterations}[#i] = ${create_each_block}(${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i));
}
`);
block.chunks.create.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].c();
}
`);
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 for_each_block = (fn, opts?) => for_loop(each_block, fn, opts);
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.init.push(
b`let ${each_block} = [];`,
for_loop(
each_block_value,
(_, index) =>
b`${each_block}[${index}] = ${create_each_block}(${each_context_getter}(#ctx, ${each_block_value}, ${index}));`
)
);
block.chunks.mount.push(b`
for (let #i = 0; #i < ${view_length}; #i += 1) {
${iterations}[#i].m(${initial_mount_node}, ${initial_anchor_node});
}
`);
block.chunks.create.push(for_each_block((block) => b`${block}.c();`));
if (parent_nodes && this.renderer.options.hydratable)
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) {
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
? 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};`}
`
);
const start = has_update_method ? 0 : `#old_length`;
// We declare `i` as block scoped here, as the `remove_old_blocks` code
// may rely on continuing where this iteration stopped.
const update = b`
${!this.block.has_update_method && b`const #old_length = ${this.vars.each_block_value}.length;`}
${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}
this.updates.push(b`
${!has_update_method && b`const #old_length = ${each_block_value}.length;`}
${each_block_value} = ${snippet};
${__DEV__ && b`@validate_each_argument(${each_block_value});`}
let #i;
for (#i = ${start}; #i < ${data_length}; #i += 1) {
const child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
${for_loop_body}
${for_each_block(
(block, index) => b`
const #child_ctx = ${each_context_getter}(#ctx, ${each_block_value}, ${index});
${$if({
if: (has_update_method || has_transitions) && block,
true: b`
${has_update_method && b`${block}.p(#child_ctx, #dirty);`}
${has_transitions && b`@transition_in(${block}, 1);`}
`,
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`,
}
${remove_old_blocks}
`;
this.updates.push(update);
)
)}
${each_block}.length = ${each_block_value}.length;
`);
}
if (this.block.has_outros) {
block.chunks.outro.push(b`
${iterations} = ${iterations}.filter(@_Boolean);
for (let #i = 0; #i < ${view_length}; #i += 1) {
@transition_out(${iterations}[#i]);
}
`);
${each_block} = ${each_block}.filter(@_Boolean);
${for_each_block((block) => b`@transition_out(${block})`)}`);
}
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 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) {
if (outro) {
const outro_var = block.alias(`${this.var.name}_outro`);
if (this.node.animation) {
const [unfreeze_var, rect_var, stop_animation_var, animationFn, params] = run_animation(this, block);
block.chunks.intro.push(b`
if (${outro_var}){
${outro_var}(1);
if (${unfreeze_var}) {
${unfreeze_var}(), (unfreeze = undefined);
${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${animationFn}, ${params});
}
}
`);
} else {
}
if (this.node.animation) {
const [unfreeze_var, rect_var, stop_animation_var, animationFn, params] = run_animation(this, block);
block.chunks.intro.push(b`
if (${outro_var}){
${outro_var}(1);
if (${unfreeze_var}) {
${unfreeze_var}();
${unfreeze_var} = void 0;
${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${animationFn}, ${params});
}
`);
}
}
if (!intro) return;
const [intro_var, node, transitionFn, params] = run_transition(this, block, intro, `intro`);
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};`;
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.chunks.measure.push(b`
${rect_var} = ${this.var}.getBoundingClientRect();
if(!${unfreeze_var}) ${rect_var} = ${this.var}.getBoundingClientRect();
${intro && b`if(${intro_var}) ${intro_var}();`}
`);
block.chunks.fix.push(b`
${unfreeze_var} = @fix_position(${this.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`
if (${unfreeze_var}) return
else {
${stop_animation_var}();
@add_render_callback(()=>{${stop_animation_var} = @run_animation(${this.var}, ${rect_var}, ${name_var}, ${params_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) {
@ -882,7 +880,7 @@ function run_animation(element: ElementWrapper, block: Block) {
block.alias('rect'),
block.alias('stop_animation'),
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) {
@ -890,6 +888,6 @@ function run_transition(element: ElementWrapper, block: Block, transition: Trans
/* node_intro */ block.alias(`${element.var.name}_${type}`),
/* node */ element.var,
/* 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 full_char_code_at from './full_char_code_at';
/** source : rollup */
export const globals = new Set([
'global',
'__proto__',
'AbortController',
'AbortSignal',
'addEventListener',
'alert',
'AnalyserNode',
'Animation',
'AnimationEvent',
'applicationCache',
'ApplicationCache',
'ApplicationCacheErrorEvent',
'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',
'BroadcastChannel',
'btoa',
'ByteLengthQueuingStrategy',
'Cache',
'caches',
'CacheStorage',
'cancelAnimationFrame',
'cancelIdleCallback',
'CanvasCaptureMediaStreamTrack',
'CanvasGradient',
'CanvasPattern',
'CanvasRenderingContext2D',
'ChannelMergerNode',
'ChannelSplitterNode',
'CharacterData',
'clearInterval',
'clearTimeout',
'clientInformation',
'ClipboardEvent',
'close',
'closed',
'CloseEvent',
'Comment',
'CompositionEvent',
'confirm',
'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',
'decodeURI',
'decodeURIComponent',
'defaultstatus',
'defaultStatus',
'DelayNode',
'DeviceMotionEvent',
'DeviceOrientationEvent',
'devicePixelRatio',
'dispatchEvent',
'document',
'Document',
'DocumentFragment',
'DocumentType',
'DOMError',
'DOMException',
'DOMImplementation',
'DOMMatrix',
'DOMMatrixReadOnly',
'DOMParser',
'DOMPoint',
'DOMPointReadOnly',
'DOMQuad',
'DOMRect',
'DOMRectReadOnly',
'DOMStringList',
'DOMStringMap',
'DOMTokenList',
'DragEvent',
'DynamicsCompressorNode',
'Element',
'encodeURI',
'encodeURIComponent',
'Error',
'ErrorEvent',
'escape',
'eval',
'EvalError',
'Event',
'EventSource',
'EventTarget',
'external',
'fetch',
'global',
'File',
'FileList',
'FileReader',
'find',
'Float32Array',
'Float64Array',
'focus',
'FocusEvent',
'FontFace',
'FontFaceSetLoadEvent',
'FormData',
'frames',
'Function',
'GainNode',
'Gamepad',
'GamepadButton',
'GamepadEvent',
'getComputedStyle',
'getSelection',
'globalThis',
'HashChangeEvent',
'hasOwnProperty',
'Headers',
'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',
'InternalError',
'innerHeight',
'innerWidth',
'InputEvent',
'Int16Array',
'Int32Array',
'Int8Array',
'IntersectionObserver',
'IntersectionObserverEntry',
'Intl',
'isFinite',
'isNaN',
'isPrototypeOf',
'isSecureContext',
'JSON',
'KeyboardEvent',
'KeyframeEffect',
'length',
'localStorage',
'location',
'Location',
'locationbar',
'Map',
'matchMedia',
'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',
'NavigationPreloadManager',
'navigator',
'Navigator',
'NetworkInformation',
'Node',
'NodeFilter',
'NodeIterator',
'NodeList',
'Notification',
'Number',
'Object',
'OfflineAudioCompletionEvent',
'OfflineAudioContext',
'offscreenBuffering',
'OffscreenCanvas',
'open',
'openDatabase',
'Option',
'origin',
'OscillatorNode',
'outerHeight',
'outerWidth',
'PageTransitionEvent',
'pageXOffset',
'pageYOffset',
'PannerNode',
'parent',
'parseFloat',
'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',
'PromiseRejectionEvent',
'prompt',
'propertyIsEnumerable',
'Proxy',
'PushManager',
'PushSubscription',
'PushSubscriptionOptions',
'queueMicrotask',
'RadioNodeList',
'Range',
'RangeError',
'ReadableStream',
'ReferenceError',
'Reflect',
'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',
'Set',
'setInterval',
'setTimeout',
'ShadowRoot',
'SharedArrayBuffer',
'SharedWorker',
'SourceBuffer',
'SourceBufferList',
'speechSynthesis',
'SpeechSynthesisEvent',
'SpeechSynthesisUtterance',
'StaticRange',
'status',
'statusbar',
'StereoPannerNode',
'stop',
'Storage',
'StorageEvent',
'StorageManager',
'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',
'TaskAttributionTiming',
'Text',
'TextDecoder',
'TextEncoder',
'TextEvent',
'TextMetrics',
'TextTrack',
'TextTrackCue',
'TextTrackCueList',
'TextTrackList',
'TimeRanges',
'toLocaleString',
'toolbar',
'top',
'toString',
'Touch',
'TouchEvent',
'TouchList',
'TrackEvent',
'TransitionEvent',
'TreeWalker',
'TypeError',
'undefined',
'UIEvent',
'Uint16Array',
'Uint32Array',
'Uint8Array',
'Uint8ClampedArray',
'unescape',
'URIError',
'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',
'Worker',
'WritableStream',
'XMLDocument',
'XMLHttpRequest',
'XMLHttpRequestEventTarget',
'XMLHttpRequestUpload',
'XMLSerializer',
'XPathEvaluator',
'XPathExpression',
'XPathResult',
'XSLTProcessor',
]);
export const reserved = new Set([
'arguments',
'await',
'break',
'case',
@ -72,10 +675,8 @@ export const reserved = new Set([
'do',
'else',
'enum',
'eval',
'export',
'extends',
'false',
'finally',
'for',
'function',
@ -87,7 +688,6 @@ export const reserved = new Set([
'interface',
'let',
'new',
'null',
'package',
'private',
'protected',
@ -98,7 +698,6 @@ export const reserved = new Set([
'switch',
'this',
'throw',
'true',
'try',
'typeof',
'var',

@ -1,8 +1,9 @@
import { noop } from '../internal/utils';
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 =
is_iframe &&
(() => {
/*#__PURE__*/ (() => {
try {
if (window.parent) void window.parent.document;
return false;
@ -12,3 +13,19 @@ export const is_cors =
})();
export const has_Symbol = typeof Symbol === 'function';
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;
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.$$
// (need to preserve final state?)

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

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

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

@ -1,5 +1,5 @@
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) {
dev$element(node, `onMount`, { target });
@ -341,18 +341,3 @@ export class HtmlTag {
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.tools';
export * from './dom';
export * from './environment';
export * from './keyed_each';
export * from './lifecycle';
export * from './loop';
@ -16,3 +15,6 @@ export * from './stores';
// export * from './style_manager'
export * from './transitions';
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';
export function update_keyed_each(
export const update_keyed_each = (
old_blocks,
dirty,
ctx,
@ -12,7 +12,7 @@ export function update_keyed_each(
next,
get_context,
transition_out?
) {
) => {
let o = old_blocks.length;
let n = list.length;
@ -54,7 +54,7 @@ export function update_keyed_each(
};
const destroy = (block) => {
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);
};
@ -94,7 +94,7 @@ export function update_keyed_each(
while (n) insert(new_blocks[n - 1]);
return new_blocks;
}
};
export function validate_each_keys(ctx, list, get_context, get_key) {
const keys = new Set();

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

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

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

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

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

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

Loading…
Cancel
Save