diff --git a/src/internal/animations.js b/src/internal/animations.js index 388110babb..8d55c196ee 100644 --- a/src/internal/animations.js +++ b/src/internal/animations.js @@ -1,4 +1,4 @@ -import { identity as linear, noop } from './utils.js'; +import { identity as linear, noop, now } from './utils.js'; import { loop } from './loop.js'; import { create_rule, delete_rule } from './style_manager.js'; @@ -12,7 +12,7 @@ export function create_animation(node, from, fn, params) { delay = 0, duration = 300, easing = linear, - start: start_time = window.performance.now() + delay, + start: start_time = now() + delay, end = start_time + duration, tick = noop, css diff --git a/src/internal/loop.js b/src/internal/loop.js index fd75f9b1a6..8150727441 100644 --- a/src/internal/loop.js +++ b/src/internal/loop.js @@ -1,9 +1,11 @@ +import { now } from './utils.js'; + const tasks = new Set(); let running = false; function run_tasks() { tasks.forEach(task => { - if (!task[0](window.performance.now())) { + if (!task[0](now())) { tasks.delete(task); task[1](); } diff --git a/src/internal/transitions.js b/src/internal/transitions.js index 3649de2b0c..af15e8969e 100644 --- a/src/internal/transitions.js +++ b/src/internal/transitions.js @@ -1,4 +1,4 @@ -import { identity as linear, noop, run_all } from './utils.js'; +import { identity as linear, noop, now, run_all } from './utils.js'; import { loop } from './loop.js'; import { create_rule, delete_rule } from './style_manager.js'; import { custom_event } from './dom.js'; @@ -63,7 +63,7 @@ export function create_in_transition(node, fn, params) { if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++); tick(0, 1); - const start_time = window.performance.now() + delay; + const start_time = now() + delay; const end_time = start_time + duration; if (task) task.abort(); @@ -136,7 +136,7 @@ export function create_out_transition(node, fn, params) { if (css) animation_name = create_rule(node, 1, 0, duration, delay, easing, css); - const start_time = window.performance.now() + delay; + const start_time = now() + delay; const end_time = start_time + duration; loop(now => { @@ -224,7 +224,7 @@ export function create_bidirectional_transition(node, fn, params, intro) { } = config; const program = { - start: window.performance.now() + delay, + start: now() + delay, b }; diff --git a/src/internal/utils.js b/src/internal/utils.js index 3ae62e375f..e6d66d8717 100644 --- a/src/internal/utils.js +++ b/src/internal/utils.js @@ -79,3 +79,12 @@ export function exclude_internal_props(props) { for (const k in props) if (k[0] !== '$') result[k] = props[k]; return result; } + +export let now = typeof window !== 'undefined' + ? () => window.performance.now() + : () => Date.now(); + +// used internally for testing +export function set_now(fn) { + now = fn; +} \ No newline at end of file diff --git a/src/motion/spring.js b/src/motion/spring.js index 7c3d287ef8..8b280366b2 100644 --- a/src/motion/spring.js +++ b/src/motion/spring.js @@ -1,5 +1,5 @@ import { writable } from 'svelte/store'; // eslint-disable-line import/no-unresolved -import { loop } from 'svelte/internal'; // eslint-disable-line import/no-unresolved +import { loop, now } from 'svelte/internal'; // eslint-disable-line import/no-unresolved import { is_date } from './utils.js'; function tick_spring(ctx, last_value, current_value, target_value) { @@ -51,7 +51,7 @@ export function spring(value, opts = {}) { if (opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) { cancel_task = true; // cancel any running animation - last_time = window.performance.now(); + last_time = now(); last_value = value; store.set(value = target_value); return new Promise(f => f()); // fulfil immediately @@ -62,7 +62,7 @@ export function spring(value, opts = {}) { } if (!task) { - last_time = window.performance.now(); + last_time = now(); cancel_task = false; task = loop(now => { diff --git a/src/motion/tweened.js b/src/motion/tweened.js index a3b5f7331e..45520832b7 100644 --- a/src/motion/tweened.js +++ b/src/motion/tweened.js @@ -1,5 +1,5 @@ import { writable } from 'svelte/store'; // eslint-disable-line import/no-unresolved -import { assign, loop } from 'svelte/internal'; // eslint-disable-line import/no-unresolved +import { assign, loop, now } from 'svelte/internal'; // eslint-disable-line import/no-unresolved import { linear } from 'svelte/easing'; // eslint-disable-line import/no-unresolved import { is_date } from './utils.js'; @@ -73,7 +73,7 @@ export function tweened(value, defaults = {}) { interpolate = get_interpolator } = assign(assign({}, defaults), opts); - const start = window.performance.now() + delay; + const start = now() + delay; let fn; task = loop(now => { diff --git a/test/runtime/index.js b/test/runtime/index.js index 64d7f3ae51..db02ce13d4 100644 --- a/test/runtime/index.js +++ b/test/runtime/index.js @@ -3,7 +3,7 @@ import * as path from "path"; import * as fs from "fs"; import { rollup } from 'rollup'; import * as virtual from 'rollup-plugin-virtual'; -import { clear_loops } from "../../internal.js"; +import { clear_loops, set_now } from "../../internal.js"; import { showOutput, @@ -100,7 +100,7 @@ describe("runtime", () => { if (raf.callback) raf.callback(); } }; - window.performance.now = () => raf.time; + set_now(() => raf.time); global.requestAnimationFrame = cb => { let called = false; raf.callback = () => { diff --git a/test/runtime/samples/spring/_config.js b/test/runtime/samples/spring/_config.js new file mode 100644 index 0000000000..79399b777a --- /dev/null +++ b/test/runtime/samples/spring/_config.js @@ -0,0 +1,3 @@ +export default { + html: `

0

` +} \ No newline at end of file diff --git a/test/runtime/samples/spring/main.svelte b/test/runtime/samples/spring/main.svelte new file mode 100644 index 0000000000..39c9afde1d --- /dev/null +++ b/test/runtime/samples/spring/main.svelte @@ -0,0 +1,8 @@ + + +

{$x}

\ No newline at end of file diff --git a/test/server-side-rendering/index.js b/test/server-side-rendering/index.js index 9f67ee06e9..4b648c0591 100644 --- a/test/server-side-rendering/index.js +++ b/test/server-side-rendering/index.js @@ -102,6 +102,8 @@ describe("ssr", () => { delete require.cache[file]; }); + delete global.window; + const compileOptions = Object.assign({ sveltePath }, config.compileOptions, { generate: 'ssr' });