Comparing version 5.1.4 to 5.1.5
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.1.4", | ||
"version": "5.1.5", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -6,4 +6,5 @@ /* This file is generated by scripts/process-messages/index.js. Do not edit! */ | ||
/** @typedef {{ start?: number, end?: number }} NodeLike */ | ||
class InternalCompileError extends CompileDiagnostic { | ||
name = 'CompileError'; | ||
class InternalCompileError extends Error { | ||
message = ''; // ensure this property is enumerable | ||
#diagnostic; | ||
@@ -16,4 +17,19 @@ /** | ||
constructor(code, message, position) { | ||
super(code, message, position); | ||
super(message); | ||
this.stack = ''; // avoid unnecessary noise; don't set it as a class property or it becomes enumerable | ||
// We want to extend from Error so that various bundler plugins properly handle it. | ||
// But we also want to share the same object shape with that of warnings, therefore | ||
// we create an instance of the shared class an copy over its properties. | ||
this.#diagnostic = new CompileDiagnostic(code, message, position); | ||
Object.assign(this, this.#diagnostic); | ||
this.name = 'CompileError'; | ||
} | ||
toString() { | ||
return this.#diagnostic.toString(); | ||
} | ||
toJSON() { | ||
return this.#diagnostic.toJSON(); | ||
} | ||
} | ||
@@ -736,3 +752,3 @@ | ||
/** | ||
* {:...} block is invalid at this position (did you forget to close the preceeding element or block?) | ||
* {:...} block is invalid at this position (did you forget to close the preceding element or block?) | ||
* @param {null | number | NodeLike} node | ||
@@ -742,3 +758,3 @@ * @returns {never} | ||
export function block_invalid_continuation_placement(node) { | ||
e(node, "block_invalid_continuation_placement", "{:...} block is invalid at this position (did you forget to close the preceeding element or block?)"); | ||
e(node, "block_invalid_continuation_placement", "{:...} block is invalid at this position (did you forget to close the preceding element or block?)"); | ||
} | ||
@@ -745,0 +761,0 @@ |
@@ -42,6 +42,6 @@ /** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement, ExpressionStatement } from 'estree' */ | ||
* @param {string} source | ||
* @param {{filename?: string}} [options] | ||
* @param {{ filename?: string, use_ts?: boolean }} [options] | ||
* @returns {{ code: string; }} | ||
*/ | ||
export function migrate(source, { filename } = {}) { | ||
export function migrate(source, { filename, use_ts } = {}) { | ||
let og_source = source; | ||
@@ -119,5 +119,8 @@ try { | ||
has_svelte_self: false, | ||
uses_ts: !!parsed.instance?.attributes.some( | ||
(attr) => attr.name === 'lang' && /** @type {any} */ (attr).value[0].data === 'ts' | ||
) | ||
uses_ts: | ||
// Some people could use jsdoc but have a tsconfig.json, so double-check file for jsdoc indicators | ||
(use_ts && !source.includes('@type {')) || | ||
!!parsed.instance?.attributes.some( | ||
(attr) => attr.name === 'lang' && /** @type {any} */ (attr).value[0].data === 'ts' | ||
) | ||
}; | ||
@@ -124,0 +127,0 @@ |
@@ -60,3 +60,19 @@ /** @import { ExportNamedDeclaration, Identifier, Node } from 'estree' */ | ||
} | ||
if (!context.state.ast_type /* .svelte.js module */ || context.state.ast_type === 'module') { | ||
for (const specified of node.specifiers) { | ||
const binding = context.state.scope.get(specified.local.name); | ||
if (!binding) continue; | ||
if (binding.kind === 'derived') { | ||
e.derived_invalid_export(node); | ||
} | ||
if ((binding.kind === 'state' || binding.kind === 'raw_state') && binding.reassigned) { | ||
e.state_invalid_export(node); | ||
} | ||
} | ||
} | ||
} | ||
} |
@@ -248,6 +248,10 @@ /** @import { CallExpression, Expression, MemberExpression } from 'estree' */ | ||
context.state.after_update.push( | ||
b.stmt(has_action_directive ? b.call('$.effect', b.thunk(call)) : call) | ||
); | ||
if (has_action_directive) { | ||
context.state.init.push( | ||
b.stmt(has_action_directive ? b.call('$.effect', b.thunk(call)) : call) | ||
); | ||
} else { | ||
context.state.after_update.push(b.stmt(call)); | ||
} | ||
} | ||
} |
@@ -161,3 +161,3 @@ /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, ObjectExpression, Statement } from 'estree' */ | ||
/** @type {typeof state} */ | ||
const element_after_update_state = { ...context.state, after_update: [] }; | ||
const element_state = { ...context.state, init: [], after_update: [] }; | ||
@@ -168,7 +168,9 @@ for (const attribute of other_directives) { | ||
element_after_update_state.after_update.push( | ||
b.stmt(has_use ? b.call('$.effect', b.thunk(handler)) : handler) | ||
); | ||
if (has_use) { | ||
element_state.init.push(b.stmt(b.call('$.effect', b.thunk(handler)))); | ||
} else { | ||
element_state.after_update.push(b.stmt(handler)); | ||
} | ||
} else { | ||
context.visit(attribute, element_after_update_state); | ||
context.visit(attribute, element_state); | ||
} | ||
@@ -406,14 +408,12 @@ } | ||
...child_state.after_update, | ||
...element_after_update_state.after_update | ||
...element_state.after_update | ||
]) | ||
); | ||
} else if (node.fragment.metadata.dynamic) { | ||
context.state.init.push(...child_state.init); | ||
context.state.init.push(...child_state.init, ...element_state.init); | ||
context.state.update.push(...child_state.update); | ||
context.state.after_update.push( | ||
...child_state.after_update, | ||
...element_after_update_state.after_update | ||
); | ||
context.state.after_update.push(...child_state.after_update, ...element_state.after_update); | ||
} else { | ||
context.state.after_update.push(...element_after_update_state.after_update); | ||
context.state.init.push(...element_state.init); | ||
context.state.after_update.push(...element_state.after_update); | ||
} | ||
@@ -420,0 +420,0 @@ |
@@ -32,4 +32,4 @@ /** @import { Expression } from 'estree' */ | ||
// actions need to run after attribute updates in order with bindings/events | ||
context.state.after_update.push(b.stmt(b.call('$.action', ...args))); | ||
context.state.init.push(b.stmt(b.call('$.action', ...args))); | ||
context.next(); | ||
} |
@@ -14,2 +14,3 @@ /** @import { Visitors } from 'zimmerframe' */ | ||
* hash: string; | ||
* minify: boolean; | ||
* selector: string; | ||
@@ -36,2 +37,3 @@ * keyframes: string[]; | ||
hash: analysis.css.hash, | ||
minify: analysis.inject_styles && !options.dev, | ||
selector: `.${analysis.css.hash}`, | ||
@@ -50,2 +52,5 @@ keyframes: analysis.css.keyframes, | ||
code.remove(/** @type {number} */ (ast.content.end), source.length); | ||
if (state.minify) { | ||
remove_preceding_whitespace(ast.content.end, state); | ||
} | ||
@@ -122,11 +127,32 @@ const css = { | ||
} | ||
} else if (state.minify) { | ||
remove_preceding_whitespace(node.start, state); | ||
// Don't minify whitespace in custom properties, since some browsers (Chromium < 99) | ||
// treat --foo: ; and --foo:; differently | ||
if (!node.property.startsWith('--')) { | ||
let start = node.start + node.property.length + 1; | ||
let end = start; | ||
while (/\s/.test(state.code.original[end])) end++; | ||
if (end > start) state.code.remove(start, end); | ||
} | ||
} | ||
}, | ||
Rule(node, { state, next, visit }) { | ||
if (state.minify) { | ||
remove_preceding_whitespace(node.start, state); | ||
remove_preceding_whitespace(node.block.end - 1, state); | ||
} | ||
// keep empty rules in dev, because it's convenient to | ||
// see them in devtools | ||
if (!dev && is_empty(node)) { | ||
state.code.prependRight(node.start, '/* (empty) '); | ||
state.code.appendLeft(node.end, '*/'); | ||
escape_comment_close(node, state.code); | ||
if (state.minify) { | ||
state.code.remove(node.start, node.end); | ||
} else { | ||
state.code.prependRight(node.start, '/* (empty) '); | ||
state.code.appendLeft(node.end, '*/'); | ||
escape_comment_close(node, state.code); | ||
} | ||
return; | ||
@@ -136,5 +162,9 @@ } | ||
if (!is_used(node)) { | ||
state.code.prependRight(node.start, '/* (unused) '); | ||
state.code.appendLeft(node.end, '*/'); | ||
escape_comment_close(node, state.code); | ||
if (state.minify) { | ||
state.code.remove(node.start, node.end); | ||
} else { | ||
state.code.prependRight(node.start, '/* (unused) '); | ||
state.code.appendLeft(node.end, '*/'); | ||
escape_comment_close(node, state.code); | ||
} | ||
@@ -149,7 +179,12 @@ return; | ||
// `:global {...}` | ||
state.code.prependRight(node.start, '/* '); | ||
state.code.appendLeft(node.block.start + 1, '*/'); | ||
if (state.minify) { | ||
state.code.remove(node.start, node.block.start + 1); | ||
state.code.remove(node.block.end - 1, node.end); | ||
} else { | ||
state.code.prependRight(node.start, '/* '); | ||
state.code.appendLeft(node.block.start + 1, '*/'); | ||
state.code.prependRight(node.block.end - 1, '/*'); | ||
state.code.appendLeft(node.block.end, '*/'); | ||
state.code.prependRight(node.block.end - 1, '/*'); | ||
state.code.appendLeft(node.block.end, '*/'); | ||
} | ||
@@ -170,7 +205,9 @@ // don't recurse into selector or body | ||
if (!path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used)) { | ||
const children = node.children; | ||
let pruning = false; | ||
let last = node.children[0].start; | ||
let prune_start = children[0].start; | ||
let last = prune_start; | ||
for (let i = 0; i < node.children.length; i += 1) { | ||
const selector = node.children[i]; | ||
for (let i = 0; i < children.length; i += 1) { | ||
const selector = children[i]; | ||
@@ -182,8 +219,27 @@ if (selector.metadata.used === pruning) { | ||
state.code.overwrite(i, i + 1, '*/'); | ||
if (state.minify) { | ||
state.code.remove(prune_start, i + 1); | ||
} else { | ||
state.code.overwrite(i, i + 1, '*/'); | ||
} | ||
} else { | ||
if (i === 0) { | ||
state.code.prependRight(selector.start, '/* (unused) '); | ||
if (state.minify) { | ||
prune_start = selector.start; | ||
} else { | ||
state.code.prependRight(selector.start, '/* (unused) '); | ||
} | ||
} else { | ||
state.code.overwrite(last, selector.start, ' /* (unused) '); | ||
// If this is not the last selector add a separator | ||
const separator = i !== children.length - 1 ? ',' : ''; | ||
if (state.minify) { | ||
prune_start = last; | ||
if (separator) { | ||
while (state.code.original[prune_start - 1] !== ',') prune_start++; | ||
state.code.update(last, prune_start, separator); | ||
} | ||
} else { | ||
state.code.overwrite(last, selector.start, `${separator} /* (unused) `); | ||
} | ||
} | ||
@@ -199,3 +255,7 @@ } | ||
if (pruning) { | ||
state.code.appendLeft(last, '*/'); | ||
if (state.minify) { | ||
state.code.remove(prune_start, last); | ||
} else { | ||
state.code.appendLeft(last, '*/'); | ||
} | ||
} | ||
@@ -332,2 +392,13 @@ } | ||
/** | ||
* Walk backwards until we find a non-whitespace character | ||
* @param {number} end | ||
* @param {State} state | ||
*/ | ||
function remove_preceding_whitespace(end, state) { | ||
let start = end; | ||
while (/\s/.test(state.code.original[start - 1])) start--; | ||
if (start < end) state.code.remove(start, end); | ||
} | ||
/** @param {Css.Rule} rule */ | ||
@@ -334,0 +405,0 @@ function is_empty(rule) { |
@@ -54,4 +54,2 @@ /** @import { Location } from 'locate-character' */ | ||
name = 'CompileDiagnostic'; | ||
// adding an empty stack so that vite will show the file and frame during build | ||
stack = ''; | ||
@@ -58,0 +56,0 @@ /** |
@@ -6,4 +6,2 @@ /** @import { Raf } from '#client' */ | ||
const request_animation_frame = BROWSER ? requestAnimationFrame : noop; | ||
const now = BROWSER ? () => performance.now() : () => Date.now(); | ||
@@ -13,5 +11,8 @@ | ||
export const raf = { | ||
tick: /** @param {any} _ */ (_) => request_animation_frame(_), | ||
// don't access requestAnimationFrame eagerly outside method | ||
// this allows basic testing of user code without JSDOM | ||
// bunder will eval and remove ternary when the user's app is built | ||
tick: /** @param {any} _ */ (_) => (BROWSER ? requestAnimationFrame : noop)(_), | ||
now: () => now(), | ||
tasks: new Set() | ||
}; |
@@ -45,4 +45,7 @@ /** @import { Readable, Writable } from './public.js' */ | ||
export function toStore(get, set) { | ||
const store = writable(get(), (set) => { | ||
let ran = false; | ||
let init_value = get(); | ||
const store = writable(init_value, (set) => { | ||
// If the value has changed before we call subscribe, then | ||
// we need to treat the value as already having run | ||
let ran = init_value !== get(); | ||
@@ -134,5 +137,8 @@ // TODO do we need a different implementation on the server? | ||
return () => { | ||
subscribers -= 1; | ||
tick().then(() => { | ||
// Only count down after timeout, else we would reach 0 before our own render effect reruns, | ||
// but reach 1 again when the tick callback of the prior teardown runs. That would mean we | ||
// re-subcribe unnecessarily and create a memory leak because the old subscription is never cleaned up. | ||
subscribers -= 1; | ||
tick().then(() => { | ||
if (subscribers === 0) { | ||
@@ -139,0 +145,0 @@ unsubscribe(); |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.1.4'; | ||
export const VERSION = '5.1.5'; | ||
export const PUBLIC_VERSION = '5'; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2301841
50751
23
41
293