diff --git a/CHANGELOG.md b/CHANGELOG.md index 56390f7b25..effa1e821c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Svelte changelog +## Unreleased + +* Support `export { ... } from` syntax in components ([#2214](https://github.com/sveltejs/svelte/issues/2214)) + +## 3.40.3 + +* Fix `` data when a transition is cancelled before completing ([#5394](https://github.com/sveltejs/svelte/issues/5394)) +* Fix destructuring into variables beginning with `$` so that they result in store updates ([#5653](https://github.com/sveltejs/svelte/issues/5653)) +* Fix `in:` transition configuration not properly updating when it's changed after its initial creation ([#6505](https://github.com/sveltejs/svelte/issues/6505)) +* Fix applying `:global()` for `>` selector combinator ([#6550](https://github.com/sveltejs/svelte/issues/6550)) +* Fix mounting component at detached DOM node ([#6567](https://github.com/sveltejs/svelte/issues/6567)) + ## 3.40.2 * Fix dynamic `autofocus={...}` attribute handling ([#4995](https://github.com/sveltejs/svelte/issues/4995)) diff --git a/package-lock.json b/package-lock.json index d1d890e4a4..e059174ea6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.40.2", + "version": "3.40.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9b927795a7..6f6303348f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.40.2", + "version": "3.40.3", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index ca0c1d4993..bbf3071583 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -516,6 +516,7 @@ The following modifiers are available: * `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase * `once` — remove the handler after the first time it runs * `self` — only trigger handler if event.target is the element itself +* `trusted` — only trigger handler if `event.trusted` is `true`. I.e. if the event is triggered by a user action. Modifiers can be chained together, e.g. `on:click|once|capture={...}`. diff --git a/site/content/tutorial/05-events/03-event-modifiers/text.md b/site/content/tutorial/05-events/03-event-modifiers/text.md index 2b2d6e6b31..f6a4b5784d 100644 --- a/site/content/tutorial/05-events/03-event-modifiers/text.md +++ b/site/content/tutorial/05-events/03-event-modifiers/text.md @@ -25,5 +25,6 @@ The full list of modifiers: * `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase ([MDN docs](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture)) * `once` — remove the handler after the first time it runs * `self` — only trigger handler if event.target is the element itself +* `trusted` — only trigger handler if `event.trusted` is `true`. I.e. if the event is triggered by a user action. You can chain modifiers together, e.g. `on:click|once|capture={...}`. diff --git a/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md b/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md index 69de470f34..e7b625c6d6 100644 --- a/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md +++ b/site/content/tutorial/06-bindings/07-multiple-select-bindings/text.md @@ -18,4 +18,4 @@ Returning to our [earlier ice cream example](tutorial/group-inputs), we can repl ``` -> Press and hold the `shift` key for selecting multiple options. +> Press and hold the `control` key for selecting multiple options. diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index a3eeb981c2..6a8d5b178e 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -24,7 +24,7 @@ import TemplateScope from './nodes/shared/TemplateScope'; import fuzzymatch from '../utils/fuzzymatch'; import get_object from './utils/get_object'; import Slot from './nodes/Slot'; -import { Node, ImportDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement } from 'estree'; +import { Node, ImportDeclaration, ExportNamedDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement, ExportDefaultDeclaration, ExportAllDeclaration } from 'estree'; import add_to_set from './utils/add_to_set'; import check_graph_for_cycles from './utils/check_graph_for_cycles'; import { print, b } from 'code-red'; @@ -70,6 +70,8 @@ export default class Component { var_lookup: Map = new Map(); imports: ImportDeclaration[] = []; + exports_from: ExportNamedDeclaration[] = []; + instance_exports_from: ExportNamedDeclaration[] = []; hoistable_nodes: Set = new Set(); node_for_declaration: Map = new Map(); @@ -333,7 +335,8 @@ export default class Component { .map(variable => ({ name: variable.name, as: variable.export_name - })) + })), + this.exports_from ); css = compile_options.customElement @@ -492,22 +495,27 @@ export default class Component { this.imports.push(node); } - extract_exports(node) { + extract_exports(node, module_script = false) { const ignores = extract_svelte_ignore_from_comments(node); if (ignores.length) this.push_ignores(ignores); - const result = this._extract_exports(node); + const result = this._extract_exports(node, module_script); if (ignores.length) this.pop_ignores(); return result; } - private _extract_exports(node) { + private _extract_exports(node: ExportDefaultDeclaration | ExportNamedDeclaration | ExportAllDeclaration, module_script) { if (node.type === 'ExportDefaultDeclaration') { - return this.error(node, compiler_errors.default_export); + return this.error(node as any, compiler_errors.default_export); } if (node.type === 'ExportNamedDeclaration') { if (node.source) { - return this.error(node, compiler_errors.not_implemented); + if (module_script) { + this.exports_from.push(node); + } else { + this.instance_exports_from.push(node); + } + return null; } if (node.declaration) { if (node.declaration.type === 'VariableDeclaration') { @@ -516,7 +524,7 @@ export default class Component { const variable = this.var_lookup.get(name); variable.export_name = name; if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) { - this.warn(declarator, compiler_warnings.unused_export_let(this.name.name, name)); + this.warn(declarator as any, compiler_warnings.unused_export_let(this.name.name, name)); } }); }); @@ -536,7 +544,7 @@ export default class Component { variable.export_name = specifier.exported.name; if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) { - this.warn(specifier, compiler_warnings.unused_export_let(this.name.name, specifier.exported.name)); + this.warn(specifier as any, compiler_warnings.unused_export_let(this.name.name, specifier.exported.name)); } } }); @@ -612,7 +620,7 @@ export default class Component { } if (/^Export/.test(node.type)) { - const replacement = this.extract_exports(node); + const replacement = this.extract_exports(node, true); if (replacement) { body[i] = replacement; } else { @@ -1010,7 +1018,7 @@ export default class Component { rename_identifiers(prop.value); } }; - + param.properties.forEach(handle_prop); break; } @@ -1024,15 +1032,15 @@ export default class Component { } } }; - + param.elements.forEach(handle_element); break; } - + case 'RestElement': param.argument = get_new_name(param.argument); break; - + case 'AssignmentPattern': param.left = get_new_name(param.left); break; diff --git a/src/compiler/compile/compiler_errors.ts b/src/compiler/compile/compiler_errors.ts index 6f4f6e902c..54263c3eb9 100644 --- a/src/compiler/compile/compiler_errors.ts +++ b/src/compiler/compile/compiler_errors.ts @@ -174,10 +174,6 @@ export default { code: 'default-export', message: 'A component cannot have a default export' }, - not_implemented: { - code: 'not-implemented', - message: 'A component currently cannot have an export ... from' - }, illegal_declaration: { code: 'illegal-declaration', message: 'The $ prefix is reserved, and cannot be used for variable and import names' diff --git a/src/compiler/compile/create_module.ts b/src/compiler/compile/create_module.ts index 80e6308263..037b2b396e 100644 --- a/src/compiler/compile/create_module.ts +++ b/src/compiler/compile/create_module.ts @@ -1,7 +1,7 @@ import list from '../utils/list'; import { ModuleFormat } from '../interfaces'; import { b, x } from 'code-red'; -import { Identifier, ImportDeclaration } from 'estree'; +import { Identifier, ImportDeclaration, ExportNamedDeclaration } from 'estree'; const wrappers = { esm, cjs }; @@ -19,20 +19,21 @@ export default function create_module( helpers: Array<{ name: string; alias: Identifier }>, globals: Array<{ name: string; alias: Identifier }>, imports: ImportDeclaration[], - module_exports: Export[] + module_exports: Export[], + exports_from: ExportNamedDeclaration[] ) { const internal_path = `${sveltePath}/internal`; helpers.sort((a, b) => (a.name < b.name) ? -1 : 1); globals.sort((a, b) => (a.name < b.name) ? -1 : 1); + + const formatter = wrappers[format]; - if (format === 'esm') { - return esm(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports); + if (!formatter) { + throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`); } - if (format === 'cjs') return cjs(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports); - - throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`); + return formatter(program, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports, exports_from); } function edit_source(source, sveltePath) { @@ -76,7 +77,8 @@ function esm( helpers: Array<{ name: string; alias: Identifier }>, globals: Array<{ name: string; alias: Identifier }>, imports: ImportDeclaration[], - module_exports: Export[] + module_exports: Export[], + exports_from: ExportNamedDeclaration[] ) { const import_declaration = { type: 'ImportDeclaration', @@ -94,6 +96,9 @@ function esm( imports.forEach(node => { node.source.value = edit_source(node.source.value, sveltePath); }); + exports_from.forEach(node => { + node.source!.value = edit_source(node.source!.value, sveltePath); + }); const exports = module_exports.length > 0 && { type: 'ExportNamedDeclaration', @@ -110,6 +115,7 @@ function esm( ${import_declaration} ${internal_globals} ${imports} + ${exports_from} ${program.body} @@ -127,7 +133,8 @@ function cjs( helpers: Array<{ name: string; alias: Identifier }>, globals: Array<{ name: string; alias: Identifier }>, imports: ImportDeclaration[], - module_exports: Export[] + module_exports: Export[], + exports_from: ExportNamedDeclaration[] ) { const internal_requires = { type: 'VariableDeclaration', @@ -183,6 +190,13 @@ function cjs( const exports = module_exports.map(x => b`exports.${{ type: 'Identifier', name: x.as }} = ${{ type: 'Identifier', name: x.name }};`); + const user_exports_from = exports_from.map(node => { + const init = x`require("${edit_source(node.source.value, sveltePath)}")`; + return node.specifiers.map(specifier => { + return b`exports.${specifier.exported} = ${init}.${specifier.local};`; + }); + }); + program.body = b` /* ${banner} */ @@ -190,6 +204,7 @@ function cjs( ${internal_requires} ${internal_globals} ${user_requires} + ${user_exports_from} ${program.body} diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index c88a244a13..d9868f4530 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -227,7 +227,8 @@ function apply_selector(blocks: Block[], node: Element, to_encapsulate: Array<{ return false; } else if (block.combinator.name === '>') { - if (apply_selector(blocks, get_element_parent(node), to_encapsulate)) { + const has_global_parent = blocks.every(block => block.global); + if (has_global_parent || apply_selector(blocks, get_element_parent(node), to_encapsulate)) { to_encapsulate.push({ node, block }); return true; } diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 535983cfd0..f74f4cdf1c 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -6,7 +6,7 @@ import { walk } from 'estree-walker'; import { extract_names, Scope } from 'periscopic'; import { invalidate } from './invalidate'; import Block from './Block'; -import { ClassDeclaration, FunctionExpression, Node, Statement, ObjectExpression, Expression } from 'estree'; +import { ImportDeclaration, ClassDeclaration, FunctionExpression, Node, Statement, ObjectExpression, Expression } from 'estree'; import { apply_preprocessor_sourcemap } from '../../utils/mapped_code'; import { RawSourceMap, DecodedSourceMap } from '@ampproject/remapping/dist/types/types'; import { flatten } from '../../utils/flatten'; @@ -174,6 +174,46 @@ export default function dom( } }); + component.instance_exports_from.forEach(exports_from => { + const import_declaration = { + ...exports_from, + type: 'ImportDeclaration', + specifiers: [], + source: exports_from.source + }; + component.imports.push(import_declaration as ImportDeclaration); + + exports_from.specifiers.forEach(specifier => { + if (component.component_options.accessors) { + const name = component.get_unique_name(specifier.exported.name); + import_declaration.specifiers.push({ + ...specifier, + type: 'ImportSpecifier', + imported: specifier.local, + local: name + }); + + accessors.push({ + type: 'MethodDefinition', + kind: 'get', + key: { type: 'Identifier', name: specifier.exported.name }, + value: x`function() { + return ${name} + }` + }); + } else if (component.compile_options.dev) { + accessors.push({ + type: 'MethodDefinition', + kind: 'get', + key: { type: 'Identifier', name: specifier.exported.name }, + value: x`function() { + throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''"); + }` + }); + } + }); + }); + if (component.compile_options.dev) { // checking that expected ones were passed const expected = props.filter(prop => prop.writable && !prop.initialised); diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 62c45c093d..db26b6673c 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -760,7 +760,7 @@ export default class ElementWrapper extends Wrapper { intro_block = b` @add_render_callback(() => { if (${outro_name}) ${outro_name}.end(1); - if (!${intro_name}) ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet}); + ${intro_name} = @create_in_transition(${this.var}, ${fn}, ${snippet}); ${intro_name}.start(); }); `; diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index 937a75b0aa..5a778ba5fb 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -92,7 +92,7 @@ export default class SlotWrapper extends Wrapper { add_to_set(spread_dynamic_dependencies, Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name))); } else { const dynamic_dependencies = Array.from(attribute.dependencies).filter((name) => this.is_dependency_dynamic(name)); - + if (dynamic_dependencies.length > 0) { changes.properties.push(p`${attribute.name}: ${renderer.dirty(dynamic_dependencies)}`); } @@ -107,7 +107,7 @@ export default class SlotWrapper extends Wrapper { if (spread_dynamic_dependencies.size) { get_slot_spread_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_spread_changes`); renderer.blocks.push(b` - const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))} > 0 ? -1 : 0; + const ${get_slot_spread_changes_fn} = #dirty => ${renderer.dirty(Array.from(spread_dynamic_dependencies))}; `); } } else { @@ -168,27 +168,41 @@ export default class SlotWrapper extends Wrapper { if (block.has_outros) { condition = x`!#current || ${condition}`; } - let dirty = x`#dirty`; - if (block.has_outros) { - dirty = x`!#current ? ${renderer.get_initial_dirty()} : ${dirty}`; + + // conditions to treat everything as dirty + const all_dirty_conditions = [ + get_slot_spread_changes_fn ? x`${get_slot_spread_changes_fn}(#dirty)` : null, + block.has_outros ? x`!#current` : null + ].filter(Boolean); + const all_dirty_condition = all_dirty_conditions.length ? all_dirty_conditions.reduce((condition1, condition2) => x`${condition1} || ${condition2}`) : null; + + let slot_update; + if (all_dirty_condition) { + const dirty = x`${all_dirty_condition} ? @get_all_dirty_from_scope(${renderer.reference('$$scope')}) : @get_slot_changes(${slot_definition}, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn})`; + + slot_update = b` + if (${slot}.p && ${condition}) { + @update_slot_base(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_context_fn}); + } + `; + } else { + slot_update = b` + if (${slot}.p && ${condition}) { + @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}, ${get_slot_context_fn}); + } + `; } - const slot_update = get_slot_spread_changes_fn ? b` - if (${slot}.p && ${condition}) { - @update_slot_spread(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_changes_fn}, ${get_slot_spread_changes_fn}, ${get_slot_context_fn}); - } - ` : b` - if (${slot}.p && ${condition}) { - @update_slot(${slot}, ${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${dirty}, ${get_slot_changes_fn}, ${get_slot_context_fn}); - } - `; let fallback_condition = renderer.dirty(fallback_dynamic_dependencies); + let fallback_dirty = x`#dirty`; if (block.has_outros) { fallback_condition = x`!#current || ${fallback_condition}`; + fallback_dirty = x`!#current ? ${renderer.get_initial_dirty()} : ${fallback_dirty}`; } + const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b` if (${slot_or_fallback} && ${slot_or_fallback}.p && ${fallback_condition}) { - ${slot_or_fallback}.p(#ctx, ${dirty}); + ${slot_or_fallback}.p(#ctx, ${fallback_dirty}); } `; diff --git a/src/compiler/interfaces.ts b/src/compiler/interfaces.ts index c9eb9e0236..73be74bef9 100644 --- a/src/compiler/interfaces.ts +++ b/src/compiler/interfaces.ts @@ -46,7 +46,7 @@ interface BaseDirective extends BaseNode { modifiers: string[]; } -export interface Transition extends BaseDirective{ +export interface Transition extends BaseDirective { type: 'Transition'; intro: boolean; outro: boolean; diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index e9976a7fa6..f563f6d099 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -134,9 +134,9 @@ export function append_styles( style_sheet_id: string, styles: string ) { - const append_styles_to = get_root_for_styles(target); + const append_styles_to = get_root_for_style(target); - if (!append_styles_to?.getElementById(style_sheet_id)) { + if (!append_styles_to.getElementById(style_sheet_id)) { const style = element('style'); style.id = style_sheet_id; style.textContent = styles; @@ -144,20 +144,19 @@ export function append_styles( } } -export function get_root_for_node(node: Node) { +export function get_root_for_style(node: Node): ShadowRoot | Document { if (!node) return document; - return (node.getRootNode ? node.getRootNode() : node.ownerDocument); // check for getRootNode because IE is still supported -} - -function get_root_for_styles(node: Node) { - const root = get_root_for_node(node); - return (root as ShadowRoot).host ? root as ShadowRoot : root as Document; + const root = node.getRootNode ? node.getRootNode() : node.ownerDocument; + if ((root as ShadowRoot).host) { + return root as ShadowRoot; + } + return document; } export function append_empty_stylesheet(node: Node) { const style_element = element('style') as HTMLStyleElement; - append_stylesheet(get_root_for_styles(node), style_element); + append_stylesheet(get_root_for_style(node), style_element); return style_element; } diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index a646c9b916..0993b3bf18 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,4 +1,4 @@ -import { append_empty_stylesheet, get_root_for_node } from './dom'; +import { append_empty_stylesheet, get_root_for_style } from './dom'; import { raf } from './environment'; interface ExtendedDoc extends Document { @@ -29,7 +29,7 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; const name = `__svelte_${hash(rule)}_${uid}`; - const doc = get_root_for_node(node) as unknown as ExtendedDoc; + const doc = get_root_for_style(node) as ExtendedDoc; active_docs.add(doc); const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = append_empty_stylesheet(node).sheet as CSSStyleSheet); const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {}); diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index f487732b77..8868e38ee2 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -119,20 +119,28 @@ export function get_slot_changes(definition, $$scope, dirty, fn) { return $$scope.dirty; } -export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) { - const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn); +export function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) { if (slot_changes) { const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn); slot.p(slot_context, slot_changes); } } -export function update_slot_spread(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_spread_changes_fn, get_slot_context_fn) { - const slot_changes = get_slot_spread_changes_fn(dirty) | get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn); - if (slot_changes) { - const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn); - slot.p(slot_context, slot_changes); +export function update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) { + const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn); + update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn); +} + +export function get_all_dirty_from_scope($$scope) { + if ($$scope.ctx.length > 32) { + const dirty = []; + const length = $$scope.ctx.length / 32; + for (let i = 0; i < length; i++) { + dirty[i] = -1; + } + return dirty; } + return -1; } export function exclude_internal_props(props) { @@ -169,7 +177,7 @@ export function null_to_empty(value) { return value == null ? '' : value; } -export function set_store_value(store, ret, value = ret) { +export function set_store_value(store, ret, value) { store.set(value); return ret; } diff --git a/test/css/samples/global-with-child-combinator-2/_config.js b/test/css/samples/global-with-child-combinator-2/_config.js new file mode 100644 index 0000000000..2286f4fe3c --- /dev/null +++ b/test/css/samples/global-with-child-combinator-2/_config.js @@ -0,0 +1,27 @@ +export default { + warnings: [ + { + code: 'css-unused-selector', + end: { + character: 111, + column: 21, + line: 8 + }, + frame: ` + 6: color: red; + 7: } + 8: a:global(.foo) > div { + ^ + 9: color: red; + 10: } + `, + message: 'Unused CSS selector "a:global(.foo) > div"', + pos: 91, + start: { + character: 91, + column: 1, + line: 8 + } + } + ] +}; diff --git a/test/css/samples/global-with-child-combinator-2/expected.css b/test/css/samples/global-with-child-combinator-2/expected.css new file mode 100644 index 0000000000..3f406244a3 --- /dev/null +++ b/test/css/samples/global-with-child-combinator-2/expected.css @@ -0,0 +1 @@ +div>div.svelte-xyz.svelte-xyz{color:red}div.svelte-xyz.foo>div.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/global-with-child-combinator-2/expected.html b/test/css/samples/global-with-child-combinator-2/expected.html new file mode 100644 index 0000000000..32ff99e34f --- /dev/null +++ b/test/css/samples/global-with-child-combinator-2/expected.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/test/css/samples/global-with-child-combinator-2/input.svelte b/test/css/samples/global-with-child-combinator-2/input.svelte new file mode 100644 index 0000000000..caf7c5869a --- /dev/null +++ b/test/css/samples/global-with-child-combinator-2/input.svelte @@ -0,0 +1,15 @@ + + +
+
+
\ No newline at end of file diff --git a/test/css/samples/global-with-child-combinator-3/_config.js b/test/css/samples/global-with-child-combinator-3/_config.js new file mode 100644 index 0000000000..c81f1a9f82 --- /dev/null +++ b/test/css/samples/global-with-child-combinator-3/_config.js @@ -0,0 +1,3 @@ +export default { + warnings: [] +}; diff --git a/test/css/samples/global-with-child-combinator-3/expected.css b/test/css/samples/global-with-child-combinator-3/expected.css new file mode 100644 index 0000000000..11c60c7147 --- /dev/null +++ b/test/css/samples/global-with-child-combinator-3/expected.css @@ -0,0 +1 @@ +a>b>div.svelte-xyz{color:red} \ No newline at end of file diff --git a/test/css/samples/global-with-child-combinator-3/expected.html b/test/css/samples/global-with-child-combinator-3/expected.html new file mode 100644 index 0000000000..32ff99e34f --- /dev/null +++ b/test/css/samples/global-with-child-combinator-3/expected.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/test/css/samples/global-with-child-combinator-3/input.svelte b/test/css/samples/global-with-child-combinator-3/input.svelte new file mode 100644 index 0000000000..146f302633 --- /dev/null +++ b/test/css/samples/global-with-child-combinator-3/input.svelte @@ -0,0 +1,9 @@ + + +
+
+
\ No newline at end of file diff --git a/test/css/samples/global-with-child-combinator/expected.html b/test/css/samples/global-with-child-combinator/expected.html new file mode 100644 index 0000000000..32ff99e34f --- /dev/null +++ b/test/css/samples/global-with-child-combinator/expected.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/test/js/samples/export-from-accessors/_config.js b/test/js/samples/export-from-accessors/_config.js new file mode 100644 index 0000000000..7f9293a560 --- /dev/null +++ b/test/js/samples/export-from-accessors/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + accessors: true + } +}; diff --git a/test/js/samples/export-from-accessors/expected.js b/test/js/samples/export-from-accessors/expected.js new file mode 100644 index 0000000000..20b0524ca7 --- /dev/null +++ b/test/js/samples/export-from-accessors/expected.js @@ -0,0 +1,34 @@ +/* generated by Svelte vX.Y.Z */ +import { SvelteComponent, init, safe_not_equal } from "svelte/internal"; + +import { f as f_1, g as g_1 } from './d'; +import { h as h_1 } from './e'; +import { i as j } from './f'; +export { d as e } from './c'; +export { c } from './b'; +export { a, b } from './a'; + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, null, null, safe_not_equal, {}); + } + + get f() { + return f_1; + } + + get g() { + return g_1; + } + + get h() { + return h_1; + } + + get j() { + return j; + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/export-from-accessors/input.svelte b/test/js/samples/export-from-accessors/input.svelte new file mode 100644 index 0000000000..66957806a2 --- /dev/null +++ b/test/js/samples/export-from-accessors/input.svelte @@ -0,0 +1,11 @@ + + + diff --git a/test/js/samples/export-from-cjs/_config.js b/test/js/samples/export-from-cjs/_config.js new file mode 100644 index 0000000000..2506f1d5fc --- /dev/null +++ b/test/js/samples/export-from-cjs/_config.js @@ -0,0 +1,6 @@ +export default { + options: { + accessors: true, + format: 'cjs' + } +}; diff --git a/test/js/samples/export-from-cjs/expected.js b/test/js/samples/export-from-cjs/expected.js new file mode 100644 index 0000000000..d40f986635 --- /dev/null +++ b/test/js/samples/export-from-cjs/expected.js @@ -0,0 +1,36 @@ +/* generated by Svelte vX.Y.Z */ +"use strict"; + +const { SvelteComponent, init, safe_not_equal } = require("svelte/internal"); +const { f: f_1, g: g_1 } = require("./d"); +const { h: h_1 } = require("./e"); +const { i: j } = require("./f"); +exports.e = require("./c").d; +exports.c = require("./b").c; +exports.a = require("./a").a; +exports.b = require("./a").b; + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, null, null, safe_not_equal, {}); + } + + get f() { + return f_1; + } + + get g() { + return g_1; + } + + get h() { + return h_1; + } + + get j() { + return j; + } +} + +exports.default = Component; \ No newline at end of file diff --git a/test/js/samples/export-from-cjs/input.svelte b/test/js/samples/export-from-cjs/input.svelte new file mode 100644 index 0000000000..66957806a2 --- /dev/null +++ b/test/js/samples/export-from-cjs/input.svelte @@ -0,0 +1,11 @@ + + + diff --git a/test/js/samples/export-from/expected.js b/test/js/samples/export-from/expected.js new file mode 100644 index 0000000000..04fb47605f --- /dev/null +++ b/test/js/samples/export-from/expected.js @@ -0,0 +1,18 @@ +/* generated by Svelte vX.Y.Z */ +import { SvelteComponent, init, safe_not_equal } from "svelte/internal"; + +import './d'; +import './e'; +import './f'; +export { d as e } from './c'; +export { c } from './b'; +export { a, b } from './a'; + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, null, null, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/export-from/input.svelte b/test/js/samples/export-from/input.svelte new file mode 100644 index 0000000000..66957806a2 --- /dev/null +++ b/test/js/samples/export-from/input.svelte @@ -0,0 +1,11 @@ + + + diff --git a/test/runtime/samples/export-from/A.svelte b/test/runtime/samples/export-from/A.svelte new file mode 100644 index 0000000000..7773727704 --- /dev/null +++ b/test/runtime/samples/export-from/A.svelte @@ -0,0 +1,23 @@ + + + + +a: {typeof a}
+b: {typeof b}
+c: {typeof c}
+d: {typeof d}
+e: {typeof e}
+f: {typeof f}
+g: {typeof g}
\ No newline at end of file diff --git a/test/runtime/samples/export-from/B.svelte b/test/runtime/samples/export-from/B.svelte new file mode 100644 index 0000000000..0cc1070cb5 --- /dev/null +++ b/test/runtime/samples/export-from/B.svelte @@ -0,0 +1,8 @@ + diff --git a/test/runtime/samples/export-from/_config.js b/test/runtime/samples/export-from/_config.js new file mode 100644 index 0000000000..9e65b7501d --- /dev/null +++ b/test/runtime/samples/export-from/_config.js @@ -0,0 +1,28 @@ +export default { + html: ` + a,b,undefined,c +
+ a: undefined
+ b: number
+ c: undefined
+ d: undefined
+ e: number
+ f: undefined
+ g: undefined
+
+ {"d":"d","e":"e","g":"f"} + `, + ssrHtml: ` + a,b,undefined,c +
+ a: undefined
+ b: number
+ c: undefined
+ d: undefined
+ e: number
+ f: undefined
+ g: undefined
+
+ {} + ` +}; diff --git a/test/runtime/samples/export-from/main.svelte b/test/runtime/samples/export-from/main.svelte new file mode 100644 index 0000000000..18cc066c1f --- /dev/null +++ b/test/runtime/samples/export-from/main.svelte @@ -0,0 +1,21 @@ + + +{a},{b},{c},{d} +
+ +
+{JSON.stringify(props)} \ No newline at end of file diff --git a/test/runtime/samples/store-assignment-updates-destructure/_config.js b/test/runtime/samples/store-assignment-updates-destructure/_config.js new file mode 100644 index 0000000000..7a1023614c --- /dev/null +++ b/test/runtime/samples/store-assignment-updates-destructure/_config.js @@ -0,0 +1,11 @@ +export default { + html: ` +
$userName1: user1
+
$userName2: undefined
+
$userName3: undefined
+
$userName4: user4
+
$userName5: undefined
+
$userName6: user6
+
$userName7: undefined
+ ` +}; diff --git a/test/runtime/samples/store-assignment-updates-destructure/main.svelte b/test/runtime/samples/store-assignment-updates-destructure/main.svelte new file mode 100644 index 0000000000..71e02fe16d --- /dev/null +++ b/test/runtime/samples/store-assignment-updates-destructure/main.svelte @@ -0,0 +1,34 @@ + + +
$userName1: {$userName1}
+
$userName2: {$userName2}
+
$userName3: {$userName3}
+
$userName4: {$userName4}
+
$userName5: {$userName5}
+
$userName6: {$userName6}
+
$userName7: {$userName7}
diff --git a/test/runtime/samples/target-dom-detached/App.svelte b/test/runtime/samples/target-dom-detached/App.svelte new file mode 100644 index 0000000000..251e480307 --- /dev/null +++ b/test/runtime/samples/target-dom-detached/App.svelte @@ -0,0 +1,11 @@ + + +
Hello {name}
+ + \ No newline at end of file diff --git a/test/runtime/samples/target-dom-detached/_config.js b/test/runtime/samples/target-dom-detached/_config.js new file mode 100644 index 0000000000..b63656530c --- /dev/null +++ b/test/runtime/samples/target-dom-detached/_config.js @@ -0,0 +1,16 @@ +export default { + skip_if_ssr: true, + compileOptions: { + cssHash: () => 'svelte-xyz' + }, + async test({ assert, component, target, window }) { + assert.htmlEqual( + window.document.head.innerHTML, + '' + ); + assert.htmlEqual( + component.div.innerHTML, + '
Hello World
' + ); + } +}; diff --git a/test/runtime/samples/target-dom-detached/main.svelte b/test/runtime/samples/target-dom-detached/main.svelte new file mode 100644 index 0000000000..42e7dffee9 --- /dev/null +++ b/test/runtime/samples/target-dom-detached/main.svelte @@ -0,0 +1,18 @@ + diff --git a/test/runtime/samples/target-dom/App.svelte b/test/runtime/samples/target-dom/App.svelte new file mode 100644 index 0000000000..251e480307 --- /dev/null +++ b/test/runtime/samples/target-dom/App.svelte @@ -0,0 +1,11 @@ + + +
Hello {name}
+ + \ No newline at end of file diff --git a/test/runtime/samples/target-dom/_config.js b/test/runtime/samples/target-dom/_config.js new file mode 100644 index 0000000000..b63656530c --- /dev/null +++ b/test/runtime/samples/target-dom/_config.js @@ -0,0 +1,16 @@ +export default { + skip_if_ssr: true, + compileOptions: { + cssHash: () => 'svelte-xyz' + }, + async test({ assert, component, target, window }) { + assert.htmlEqual( + window.document.head.innerHTML, + '' + ); + assert.htmlEqual( + component.div.innerHTML, + '
Hello World
' + ); + } +}; diff --git a/test/runtime/samples/target-dom/main.svelte b/test/runtime/samples/target-dom/main.svelte new file mode 100644 index 0000000000..68d2990552 --- /dev/null +++ b/test/runtime/samples/target-dom/main.svelte @@ -0,0 +1,18 @@ + + +
\ No newline at end of file diff --git a/test/runtime/samples/target-shadow-dom/App.svelte b/test/runtime/samples/target-shadow-dom/App.svelte new file mode 100644 index 0000000000..251e480307 --- /dev/null +++ b/test/runtime/samples/target-shadow-dom/App.svelte @@ -0,0 +1,11 @@ + + +
Hello {name}
+ + \ No newline at end of file diff --git a/test/runtime/samples/target-shadow-dom/_config.js b/test/runtime/samples/target-shadow-dom/_config.js new file mode 100644 index 0000000000..cec383afd0 --- /dev/null +++ b/test/runtime/samples/target-shadow-dom/_config.js @@ -0,0 +1,13 @@ +export default { + skip_if_ssr: true, + compileOptions: { + cssHash: () => 'svelte-xyz' + }, + async test({ assert, component, target, window }) { + assert.htmlEqual(window.document.head.innerHTML, ''); + assert.htmlEqual(component.div.shadowRoot.innerHTML, ` + +
Hello World
+ `); + } +}; diff --git a/test/runtime/samples/target-shadow-dom/main.svelte b/test/runtime/samples/target-shadow-dom/main.svelte new file mode 100644 index 0000000000..cb47ad01f0 --- /dev/null +++ b/test/runtime/samples/target-shadow-dom/main.svelte @@ -0,0 +1,19 @@ + + +
\ No newline at end of file diff --git a/test/runtime/samples/transition-css-in-out-in-with-param/_config.js b/test/runtime/samples/transition-css-in-out-in-with-param/_config.js new file mode 100644 index 0000000000..c5dfb63225 --- /dev/null +++ b/test/runtime/samples/transition-css-in-out-in-with-param/_config.js @@ -0,0 +1,21 @@ +export default { + test({ assert, component, target, window, raf }) { + component.visible = true; + const div = target.querySelector('div'); + + // animation duration of `in` should be 10ms. + assert.equal(div.style.animation, '__svelte_1670736059_0 10ms linear 0ms 1 both'); + + // animation duration of `out` should be 5ms. + component.visible = false; + assert.equal(div.style.animation, '__svelte_1670736059_0 10ms linear 0ms 1 both, __svelte_1998461463_0 5ms linear 0ms 1 both'); + + // change param + raf.tick(1); + component.param = true; + component.visible = true; + + // animation duration of `in` should be 20ms. + assert.equal(div.style.animation, '__svelte_722598827_0 20ms linear 0ms 1 both'); + } +}; diff --git a/test/runtime/samples/transition-css-in-out-in-with-param/main.svelte b/test/runtime/samples/transition-css-in-out-in-with-param/main.svelte new file mode 100644 index 0000000000..616e2e0e8b --- /dev/null +++ b/test/runtime/samples/transition-css-in-out-in-with-param/main.svelte @@ -0,0 +1,26 @@ + + +{#if visible} +
+{/if} \ No newline at end of file diff --git a/test/runtime/samples/transition-css-in-out-in/_config.js b/test/runtime/samples/transition-css-in-out-in/_config.js index cd7ae14ce8..6d93c0e8c3 100644 --- a/test/runtime/samples/transition-css-in-out-in/_config.js +++ b/test/runtime/samples/transition-css-in-out-in/_config.js @@ -15,6 +15,6 @@ export default { component.visible = true; // reset original styles - assert.equal(div.style.animation, '__svelte_3809512021_1 100ms linear 0ms 1 both'); + assert.equal(div.style.animation, '__svelte_3809512021_0 100ms linear 0ms 1 both'); } }; diff --git a/test/runtime/samples/transition-js-slot-2/_config.js b/test/runtime/samples/transition-js-slot-2/_config.js index 67cc0b46d2..0f0cad5e41 100644 --- a/test/runtime/samples/transition-js-slot-2/_config.js +++ b/test/runtime/samples/transition-js-slot-2/_config.js @@ -1,3 +1,4 @@ +// cancelled the transition halfway export default { html: `
Foo
diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte b/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte new file mode 100644 index 0000000000..04eea750fd --- /dev/null +++ b/test/runtime/samples/transition-js-slot-4-cancelled/Nested.svelte @@ -0,0 +1,19 @@ + + +{#if visible} +
+ +
+{/if} \ No newline at end of file diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/_config.js b/test/runtime/samples/transition-js-slot-4-cancelled/_config.js new file mode 100644 index 0000000000..d6b7c31132 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-4-cancelled/_config.js @@ -0,0 +1,35 @@ +// updated props in the middle of transitions +// and cancelled the transition halfway +export default { + html: ` +
outside Foo Foo Foo
+
inside Foo Foo Foo
+ `, + props: { + props: 'Foo' + }, + + async test({ assert, component, target, window, raf }) { + await component.hide(); + const [, div] = target.querySelectorAll('div'); + + raf.tick(50); + assert.equal(div.foo, 0.5); + + component.props = 'Bar'; + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Foo Foo Foo
+ `); + + await component.show(); + + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Bar Bar Bar
+ `); + + raf.tick(100); + assert.equal(div.foo, 1); + } +}; diff --git a/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte b/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte new file mode 100644 index 0000000000..1003419244 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-4-cancelled/main.svelte @@ -0,0 +1,22 @@ + + +
outside {state} {props} {slotProps}
+ + inside {state} {props} {slotProps} + diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte new file mode 100644 index 0000000000..10050b6a10 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/Nested.svelte @@ -0,0 +1,19 @@ + + +{#if visible} +
+ +
+{/if} diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js new file mode 100644 index 0000000000..aedc87f0b6 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/_config.js @@ -0,0 +1,40 @@ +// updated props in the middle of transitions +// and cancelled the transition halfway +// + spreaded props + overflow context + +export default { + html: ` +
outside Foo Foo Foo
+
inside Foo Foo Foo
+ 0 + `, + props: { + props: 'Foo' + }, + + async test({ assert, component, target, window, raf }) { + await component.hide(); + const [, div] = target.querySelectorAll('div'); + + raf.tick(50); + assert.equal(div.foo, 0.5); + + component.props = 'Bar'; + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Foo Foo Foo
+ 0 + `); + + await component.show(); + + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Bar Bar Bar
+ 0 + `); + + raf.tick(100); + assert.equal(div.foo, 1); + } +}; diff --git a/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte new file mode 100644 index 0000000000..9c46fd0521 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-5-cancelled-overflow/main.svelte @@ -0,0 +1,27 @@ + + +
outside {state} {props} {slotProps}
+ + + inside {state} {props} {slotProps} + + +{a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33} \ No newline at end of file diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte new file mode 100644 index 0000000000..b1853993d3 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested.svelte @@ -0,0 +1,19 @@ + + +{#if visible} +
+ +
+{/if} \ No newline at end of file diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte new file mode 100644 index 0000000000..52f89858a0 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/Nested2.svelte @@ -0,0 +1,19 @@ + + +{#if visible} +
+ +
+{/if} \ No newline at end of file diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js b/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js new file mode 100644 index 0000000000..1d42c9cf71 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/_config.js @@ -0,0 +1,40 @@ +// updated props in the middle of transitions +// and cancelled the transition halfway +// with spreaded props + +export default { + html: ` +
outside Foo Foo Foo
+
inside Foo Foo Foo
+
inside Foo Foo XXX
+ `, + props: { + props: 'Foo' + }, + + async test({ assert, component, target, window, raf }) { + await component.hide(); + const [, div] = target.querySelectorAll('div'); + + raf.tick(50); + assert.equal(div.foo, 0.5); + + component.props = 'Bar'; + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Foo Foo Foo
+
inside Foo Foo XXX
+ `); + + await component.show(); + + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Bar Bar Bar
+
inside Bar Bar XXX
+ `); + + raf.tick(100); + assert.equal(div.foo, 1); + } +}; diff --git a/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte b/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte new file mode 100644 index 0000000000..5dd8ce348e --- /dev/null +++ b/test/runtime/samples/transition-js-slot-6-spread-cancelled/main.svelte @@ -0,0 +1,26 @@ + + +
outside {state} {props} {slotProps.slotProps}
+ + inside {state} {props} {slotProps} + + + inside {state} {props} {slotProps} + diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte new file mode 100644 index 0000000000..b01200fd9f --- /dev/null +++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/Nested.svelte @@ -0,0 +1,19 @@ + + +{#if visible} +
+ +
+{/if} diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js new file mode 100644 index 0000000000..aedc87f0b6 --- /dev/null +++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/_config.js @@ -0,0 +1,40 @@ +// updated props in the middle of transitions +// and cancelled the transition halfway +// + spreaded props + overflow context + +export default { + html: ` +
outside Foo Foo Foo
+
inside Foo Foo Foo
+ 0 + `, + props: { + props: 'Foo' + }, + + async test({ assert, component, target, window, raf }) { + await component.hide(); + const [, div] = target.querySelectorAll('div'); + + raf.tick(50); + assert.equal(div.foo, 0.5); + + component.props = 'Bar'; + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Foo Foo Foo
+ 0 + `); + + await component.show(); + + assert.htmlEqual(target.innerHTML, ` +
outside Bar Bar Bar
+
inside Bar Bar Bar
+ 0 + `); + + raf.tick(100); + assert.equal(div.foo, 1); + } +}; diff --git a/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte new file mode 100644 index 0000000000..000b29ee7f --- /dev/null +++ b/test/runtime/samples/transition-js-slot-7-spread-cancelled-overflow/main.svelte @@ -0,0 +1,27 @@ + + +
outside {state} {props} {slotProps.slotProps}
+ + + inside {state} {props} {slotProps} + + +{a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33} \ No newline at end of file