feat: docker compose maybe
This commit is contained in:
6
node_modules/svelte/src/.eslintrc.json
generated
vendored
Normal file
6
node_modules/svelte/src/.eslintrc.json
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": ["lube"],
|
||||
"rules": {
|
||||
"lube/svelte-naming-convention": ["error", { "fixSameNames": true }]
|
||||
}
|
||||
}
|
83
node_modules/svelte/src/compiler/Stats.js
generated
vendored
Normal file
83
node_modules/svelte/src/compiler/Stats.js
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
const now = () => performance.now();
|
||||
|
||||
/** @param {any} timings */
|
||||
function collapse_timings(timings) {
|
||||
const result = {};
|
||||
timings.forEach((timing) => {
|
||||
result[timing.label] = Object.assign(
|
||||
{
|
||||
total: timing.end - timing.start
|
||||
},
|
||||
timing.children && collapse_timings(timing.children)
|
||||
);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export default class Stats {
|
||||
/**
|
||||
* @typedef {Object} Timing
|
||||
* @property {string} label
|
||||
* @property {number} start
|
||||
* @property {number} end
|
||||
* @property {Timing[]} children
|
||||
*/
|
||||
|
||||
/** @type {number} */
|
||||
start_time;
|
||||
|
||||
/** @type {Timing} */
|
||||
current_timing;
|
||||
|
||||
/** @type {Timing[]} */
|
||||
current_children;
|
||||
|
||||
/** @type {Timing[]} */
|
||||
timings;
|
||||
|
||||
/** @type {Timing[]} */
|
||||
stack;
|
||||
constructor() {
|
||||
this.start_time = now();
|
||||
this.stack = [];
|
||||
this.current_children = this.timings = [];
|
||||
}
|
||||
|
||||
/** @param {any} label */
|
||||
start(label) {
|
||||
const timing = {
|
||||
label,
|
||||
start: now(),
|
||||
end: null,
|
||||
children: []
|
||||
};
|
||||
this.current_children.push(timing);
|
||||
this.stack.push(timing);
|
||||
this.current_timing = timing;
|
||||
this.current_children = timing.children;
|
||||
}
|
||||
|
||||
/** @param {any} label */
|
||||
stop(label) {
|
||||
if (label !== this.current_timing.label) {
|
||||
throw new Error(
|
||||
`Mismatched timing labels (expected ${this.current_timing.label}, got ${label})`
|
||||
);
|
||||
}
|
||||
this.current_timing.end = now();
|
||||
this.stack.pop();
|
||||
this.current_timing = this.stack[this.stack.length - 1];
|
||||
this.current_children = this.current_timing ? this.current_timing.children : this.timings;
|
||||
}
|
||||
render() {
|
||||
const timings = Object.assign(
|
||||
{
|
||||
total: now() - this.start_time
|
||||
},
|
||||
collapse_timings(this.timings)
|
||||
);
|
||||
return {
|
||||
timings
|
||||
};
|
||||
}
|
||||
}
|
1877
node_modules/svelte/src/compiler/compile/Component.js
generated
vendored
Normal file
1877
node_modules/svelte/src/compiler/compile/Component.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
356
node_modules/svelte/src/compiler/compile/compiler_errors.js
generated
vendored
Normal file
356
node_modules/svelte/src/compiler/compile/compiler_errors.js
generated
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
// All compiler errors should be listed and accessed from here
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export default {
|
||||
invalid_binding_elements: /**
|
||||
* @param {string} element
|
||||
* @param {string} binding
|
||||
*/ (element, binding) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding on <${element}> elements`
|
||||
}),
|
||||
invalid_binding_element_with: /**
|
||||
* @param {string} elements
|
||||
* @param {string} binding
|
||||
*/ (elements, binding) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' binding can only be used with ${elements}`
|
||||
}),
|
||||
invalid_binding_on: /**
|
||||
* @param {string} binding
|
||||
* @param {string} element
|
||||
* @param {string} [post]
|
||||
*/ (binding, element, post) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding on ${element}` + (post || '')
|
||||
}),
|
||||
invalid_binding_foreign: /** @param {string} binding */ (binding) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding. Foreign elements only support bind:this`
|
||||
}),
|
||||
invalid_binding_no_checkbox: /**
|
||||
* @param {string} binding
|
||||
* @param {boolean} is_radio
|
||||
*/ (binding, is_radio) => ({
|
||||
code: 'invalid-binding',
|
||||
message:
|
||||
`'${binding}' binding can only be used with <input type="checkbox">` +
|
||||
(is_radio ? ' — for <input type="radio">, use \'group\' binding' : '')
|
||||
}),
|
||||
invalid_binding: /** @param {string} binding */ (binding) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding`
|
||||
}),
|
||||
invalid_binding_window: /** @param {string[]} parts */ (parts) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${
|
||||
parts[parts.length - 1]
|
||||
}' rather than '${parts.join('.')}'`
|
||||
}),
|
||||
invalid_binding_let: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable declared with the let: directive'
|
||||
},
|
||||
invalid_binding_await: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
|
||||
},
|
||||
invalid_binding_const: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable declared with {@const ...}'
|
||||
},
|
||||
invalid_binding_writable: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable which is not writable'
|
||||
},
|
||||
binding_undeclared: /** @param {string} name */ (name) => ({
|
||||
code: 'binding-undeclared',
|
||||
message: `${name} is not declared`
|
||||
}),
|
||||
invalid_type: {
|
||||
code: 'invalid-type',
|
||||
message: "'type' attribute cannot be dynamic if input uses two-way binding"
|
||||
},
|
||||
missing_type: {
|
||||
code: 'missing-type',
|
||||
message: "'type' attribute must be specified"
|
||||
},
|
||||
dynamic_multiple_attribute: {
|
||||
code: 'dynamic-multiple-attribute',
|
||||
message: "'multiple' attribute cannot be dynamic if select uses two-way binding"
|
||||
},
|
||||
missing_contenteditable_attribute: {
|
||||
code: 'missing-contenteditable-attribute',
|
||||
message:
|
||||
"'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings"
|
||||
},
|
||||
dynamic_contenteditable_attribute: {
|
||||
code: 'dynamic-contenteditable-attribute',
|
||||
message: "'contenteditable' attribute cannot be dynamic if element uses two-way binding"
|
||||
},
|
||||
invalid_event_modifier_combination: /**
|
||||
* @param {string} modifier1
|
||||
* @param {string} modifier2
|
||||
*/ (modifier1, modifier2) => ({
|
||||
code: 'invalid-event-modifier',
|
||||
message: `The '${modifier1}' and '${modifier2}' modifiers cannot be used together`
|
||||
}),
|
||||
invalid_event_modifier_legacy: /** @param {string} modifier */ (modifier) => ({
|
||||
code: 'invalid-event-modifier',
|
||||
message: `The '${modifier}' modifier cannot be used in legacy mode`
|
||||
}),
|
||||
invalid_event_modifier: /** @param {string} valid */ (valid) => ({
|
||||
code: 'invalid-event-modifier',
|
||||
message: `Valid event modifiers are ${valid}`
|
||||
}),
|
||||
invalid_event_modifier_component: {
|
||||
code: 'invalid-event-modifier',
|
||||
message: "Event modifiers other than 'once' can only be used on DOM elements"
|
||||
},
|
||||
textarea_duplicate_value: {
|
||||
code: 'textarea-duplicate-value',
|
||||
message:
|
||||
'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
|
||||
},
|
||||
illegal_attribute: /** @param {string} name */ (name) => ({
|
||||
code: 'illegal-attribute',
|
||||
message: `'${name}' is not a valid attribute name`
|
||||
}),
|
||||
invalid_slot_attribute: {
|
||||
code: 'invalid-slot-attribute',
|
||||
message: 'slot attribute cannot have a dynamic value'
|
||||
},
|
||||
duplicate_slot_attribute: /** @param {string} name */ (name) => ({
|
||||
code: 'duplicate-slot-attribute',
|
||||
message: `Duplicate '${name}' slot`
|
||||
}),
|
||||
invalid_slotted_content: {
|
||||
code: 'invalid-slotted-content',
|
||||
message:
|
||||
"Element with a slot='...' attribute must be a child of a component or a descendant of a custom element"
|
||||
},
|
||||
invalid_attribute_head: {
|
||||
code: 'invalid-attribute',
|
||||
message: '<svelte:head> should not have any attributes or directives'
|
||||
},
|
||||
invalid_action: {
|
||||
code: 'invalid-action',
|
||||
message: 'Actions can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_animation: {
|
||||
code: 'invalid-animation',
|
||||
message: 'Animations can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_class: {
|
||||
code: 'invalid-class',
|
||||
message: 'Classes can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_transition: {
|
||||
code: 'invalid-transition',
|
||||
message: 'Transitions can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_let: {
|
||||
code: 'invalid-let',
|
||||
message: 'let directive value must be an identifier or an object/array pattern'
|
||||
},
|
||||
invalid_slot_directive: {
|
||||
code: 'invalid-slot-directive',
|
||||
message: '<slot> cannot have directives'
|
||||
},
|
||||
dynamic_slot_name: {
|
||||
code: 'dynamic-slot-name',
|
||||
message: '<slot> name cannot be dynamic'
|
||||
},
|
||||
invalid_slot_name: {
|
||||
code: 'invalid-slot-name',
|
||||
message: 'default is a reserved word — it cannot be used as a slot name'
|
||||
},
|
||||
invalid_slot_attribute_value_missing: {
|
||||
code: 'invalid-slot-attribute',
|
||||
message: 'slot attribute value is missing'
|
||||
},
|
||||
invalid_slotted_content_fragment: {
|
||||
code: 'invalid-slotted-content',
|
||||
message: '<svelte:fragment> must be a child of a component'
|
||||
},
|
||||
illegal_attribute_title: {
|
||||
code: 'illegal-attribute',
|
||||
message: '<title> cannot have attributes'
|
||||
},
|
||||
illegal_structure_title: {
|
||||
code: 'illegal-structure',
|
||||
message: '<title> can only contain text and {tags}'
|
||||
},
|
||||
duplicate_transition: /**
|
||||
* @param {string} directive
|
||||
* @param {string} parent_directive
|
||||
*/ (directive, parent_directive) => {
|
||||
/** @param {string} _directive */
|
||||
function describe(_directive) {
|
||||
return _directive === 'transition' ? "a 'transition'" : `an '${_directive}'`;
|
||||
}
|
||||
const message =
|
||||
directive === parent_directive
|
||||
? `An element can only have one '${directive}' directive`
|
||||
: `An element cannot have both ${describe(parent_directive)} directive and ${describe(
|
||||
directive
|
||||
)} directive`;
|
||||
return {
|
||||
code: 'duplicate-transition',
|
||||
message
|
||||
};
|
||||
},
|
||||
contextual_store: {
|
||||
code: 'contextual-store',
|
||||
message:
|
||||
'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
|
||||
},
|
||||
default_export: {
|
||||
code: 'default-export',
|
||||
message: 'A component cannot have a default export'
|
||||
},
|
||||
illegal_declaration: {
|
||||
code: 'illegal-declaration',
|
||||
message: 'The $ prefix is reserved, and cannot be used for variable and import names'
|
||||
},
|
||||
illegal_subscription: {
|
||||
code: 'illegal-subscription',
|
||||
message: 'Cannot reference store value inside <script context="module">'
|
||||
},
|
||||
illegal_global: /** @param {string} name */ (name) => ({
|
||||
code: 'illegal-global',
|
||||
message: `${name} is an illegal variable name`
|
||||
}),
|
||||
illegal_variable_declaration: {
|
||||
code: 'illegal-variable-declaration',
|
||||
message: 'Cannot declare same variable name which is imported inside <script context="module">'
|
||||
},
|
||||
cyclical_reactive_declaration: /** @param {string[]} cycle */ (cycle) => ({
|
||||
code: 'cyclical-reactive-declaration',
|
||||
message: `Cyclical dependency detected: ${cycle.join(' → ')}`
|
||||
}),
|
||||
invalid_tag_property: {
|
||||
code: 'invalid-tag-property',
|
||||
message: "tag name must be two or more words joined by the '-' character"
|
||||
},
|
||||
invalid_customElement_attribute: {
|
||||
code: 'invalid-customElement-attribute',
|
||||
message:
|
||||
"'customElement' must be a string literal defining a valid custom element name or an object of the form " +
|
||||
"{ tag: string; shadow?: 'open' | 'none'; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }"
|
||||
},
|
||||
invalid_tag_attribute: {
|
||||
code: 'invalid-tag-attribute',
|
||||
message: "'tag' must be a string literal"
|
||||
},
|
||||
invalid_shadow_attribute: {
|
||||
code: 'invalid-shadow-attribute',
|
||||
message: "'shadow' must be either 'open' or 'none'"
|
||||
},
|
||||
invalid_props_attribute: {
|
||||
code: 'invalid-props-attribute',
|
||||
message:
|
||||
"'props' must be a statically analyzable object literal of the form " +
|
||||
"'{ [key: string]: { attribute?: string; reflect?: boolean; type?: 'String' | 'Boolean' | 'Number' | 'Array' | 'Object' }'"
|
||||
},
|
||||
invalid_namespace_property: /**
|
||||
* @param {string} namespace
|
||||
* @param {string} [suggestion]
|
||||
*/ (namespace, suggestion) => ({
|
||||
code: 'invalid-namespace-property',
|
||||
message:
|
||||
`Invalid namespace '${namespace}'` + (suggestion ? ` (did you mean '${suggestion}'?)` : '')
|
||||
}),
|
||||
invalid_namespace_attribute: {
|
||||
code: 'invalid-namespace-attribute',
|
||||
message: "The 'namespace' attribute must be a string literal representing a valid namespace"
|
||||
},
|
||||
invalid_attribute_value: /** @param {string} name */ (name) => ({
|
||||
code: `invalid-${name}-value`,
|
||||
message: `${name} attribute must be true or false`
|
||||
}),
|
||||
invalid_options_attribute_unknown: /** @param {string} name */ (name) => ({
|
||||
code: 'invalid-options-attribute',
|
||||
message: `<svelte:options> unknown attribute '${name}'`
|
||||
}),
|
||||
invalid_options_attribute: {
|
||||
code: 'invalid-options-attribute',
|
||||
message:
|
||||
"<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
|
||||
},
|
||||
css_invalid_global: {
|
||||
code: 'css-invalid-global',
|
||||
message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
|
||||
},
|
||||
css_invalid_global_selector: {
|
||||
code: 'css-invalid-global-selector',
|
||||
message: ':global(...) must contain a single selector'
|
||||
},
|
||||
css_invalid_global_selector_position: {
|
||||
code: 'css-invalid-global-selector-position',
|
||||
message:
|
||||
':global(...) not at the start of a selector sequence should not contain type or universal selectors'
|
||||
},
|
||||
css_invalid_selector: /** @param {string} selector */ (selector) => ({
|
||||
code: 'css-invalid-selector',
|
||||
message: `Invalid selector "${selector}"`
|
||||
}),
|
||||
duplicate_animation: {
|
||||
code: 'duplicate-animation',
|
||||
message: "An element can only have one 'animate' directive"
|
||||
},
|
||||
invalid_animation_immediate: {
|
||||
code: 'invalid-animation',
|
||||
message:
|
||||
'An element that uses the animate directive must be the immediate child of a keyed each block'
|
||||
},
|
||||
invalid_animation_key: {
|
||||
code: 'invalid-animation',
|
||||
message:
|
||||
'An element that uses the animate directive must be used inside a keyed each block. Did you forget to add a key to your each block?'
|
||||
},
|
||||
invalid_animation_sole: {
|
||||
code: 'invalid-animation',
|
||||
message:
|
||||
'An element that uses the animate directive must be the sole child of a keyed each block'
|
||||
},
|
||||
invalid_animation_dynamic_element: {
|
||||
code: 'invalid-animation',
|
||||
message: '<svelte:element> cannot have a animate directive'
|
||||
},
|
||||
invalid_directive_value: {
|
||||
code: 'invalid-directive-value',
|
||||
message:
|
||||
'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
|
||||
},
|
||||
invalid_const_placement: {
|
||||
code: 'invalid-const-placement',
|
||||
message:
|
||||
'{@const} must be the immediate child of {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>'
|
||||
},
|
||||
invalid_const_declaration: /** @param {string} name */ (name) => ({
|
||||
code: 'invalid-const-declaration',
|
||||
message: `'${name}' has already been declared`
|
||||
}),
|
||||
invalid_const_update: /** @param {string} name */ (name) => ({
|
||||
code: 'invalid-const-update',
|
||||
message: `'${name}' is declared using {@const ...} and is read-only`
|
||||
}),
|
||||
cyclical_const_tags: /** @param {string[]} cycle */ (cycle) => ({
|
||||
code: 'cyclical-const-tags',
|
||||
message: `Cyclical dependency detected: ${cycle.join(' → ')}`
|
||||
}),
|
||||
invalid_component_style_directive: {
|
||||
code: 'invalid-component-style-directive',
|
||||
message: 'Style directives cannot be used on components'
|
||||
},
|
||||
invalid_var_declaration: {
|
||||
code: 'invalid_var_declaration',
|
||||
message: '"var" scope should not extend outside the reactive block'
|
||||
},
|
||||
invalid_style_directive_modifier: /** @param {string} valid */ (valid) => ({
|
||||
code: 'invalid-style-directive-modifier',
|
||||
message: `Valid modifiers for style directives are: ${valid}`
|
||||
})
|
||||
};
|
310
node_modules/svelte/src/compiler/compile/compiler_warnings.js
generated
vendored
Normal file
310
node_modules/svelte/src/compiler/compile/compiler_warnings.js
generated
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export default {
|
||||
tag_option_deprecated: {
|
||||
code: 'tag-option-deprecated',
|
||||
message: "'tag' option is deprecated — use 'customElement' instead"
|
||||
},
|
||||
unused_export_let: /**
|
||||
* @param {string} component
|
||||
* @param {string} property
|
||||
*/ (component, property) => ({
|
||||
code: 'unused-export-let',
|
||||
message: `${component} has unused export property '${property}'. If it is for external reference only, please consider using \`export const ${property}\``
|
||||
}),
|
||||
module_script_reactive_declaration: {
|
||||
code: 'module-script-reactive-declaration',
|
||||
message: '$: has no effect in a module script'
|
||||
},
|
||||
non_top_level_reactive_declaration: {
|
||||
code: 'non-top-level-reactive-declaration',
|
||||
message: '$: has no effect outside of the top-level'
|
||||
},
|
||||
module_script_variable_reactive_declaration: /** @param {string[]} names */ (names) => ({
|
||||
code: 'module-script-reactive-declaration',
|
||||
message: `${names.map((name) => `"${name}"`).join(', ')} ${
|
||||
names.length > 1 ? 'are' : 'is'
|
||||
} declared in a module script and will not be reactive`
|
||||
}),
|
||||
missing_declaration: /**
|
||||
* @param {string} name
|
||||
* @param {boolean} has_script
|
||||
*/ (name, has_script) => ({
|
||||
code: 'missing-declaration',
|
||||
message:
|
||||
`'${name}' is not defined` +
|
||||
(has_script
|
||||
? ''
|
||||
: `. Consider adding a <script> block with 'export let ${name}' to declare a prop`)
|
||||
}),
|
||||
missing_custom_element_compile_options: {
|
||||
code: 'missing-custom-element-compile-options',
|
||||
message:
|
||||
"The 'customElement' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
|
||||
},
|
||||
css_unused_selector: /** @param {string} selector */ (selector) => ({
|
||||
code: 'css-unused-selector',
|
||||
message: `Unused CSS selector "${selector}"`
|
||||
}),
|
||||
empty_block: {
|
||||
code: 'empty-block',
|
||||
message: 'Empty block'
|
||||
},
|
||||
reactive_component: /** @param {string} name */ (name) => ({
|
||||
code: 'reactive-component',
|
||||
message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
|
||||
}),
|
||||
component_name_lowercase: /** @param {string} name */ (name) => ({
|
||||
code: 'component-name-lowercase',
|
||||
message: `<${name}> will be treated as an HTML element unless it begins with a capital letter`
|
||||
}),
|
||||
avoid_is: {
|
||||
code: 'avoid-is',
|
||||
message: "The 'is' attribute is not supported cross-browser and should be avoided"
|
||||
},
|
||||
invalid_html_attribute: /**
|
||||
* @param {string} name
|
||||
* @param {string} suggestion
|
||||
*/ (name, suggestion) => ({
|
||||
code: 'invalid-html-attribute',
|
||||
message: `'${name}' is not a valid HTML attribute. Did you mean '${suggestion}'?`
|
||||
}),
|
||||
a11y_aria_attributes: /** @param {string} name */ (name) => ({
|
||||
code: 'a11y-aria-attributes',
|
||||
message: `A11y: <${name}> should not have aria-* attributes`
|
||||
}),
|
||||
a11y_incorrect_attribute_type: /**
|
||||
* @param {import('aria-query').ARIAPropertyDefinition} schema
|
||||
* @param {string} attribute
|
||||
*/ (schema, attribute) => {
|
||||
let message;
|
||||
switch (schema.type) {
|
||||
case 'boolean':
|
||||
message = `The value of '${attribute}' must be exactly one of true or false`;
|
||||
break;
|
||||
case 'id':
|
||||
message = `The value of '${attribute}' must be a string that represents a DOM element ID`;
|
||||
break;
|
||||
case 'idlist':
|
||||
message = `The value of '${attribute}' must be a space-separated list of strings that represent DOM element IDs`;
|
||||
break;
|
||||
case 'tristate':
|
||||
message = `The value of '${attribute}' must be exactly one of true, false, or mixed`;
|
||||
break;
|
||||
case 'token':
|
||||
message = `The value of '${attribute}' must be exactly one of ${(schema.values || []).join(
|
||||
', '
|
||||
)}`;
|
||||
break;
|
||||
case 'tokenlist':
|
||||
message = `The value of '${attribute}' must be a space-separated list of one or more of ${(
|
||||
schema.values || []
|
||||
).join(', ')}`;
|
||||
break;
|
||||
default:
|
||||
message = `The value of '${attribute}' must be of type ${schema.type}`;
|
||||
}
|
||||
return {
|
||||
code: 'a11y-incorrect-aria-attribute-type',
|
||||
message: `A11y: ${message}`
|
||||
};
|
||||
},
|
||||
a11y_unknown_aria_attribute: /**
|
||||
* @param {string} attribute
|
||||
* @param {string} [suggestion]
|
||||
*/ (attribute, suggestion) => ({
|
||||
code: 'a11y-unknown-aria-attribute',
|
||||
message:
|
||||
`A11y: Unknown aria attribute 'aria-${attribute}'` +
|
||||
(suggestion ? ` (did you mean '${suggestion}'?)` : '')
|
||||
}),
|
||||
a11y_hidden: /** @param {string} name */ (name) => ({
|
||||
code: 'a11y-hidden',
|
||||
message: `A11y: <${name}> element should not be hidden`
|
||||
}),
|
||||
a11y_misplaced_role: /** @param {string} name */ (name) => ({
|
||||
code: 'a11y-misplaced-role',
|
||||
message: `A11y: <${name}> should not have role attribute`
|
||||
}),
|
||||
a11y_unknown_role: /**
|
||||
* @param {string | boolean} role
|
||||
* @param {string} [suggestion]
|
||||
*/ (role, suggestion) => ({
|
||||
code: 'a11y-unknown-role',
|
||||
message: `A11y: Unknown role '${role}'` + (suggestion ? ` (did you mean '${suggestion}'?)` : '')
|
||||
}),
|
||||
a11y_no_abstract_role: /** @param {string | boolean} role */ (role) => ({
|
||||
code: 'a11y-no-abstract-role',
|
||||
message: `A11y: Abstract role '${role}' is forbidden`
|
||||
}),
|
||||
a11y_no_redundant_roles: /** @param {string | boolean} role */ (role) => ({
|
||||
code: 'a11y-no-redundant-roles',
|
||||
message: `A11y: Redundant role '${role}'`
|
||||
}),
|
||||
a11y_no_static_element_interactions: /**
|
||||
* @param {string} element
|
||||
* @param {string[]} handlers
|
||||
*/ (element, handlers) => ({
|
||||
code: 'a11y-no-static-element-interactions',
|
||||
message: `A11y: <${element}> with ${handlers.join(', ')} ${
|
||||
handlers.length === 1 ? 'handler' : 'handlers'
|
||||
} must have an ARIA role`
|
||||
}),
|
||||
a11y_no_interactive_element_to_noninteractive_role: /**
|
||||
* @param {string | boolean} role
|
||||
* @param {string} element
|
||||
*/ (role, element) => ({
|
||||
code: 'a11y-no-interactive-element-to-noninteractive-role',
|
||||
message: `A11y: <${element}> cannot have role '${role}'`
|
||||
}),
|
||||
a11y_no_noninteractive_element_interactions: /** @param {string} element */ (element) => ({
|
||||
code: 'a11y-no-noninteractive-element-interactions',
|
||||
message: `A11y: Non-interactive element <${element}> should not be assigned mouse or keyboard event listeners.`
|
||||
}),
|
||||
a11y_no_noninteractive_element_to_interactive_role: /**
|
||||
* @param {string | boolean} role
|
||||
* @param {string} element
|
||||
*/ (role, element) => ({
|
||||
code: 'a11y-no-noninteractive-element-to-interactive-role',
|
||||
message: `A11y: Non-interactive element <${element}> cannot have interactive role '${role}'`
|
||||
}),
|
||||
a11y_role_has_required_aria_props: /**
|
||||
* @param {string} role
|
||||
* @param {string[]} props
|
||||
*/ (role, props) => ({
|
||||
code: 'a11y-role-has-required-aria-props',
|
||||
message: `A11y: Elements with the ARIA role "${role}" must have the following attributes defined: ${props
|
||||
.map((name) => `"${name}"`)
|
||||
.join(', ')}`
|
||||
}),
|
||||
a11y_role_supports_aria_props: /**
|
||||
* @param {string} attribute
|
||||
* @param {string} role
|
||||
* @param {boolean} is_implicit
|
||||
* @param {string} name
|
||||
*/ (attribute, role, is_implicit, name) => {
|
||||
let message = `The attribute '${attribute}' is not supported by the role '${role}'.`;
|
||||
if (is_implicit) {
|
||||
message += ` This role is implicit on the element <${name}>.`;
|
||||
}
|
||||
return {
|
||||
code: 'a11y-role-supports-aria-props',
|
||||
message: `A11y: ${message}`
|
||||
};
|
||||
},
|
||||
a11y_accesskey: {
|
||||
code: 'a11y-accesskey',
|
||||
message: 'A11y: Avoid using accesskey'
|
||||
},
|
||||
a11y_autofocus: {
|
||||
code: 'a11y-autofocus',
|
||||
message: 'A11y: Avoid using autofocus'
|
||||
},
|
||||
a11y_misplaced_scope: {
|
||||
code: 'a11y-misplaced-scope',
|
||||
message: 'A11y: The scope attribute should only be used with <th> elements'
|
||||
},
|
||||
a11y_positive_tabindex: {
|
||||
code: 'a11y-positive-tabindex',
|
||||
message: 'A11y: avoid tabindex values above zero'
|
||||
},
|
||||
a11y_invalid_attribute: /**
|
||||
* @param {string} href_attribute
|
||||
* @param {string} href_value
|
||||
*/ (href_attribute, href_value) => ({
|
||||
code: 'a11y-invalid-attribute',
|
||||
message: `A11y: '${href_value}' is not a valid ${href_attribute} attribute`
|
||||
}),
|
||||
a11y_missing_attribute: /**
|
||||
* @param {string} name
|
||||
* @param {string} article
|
||||
* @param {string} sequence
|
||||
*/ (name, article, sequence) => ({
|
||||
code: 'a11y-missing-attribute',
|
||||
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
|
||||
}),
|
||||
a11y_autocomplete_valid: /**
|
||||
* @param {null | true | string} type
|
||||
* @param {null | true | string} value
|
||||
*/ (type, value) => ({
|
||||
code: 'a11y-autocomplete-valid',
|
||||
message: `A11y: The value '${value}' is not supported by the attribute 'autocomplete' on element <input type="${
|
||||
type || '...'
|
||||
}">`
|
||||
}),
|
||||
a11y_img_redundant_alt: {
|
||||
code: 'a11y-img-redundant-alt',
|
||||
message: 'A11y: Screenreaders already announce <img> elements as an image.'
|
||||
},
|
||||
a11y_interactive_supports_focus: /** @param {string} role */ (role) => ({
|
||||
code: 'a11y-interactive-supports-focus',
|
||||
message: `A11y: Elements with the '${role}' interactive role must have a tabindex value.`
|
||||
}),
|
||||
a11y_label_has_associated_control: {
|
||||
code: 'a11y-label-has-associated-control',
|
||||
message: 'A11y: A form label must be associated with a control.'
|
||||
},
|
||||
a11y_media_has_caption: {
|
||||
code: 'a11y-media-has-caption',
|
||||
message: 'A11y: <video> elements must have a <track kind="captions">'
|
||||
},
|
||||
a11y_distracting_elements: /** @param {string} name */ (name) => ({
|
||||
code: 'a11y-distracting-elements',
|
||||
message: `A11y: Avoid <${name}> elements`
|
||||
}),
|
||||
a11y_structure_immediate: {
|
||||
code: 'a11y-structure',
|
||||
message: 'A11y: <figcaption> must be an immediate child of <figure>'
|
||||
},
|
||||
a11y_structure_first_or_last: {
|
||||
code: 'a11y-structure',
|
||||
message: 'A11y: <figcaption> must be first or last child of <figure>'
|
||||
},
|
||||
a11y_mouse_events_have_key_events: /**
|
||||
* @param {string} event
|
||||
* @param {string} accompanied_by
|
||||
*/ (event, accompanied_by) => ({
|
||||
code: 'a11y-mouse-events-have-key-events',
|
||||
message: `A11y: on:${event} must be accompanied by on:${accompanied_by}`
|
||||
}),
|
||||
a11y_click_events_have_key_events: {
|
||||
code: 'a11y-click-events-have-key-events',
|
||||
message:
|
||||
'A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as <button type="button"> or <a> might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details.'
|
||||
},
|
||||
a11y_missing_content: /** @param {string} name */ (name) => ({
|
||||
code: 'a11y-missing-content',
|
||||
message: `A11y: <${name}> element should have child content`
|
||||
}),
|
||||
a11y_no_noninteractive_tabindex: {
|
||||
code: 'a11y-no-noninteractive-tabindex',
|
||||
message: 'A11y: noninteractive element cannot have nonnegative tabIndex value'
|
||||
},
|
||||
a11y_aria_activedescendant_has_tabindex: {
|
||||
code: 'a11y-aria-activedescendant-has-tabindex',
|
||||
message: 'A11y: Elements with attribute aria-activedescendant should have tabindex value'
|
||||
},
|
||||
redundant_event_modifier_for_touch: {
|
||||
code: 'redundant-event-modifier',
|
||||
message: "Touch event handlers that don't use the 'event' object are passive by default"
|
||||
},
|
||||
redundant_event_modifier_passive: {
|
||||
code: 'redundant-event-modifier',
|
||||
message: 'The passive modifier only works with wheel and touch events'
|
||||
},
|
||||
invalid_rest_eachblock_binding: /** @param {string} rest_element_name */ (rest_element_name) => ({
|
||||
code: 'invalid-rest-eachblock-binding',
|
||||
message: `The rest operator (...) will create a new object and binding '${rest_element_name}' with the original object will not work`
|
||||
}),
|
||||
avoid_mouse_events_on_document: {
|
||||
code: 'avoid-mouse-events-on-document',
|
||||
message:
|
||||
'Mouse enter/leave events on the document are not supported in all browsers and should be avoided'
|
||||
},
|
||||
illegal_attribute_character: {
|
||||
code: 'illegal-attribute-character',
|
||||
message:
|
||||
"Attributes should not contain ':' characters to prevent ambiguity with Svelte directives"
|
||||
}
|
||||
};
|
156
node_modules/svelte/src/compiler/compile/create_module.js
generated
vendored
Normal file
156
node_modules/svelte/src/compiler/compile/create_module.js
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
import { b } from 'code-red';
|
||||
|
||||
/**
|
||||
* @param {any} program
|
||||
* @param {import('estree').Identifier} name
|
||||
* @param {string} banner
|
||||
* @param {any} svelte_path
|
||||
* @param {Array<{ name: string; alias: import('estree').Identifier }>} helpers
|
||||
* @param {Array<{ name: string; alias: import('estree').Identifier }>} globals
|
||||
* @param {import('estree').ImportDeclaration[]} imports
|
||||
* @param {Export[]} module_exports
|
||||
* @param {import('estree').ExportNamedDeclaration[]} exports_from
|
||||
*/
|
||||
export default function create_module(
|
||||
program,
|
||||
name,
|
||||
banner,
|
||||
svelte_path = 'svelte',
|
||||
helpers,
|
||||
globals,
|
||||
imports,
|
||||
module_exports,
|
||||
exports_from
|
||||
) {
|
||||
const internal_path = `${svelte_path}/internal`;
|
||||
helpers.sort((a, b) => (a.name < b.name ? -1 : 1));
|
||||
globals.sort((a, b) => (a.name < b.name ? -1 : 1));
|
||||
return esm(
|
||||
program,
|
||||
name,
|
||||
banner,
|
||||
svelte_path,
|
||||
internal_path,
|
||||
helpers,
|
||||
globals,
|
||||
imports,
|
||||
module_exports,
|
||||
exports_from
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} source
|
||||
* @param {any} svelte_path
|
||||
*/
|
||||
function edit_source(source, svelte_path) {
|
||||
return source === 'svelte' || source.startsWith('svelte/')
|
||||
? source.replace('svelte', svelte_path)
|
||||
: source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<{ name: string; alias: import('estree').Identifier }>} globals
|
||||
* @param {Array<{ name: string; alias: import('estree').Identifier }>} helpers
|
||||
*/
|
||||
function get_internal_globals(globals, helpers) {
|
||||
return (
|
||||
globals.length > 0 && {
|
||||
type: 'VariableDeclaration',
|
||||
kind: 'const',
|
||||
declarations: [
|
||||
{
|
||||
type: 'VariableDeclarator',
|
||||
id: {
|
||||
type: 'ObjectPattern',
|
||||
properties: globals.map((g) => ({
|
||||
type: 'Property',
|
||||
method: false,
|
||||
shorthand: false,
|
||||
computed: false,
|
||||
key: { type: 'Identifier', name: g.name },
|
||||
value: g.alias,
|
||||
kind: 'init'
|
||||
}))
|
||||
},
|
||||
init: helpers.find(({ name }) => name === 'globals').alias
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} program
|
||||
* @param {import('estree').Identifier} name
|
||||
* @param {string} banner
|
||||
* @param {string} svelte_path
|
||||
* @param {string} internal_path
|
||||
* @param {Array<{ name: string; alias: import('estree').Identifier }>} helpers
|
||||
* @param {Array<{ name: string; alias: import('estree').Identifier }>} globals
|
||||
* @param {import('estree').ImportDeclaration[]} imports
|
||||
* @param {Export[]} module_exports
|
||||
* @param {import('estree').ExportNamedDeclaration[]} exports_from
|
||||
*/
|
||||
function esm(
|
||||
program,
|
||||
name,
|
||||
banner,
|
||||
svelte_path,
|
||||
internal_path,
|
||||
helpers,
|
||||
globals,
|
||||
imports,
|
||||
module_exports,
|
||||
exports_from
|
||||
) {
|
||||
const import_declaration = {
|
||||
type: 'ImportDeclaration',
|
||||
specifiers: helpers.map((h) => ({
|
||||
type: 'ImportSpecifier',
|
||||
local: h.alias,
|
||||
imported: { type: 'Identifier', name: h.name }
|
||||
})),
|
||||
source: { type: 'Literal', value: internal_path }
|
||||
};
|
||||
const internal_globals = get_internal_globals(globals, helpers);
|
||||
// edit user imports
|
||||
|
||||
/** @param {any} node */
|
||||
function rewrite_import(node) {
|
||||
const value = edit_source(node.source.value, svelte_path);
|
||||
if (node.source.value !== value) {
|
||||
node.source.value = value;
|
||||
node.source.raw = null;
|
||||
}
|
||||
}
|
||||
imports.forEach(rewrite_import);
|
||||
exports_from.forEach(rewrite_import);
|
||||
const exports = module_exports.length > 0 && {
|
||||
type: 'ExportNamedDeclaration',
|
||||
specifiers: module_exports.map((x) => ({
|
||||
type: 'Specifier',
|
||||
local: { type: 'Identifier', name: x.name },
|
||||
exported: { type: 'Identifier', name: x.as }
|
||||
}))
|
||||
};
|
||||
program.body = b`
|
||||
/* ${banner} */
|
||||
|
||||
${import_declaration}
|
||||
${internal_globals}
|
||||
${imports}
|
||||
${exports_from}
|
||||
|
||||
${program.body}
|
||||
|
||||
export default ${name};
|
||||
${exports}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Export
|
||||
* @property {string} name
|
||||
* @property {string} as
|
||||
*/
|
833
node_modules/svelte/src/compiler/compile/css/Selector.js
generated
vendored
Normal file
833
node_modules/svelte/src/compiler/compile/css/Selector.js
generated
vendored
Normal file
@ -0,0 +1,833 @@
|
||||
import { gather_possible_values, UNKNOWN } from './gather_possible_values.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import { regex_starts_with_whitespace, regex_ends_with_whitespace } from '../../utils/patterns.js';
|
||||
|
||||
const BlockAppliesToNode = /** @type {const} */ ({
|
||||
NotPossible: 0,
|
||||
Possible: 1,
|
||||
UnknownSelectorType: 2
|
||||
});
|
||||
|
||||
const NodeExist = /** @type {const} */ ({
|
||||
Probably: 0,
|
||||
Definitely: 1
|
||||
});
|
||||
|
||||
/** @typedef {typeof NodeExist[keyof typeof NodeExist]} NodeExistsValue */
|
||||
|
||||
const whitelist_attribute_selector = new Map([
|
||||
['details', new Set(['open'])],
|
||||
['dialog', new Set(['open'])]
|
||||
]);
|
||||
const regex_is_single_css_selector = /[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/;
|
||||
|
||||
export default class Selector {
|
||||
/** @type {import('./private.js').CssNode} */
|
||||
node;
|
||||
|
||||
/** @type {import('./Stylesheet.js').default} */
|
||||
stylesheet;
|
||||
|
||||
/** @type {Block[]} */
|
||||
blocks;
|
||||
|
||||
/** @type {Block[]} */
|
||||
local_blocks;
|
||||
|
||||
/** @type {boolean} */
|
||||
used;
|
||||
|
||||
/**
|
||||
* @param {import('./private.js').CssNode} node
|
||||
* @param {import('./Stylesheet.js').default} stylesheet
|
||||
*/
|
||||
constructor(node, stylesheet) {
|
||||
this.node = node;
|
||||
this.stylesheet = stylesheet;
|
||||
this.blocks = group_selectors(node);
|
||||
// take trailing :global(...) selectors out of consideration
|
||||
let i = this.blocks.length;
|
||||
while (i > 0) {
|
||||
if (!this.blocks[i - 1].global) break;
|
||||
i -= 1;
|
||||
}
|
||||
this.local_blocks = this.blocks.slice(0, i);
|
||||
const host_only = this.blocks.length === 1 && this.blocks[0].host;
|
||||
const root_only = this.blocks.length === 1 && this.blocks[0].root;
|
||||
this.used = this.local_blocks.length === 0 || host_only || root_only;
|
||||
}
|
||||
|
||||
/** @param {import('../nodes/Element.js').default} node */
|
||||
apply(node) {
|
||||
/** @type {Array<{ node: import('../nodes/Element.js').default; block: Block }>} */
|
||||
const to_encapsulate = [];
|
||||
apply_selector(this.local_blocks.slice(), node, to_encapsulate);
|
||||
if (to_encapsulate.length > 0) {
|
||||
to_encapsulate.forEach(({ node, block }) => {
|
||||
this.stylesheet.nodes_with_css_class.add(node);
|
||||
block.should_encapsulate = true;
|
||||
});
|
||||
this.used = true;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('magic-string').default} code */
|
||||
minify(code) {
|
||||
/** @type {number} */
|
||||
let c = null;
|
||||
this.blocks.forEach((block, i) => {
|
||||
if (i > 0) {
|
||||
if (block.start - c > 1) {
|
||||
code.update(c, block.start, block.combinator.name || ' ');
|
||||
}
|
||||
}
|
||||
c = block.end;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {string} attr
|
||||
* @param {number} max_amount_class_specificity_increased
|
||||
*/
|
||||
transform(code, attr, max_amount_class_specificity_increased) {
|
||||
const amount_class_specificity_to_increase =
|
||||
max_amount_class_specificity_increased -
|
||||
this.blocks.filter((block) => block.should_encapsulate).length;
|
||||
|
||||
/** @param {import('./private.js').CssNode} selector */
|
||||
function remove_global_pseudo_class(selector) {
|
||||
const first = selector.children[0];
|
||||
const last = selector.children[selector.children.length - 1];
|
||||
code.remove(selector.start, first.start).remove(last.end, selector.end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Block} block
|
||||
* @param {string} attr
|
||||
*/
|
||||
function encapsulate_block(block, attr) {
|
||||
for (const selector of block.selectors) {
|
||||
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
|
||||
remove_global_pseudo_class(selector);
|
||||
}
|
||||
}
|
||||
let i = block.selectors.length;
|
||||
while (i--) {
|
||||
const selector = block.selectors[i];
|
||||
if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') {
|
||||
if (selector.name !== 'root' && selector.name !== 'host') {
|
||||
if (i === 0) code.prependRight(selector.start, attr);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (selector.type === 'TypeSelector' && selector.name === '*') {
|
||||
code.update(selector.start, selector.end, attr);
|
||||
} else {
|
||||
code.appendLeft(selector.end, attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.blocks.forEach((block, index) => {
|
||||
if (block.global) {
|
||||
remove_global_pseudo_class(block.selectors[0]);
|
||||
}
|
||||
if (block.should_encapsulate)
|
||||
encapsulate_block(
|
||||
block,
|
||||
index === this.blocks.length - 1
|
||||
? attr.repeat(amount_class_specificity_to_increase + 1)
|
||||
: attr
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate(component) {
|
||||
let start = 0;
|
||||
let end = this.blocks.length;
|
||||
for (; start < end; start += 1) {
|
||||
if (!this.blocks[start].global) break;
|
||||
}
|
||||
for (; end > start; end -= 1) {
|
||||
if (!this.blocks[end - 1].global) break;
|
||||
}
|
||||
for (let i = start; i < end; i += 1) {
|
||||
if (this.blocks[i].global) {
|
||||
return component.error(this.blocks[i].selectors[0], compiler_errors.css_invalid_global);
|
||||
}
|
||||
}
|
||||
this.validate_global_with_multiple_selectors(component);
|
||||
this.validate_global_compound_selector(component);
|
||||
this.validate_invalid_combinator_without_selector(component);
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate_global_with_multiple_selectors(component) {
|
||||
if (this.blocks.length === 1 && this.blocks[0].selectors.length === 1) {
|
||||
// standalone :global() with multiple selectors is OK
|
||||
return;
|
||||
}
|
||||
for (const block of this.blocks) {
|
||||
for (const selector of block.selectors) {
|
||||
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
|
||||
if (regex_is_single_css_selector.test(selector.children[0].value)) {
|
||||
component.error(selector, compiler_errors.css_invalid_global_selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate_invalid_combinator_without_selector(component) {
|
||||
for (let i = 0; i < this.blocks.length; i++) {
|
||||
const block = this.blocks[i];
|
||||
if (block.combinator && block.selectors.length === 0) {
|
||||
component.error(
|
||||
this.node,
|
||||
compiler_errors.css_invalid_selector(
|
||||
component.source.slice(this.node.start, this.node.end)
|
||||
)
|
||||
);
|
||||
}
|
||||
if (!block.combinator && block.selectors.length === 0) {
|
||||
component.error(
|
||||
this.node,
|
||||
compiler_errors.css_invalid_selector(
|
||||
component.source.slice(this.node.start, this.node.end)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate_global_compound_selector(component) {
|
||||
for (const block of this.blocks) {
|
||||
for (let index = 0; index < block.selectors.length; index++) {
|
||||
const selector = block.selectors[index];
|
||||
if (
|
||||
selector.type === 'PseudoClassSelector' &&
|
||||
selector.name === 'global' &&
|
||||
index !== 0 &&
|
||||
selector.children &&
|
||||
selector.children.length > 0 &&
|
||||
!/[.:#\s]/.test(selector.children[0].value[0])
|
||||
) {
|
||||
component.error(selector, compiler_errors.css_invalid_global_selector_position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_amount_class_specificity_increased() {
|
||||
let count = 0;
|
||||
for (const block of this.blocks) {
|
||||
if (block.should_encapsulate) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Block[]} blocks
|
||||
* @param {import('../nodes/Element.js').default} node
|
||||
* @param {Array<{ node: import('../nodes/Element.js').default; block: Block }>} to_encapsulate
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function apply_selector(blocks, node, to_encapsulate) {
|
||||
const block = blocks.pop();
|
||||
if (!block) return false;
|
||||
if (!node) {
|
||||
return (
|
||||
(block.global && blocks.every((block) => block.global)) || (block.host && blocks.length === 0)
|
||||
);
|
||||
}
|
||||
switch (block_might_apply_to_node(block, node)) {
|
||||
case BlockAppliesToNode.NotPossible:
|
||||
return false;
|
||||
case BlockAppliesToNode.UnknownSelectorType:
|
||||
// bail. TODO figure out what these could be
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
if (block.combinator) {
|
||||
if (block.combinator.type === 'Combinator' && block.combinator.name === ' ') {
|
||||
for (const ancestor_block of blocks) {
|
||||
if (ancestor_block.global) {
|
||||
continue;
|
||||
}
|
||||
if (ancestor_block.host) {
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
let parent = node;
|
||||
while ((parent = get_element_parent(parent))) {
|
||||
if (
|
||||
block_might_apply_to_node(ancestor_block, parent) !== BlockAppliesToNode.NotPossible
|
||||
) {
|
||||
to_encapsulate.push({ node: parent, block: ancestor_block });
|
||||
}
|
||||
}
|
||||
if (to_encapsulate.length) {
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (blocks.every((block) => block.global)) {
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else if (block.combinator.name === '>') {
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
} else if (block.combinator.name === '+' || block.combinator.name === '~') {
|
||||
const siblings = get_possible_element_siblings(node, block.combinator.name === '+');
|
||||
let has_match = false;
|
||||
// NOTE: if we have :global(), we couldn't figure out what is selected within `:global` due to the
|
||||
// css-tree limitation that does not parse the inner selector of :global
|
||||
// so unless we are sure there will be no sibling to match, we will consider it as matched
|
||||
const has_global = blocks.some((block) => block.global);
|
||||
if (has_global) {
|
||||
if (siblings.size === 0 && get_element_parent(node) !== null) {
|
||||
return false;
|
||||
}
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
for (const possible_sibling of siblings.keys()) {
|
||||
if (apply_selector(blocks.slice(), possible_sibling, to_encapsulate)) {
|
||||
to_encapsulate.push({ node, block });
|
||||
has_match = true;
|
||||
}
|
||||
}
|
||||
return has_match;
|
||||
}
|
||||
// TODO other combinators
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
to_encapsulate.push({ node, block });
|
||||
return true;
|
||||
}
|
||||
|
||||
const regex_backslash_and_following_character = /\\(.)/g;
|
||||
|
||||
/**
|
||||
* @param {Block} block
|
||||
* @param {import('../nodes/Element.js').default} node
|
||||
* @returns {typeof BlockAppliesToNode[keyof typeof BlockAppliesToNode]}
|
||||
*/
|
||||
function block_might_apply_to_node(block, node) {
|
||||
let i = block.selectors.length;
|
||||
while (i--) {
|
||||
const selector = block.selectors[i];
|
||||
const name =
|
||||
typeof selector.name === 'string' &&
|
||||
selector.name.replace(regex_backslash_and_following_character, '$1');
|
||||
if (selector.type === 'PseudoClassSelector' && (name === 'host' || name === 'root')) {
|
||||
return BlockAppliesToNode.NotPossible;
|
||||
}
|
||||
if (
|
||||
block.selectors.length === 1 &&
|
||||
selector.type === 'PseudoClassSelector' &&
|
||||
name === 'global'
|
||||
) {
|
||||
return BlockAppliesToNode.NotPossible;
|
||||
}
|
||||
if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
|
||||
continue;
|
||||
}
|
||||
if (selector.type === 'ClassSelector') {
|
||||
if (
|
||||
!attribute_matches(node, 'class', name, '~=', false) &&
|
||||
!node.classes.some((c) => c.name === name)
|
||||
)
|
||||
return BlockAppliesToNode.NotPossible;
|
||||
} else if (selector.type === 'IdSelector') {
|
||||
if (!attribute_matches(node, 'id', name, '=', false)) return BlockAppliesToNode.NotPossible;
|
||||
} else if (selector.type === 'AttributeSelector') {
|
||||
if (
|
||||
!(
|
||||
whitelist_attribute_selector.has(node.name.toLowerCase()) &&
|
||||
whitelist_attribute_selector
|
||||
.get(node.name.toLowerCase())
|
||||
.has(selector.name.name.toLowerCase())
|
||||
) &&
|
||||
!attribute_matches(
|
||||
node,
|
||||
selector.name.name,
|
||||
selector.value && unquote(selector.value),
|
||||
selector.matcher,
|
||||
selector.flags
|
||||
)
|
||||
) {
|
||||
return BlockAppliesToNode.NotPossible;
|
||||
}
|
||||
} else if (selector.type === 'TypeSelector') {
|
||||
if (
|
||||
node.name.toLowerCase() !== name.toLowerCase() &&
|
||||
name !== '*' &&
|
||||
!node.is_dynamic_element
|
||||
)
|
||||
return BlockAppliesToNode.NotPossible;
|
||||
} else {
|
||||
return BlockAppliesToNode.UnknownSelectorType;
|
||||
}
|
||||
}
|
||||
return BlockAppliesToNode.Possible;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} operator
|
||||
* @param {any} expected_value
|
||||
* @param {any} case_insensitive
|
||||
* @param {any} value
|
||||
*/
|
||||
function test_attribute(operator, expected_value, case_insensitive, value) {
|
||||
if (case_insensitive) {
|
||||
expected_value = expected_value.toLowerCase();
|
||||
value = value.toLowerCase();
|
||||
}
|
||||
switch (operator) {
|
||||
case '=':
|
||||
return value === expected_value;
|
||||
case '~=':
|
||||
return value.split(/\s/).includes(expected_value);
|
||||
case '|=':
|
||||
return `${value}-`.startsWith(`${expected_value}-`);
|
||||
case '^=':
|
||||
return value.startsWith(expected_value);
|
||||
case '$=':
|
||||
return value.endsWith(expected_value);
|
||||
case '*=':
|
||||
return value.includes(expected_value);
|
||||
default:
|
||||
throw new Error("this shouldn't happen");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./private.js').CssNode} node
|
||||
* @param {string} name
|
||||
* @param {string} expected_value
|
||||
* @param {string} operator
|
||||
* @param {boolean} case_insensitive
|
||||
*/
|
||||
function attribute_matches(node, name, expected_value, operator, case_insensitive) {
|
||||
const spread = node.attributes.find((attr) => attr.type === 'Spread');
|
||||
if (spread) return true;
|
||||
if (node.bindings.some((binding) => binding.name === name)) return true;
|
||||
const attr = node.attributes.find((attr) => attr.name === name);
|
||||
if (!attr) return false;
|
||||
if (attr.is_true) return operator === null;
|
||||
if (expected_value == null) return true;
|
||||
if (attr.chunks.length === 1) {
|
||||
const value = attr.chunks[0];
|
||||
if (!value) return false;
|
||||
if (value.type === 'Text')
|
||||
return test_attribute(operator, expected_value, case_insensitive, value.data);
|
||||
}
|
||||
const possible_values = new Set();
|
||||
let prev_values = [];
|
||||
for (const chunk of attr.chunks) {
|
||||
const current_possible_values = new Set();
|
||||
if (chunk.type === 'Text') {
|
||||
current_possible_values.add(chunk.data);
|
||||
} else {
|
||||
gather_possible_values(chunk.node, current_possible_values);
|
||||
}
|
||||
// impossible to find out all combinations
|
||||
if (current_possible_values.has(UNKNOWN)) return true;
|
||||
if (prev_values.length > 0) {
|
||||
const start_with_space = [];
|
||||
const remaining = [];
|
||||
current_possible_values.forEach((current_possible_value) => {
|
||||
if (regex_starts_with_whitespace.test(current_possible_value)) {
|
||||
start_with_space.push(current_possible_value);
|
||||
} else {
|
||||
remaining.push(current_possible_value);
|
||||
}
|
||||
});
|
||||
if (remaining.length > 0) {
|
||||
if (start_with_space.length > 0) {
|
||||
prev_values.forEach((prev_value) => possible_values.add(prev_value));
|
||||
}
|
||||
const combined = [];
|
||||
prev_values.forEach((prev_value) => {
|
||||
remaining.forEach((value) => {
|
||||
combined.push(prev_value + value);
|
||||
});
|
||||
});
|
||||
prev_values = combined;
|
||||
start_with_space.forEach((value) => {
|
||||
if (regex_ends_with_whitespace.test(value)) {
|
||||
possible_values.add(value);
|
||||
} else {
|
||||
prev_values.push(value);
|
||||
}
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
prev_values.forEach((prev_value) => possible_values.add(prev_value));
|
||||
prev_values = [];
|
||||
}
|
||||
}
|
||||
current_possible_values.forEach((current_possible_value) => {
|
||||
if (regex_ends_with_whitespace.test(current_possible_value)) {
|
||||
possible_values.add(current_possible_value);
|
||||
} else {
|
||||
prev_values.push(current_possible_value);
|
||||
}
|
||||
});
|
||||
if (prev_values.length < current_possible_values.size) {
|
||||
prev_values.push(' ');
|
||||
}
|
||||
if (prev_values.length > 20) {
|
||||
// might grow exponentially, bail out
|
||||
return true;
|
||||
}
|
||||
}
|
||||
prev_values.forEach((prev_value) => possible_values.add(prev_value));
|
||||
if (possible_values.has(UNKNOWN)) return true;
|
||||
for (const value of possible_values) {
|
||||
if (test_attribute(operator, expected_value, case_insensitive, value)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @param {import('./private.js').CssNode} value */
|
||||
function unquote(value) {
|
||||
if (value.type === 'Identifier') return value.name;
|
||||
const str = value.value;
|
||||
if ((str[0] === str[str.length - 1] && str[0] === "'") || str[0] === '"') {
|
||||
return str.slice(1, str.length - 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../nodes/Element.js').default} node
|
||||
* @returns {any}
|
||||
*/
|
||||
function get_element_parent(node) {
|
||||
/** @type {import('../nodes/interfaces.js').INode} */
|
||||
let parent = node;
|
||||
while ((parent = parent.parent) && parent.type !== 'Element');
|
||||
return /** @type {import('../nodes/Element.js').default | null} */ (parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the given node's previous sibling in the DOM
|
||||
*
|
||||
* The Svelte <slot> is just a placeholder and is not actually real. Any children nodes
|
||||
* in <slot> are 'flattened' and considered as the same level as the <slot>'s siblings
|
||||
*
|
||||
* e.g.
|
||||
* <h1>Heading 1</h1>
|
||||
* <slot>
|
||||
* <h2>Heading 2</h2>
|
||||
* </slot>
|
||||
*
|
||||
* is considered to look like:
|
||||
* <h1>Heading 1</h1>
|
||||
* <h2>Heading 2</h2>
|
||||
* @param {import('../nodes/interfaces.js').INode} node
|
||||
* @returns {import('../nodes/interfaces.js').INode}
|
||||
*/
|
||||
function find_previous_sibling(node) {
|
||||
/** @type {import('../nodes/interfaces.js').INode} */
|
||||
let current_node = node;
|
||||
do {
|
||||
if (current_node.type === 'Slot') {
|
||||
const slot_children = current_node.children;
|
||||
if (slot_children.length > 0) {
|
||||
current_node = slot_children.slice(-1)[0]; // go to its last child first
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (!current_node.prev && current_node.parent && current_node.parent.type === 'Slot') {
|
||||
current_node = current_node.parent;
|
||||
}
|
||||
current_node = current_node.prev;
|
||||
} while (current_node && current_node.type === 'Slot');
|
||||
return current_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../nodes/interfaces.js').INode} node
|
||||
* @param {boolean} adjacent_only
|
||||
* @returns {Map<import('../nodes/Element.js').default, NodeExistsValue>}
|
||||
*/
|
||||
function get_possible_element_siblings(node, adjacent_only) {
|
||||
/** @type {Map<import('../nodes/Element.js').default, NodeExistsValue>} */
|
||||
const result = new Map();
|
||||
|
||||
/** @type {import('../nodes/interfaces.js').INode} */
|
||||
let prev = node;
|
||||
while ((prev = find_previous_sibling(prev))) {
|
||||
if (prev.type === 'Element') {
|
||||
if (
|
||||
!prev.attributes.find(
|
||||
(attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot'
|
||||
)
|
||||
) {
|
||||
result.set(prev, NodeExist.Definitely);
|
||||
}
|
||||
if (adjacent_only) {
|
||||
break;
|
||||
}
|
||||
} else if (prev.type === 'EachBlock' || prev.type === 'IfBlock' || prev.type === 'AwaitBlock') {
|
||||
const possible_last_child = get_possible_last_child(prev, adjacent_only);
|
||||
add_to_map(possible_last_child, result);
|
||||
if (adjacent_only && has_definite_elements(possible_last_child)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!prev || !adjacent_only) {
|
||||
/** @type {import('../nodes/interfaces.js').INode} */
|
||||
let parent = node;
|
||||
let skip_each_for_last_child = node.type === 'ElseBlock';
|
||||
while (
|
||||
(parent = parent.parent) &&
|
||||
(parent.type === 'EachBlock' ||
|
||||
parent.type === 'IfBlock' ||
|
||||
parent.type === 'ElseBlock' ||
|
||||
parent.type === 'AwaitBlock')
|
||||
) {
|
||||
const possible_siblings = get_possible_element_siblings(parent, adjacent_only);
|
||||
add_to_map(possible_siblings, result);
|
||||
if (parent.type === 'EachBlock') {
|
||||
// first child of each block can select the last child of each block as previous sibling
|
||||
if (skip_each_for_last_child) {
|
||||
skip_each_for_last_child = false;
|
||||
} else {
|
||||
add_to_map(get_possible_last_child(parent, adjacent_only), result);
|
||||
}
|
||||
} else if (parent.type === 'ElseBlock') {
|
||||
skip_each_for_last_child = true;
|
||||
parent = parent.parent;
|
||||
}
|
||||
if (adjacent_only && has_definite_elements(possible_siblings)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../nodes/EachBlock.js').default | import('../nodes/IfBlock.js').default | import('../nodes/AwaitBlock.js').default} block
|
||||
* @param {boolean} adjacent_only
|
||||
* @returns {Map<import('../nodes/Element.js').default, NodeExistsValue>}
|
||||
*/
|
||||
function get_possible_last_child(block, adjacent_only) {
|
||||
/** @typedef {Map<import('../nodes/Element.js').default, NodeExistsValue>} NodeMap */
|
||||
|
||||
/** @type {NodeMap} */
|
||||
const result = new Map();
|
||||
if (block.type === 'EachBlock') {
|
||||
/** @type {NodeMap} */
|
||||
const each_result = loop_child(block.children, adjacent_only);
|
||||
|
||||
/** @type {NodeMap} */
|
||||
const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
|
||||
const not_exhaustive = !has_definite_elements(else_result);
|
||||
if (not_exhaustive) {
|
||||
mark_as_probably(each_result);
|
||||
mark_as_probably(else_result);
|
||||
}
|
||||
add_to_map(each_result, result);
|
||||
add_to_map(else_result, result);
|
||||
} else if (block.type === 'IfBlock') {
|
||||
/** @type {NodeMap} */
|
||||
const if_result = loop_child(block.children, adjacent_only);
|
||||
|
||||
/** @type {NodeMap} */
|
||||
const else_result = block.else ? loop_child(block.else.children, adjacent_only) : new Map();
|
||||
const not_exhaustive = !has_definite_elements(if_result) || !has_definite_elements(else_result);
|
||||
if (not_exhaustive) {
|
||||
mark_as_probably(if_result);
|
||||
mark_as_probably(else_result);
|
||||
}
|
||||
add_to_map(if_result, result);
|
||||
add_to_map(else_result, result);
|
||||
} else if (block.type === 'AwaitBlock') {
|
||||
/** @type {NodeMap} */
|
||||
const pending_result = block.pending
|
||||
? loop_child(block.pending.children, adjacent_only)
|
||||
: new Map();
|
||||
|
||||
/** @type {NodeMap} */
|
||||
const then_result = block.then ? loop_child(block.then.children, adjacent_only) : new Map();
|
||||
|
||||
/** @type {NodeMap} */
|
||||
const catch_result = block.catch ? loop_child(block.catch.children, adjacent_only) : new Map();
|
||||
const not_exhaustive =
|
||||
!has_definite_elements(pending_result) ||
|
||||
!has_definite_elements(then_result) ||
|
||||
!has_definite_elements(catch_result);
|
||||
if (not_exhaustive) {
|
||||
mark_as_probably(pending_result);
|
||||
mark_as_probably(then_result);
|
||||
mark_as_probably(catch_result);
|
||||
}
|
||||
add_to_map(pending_result, result);
|
||||
add_to_map(then_result, result);
|
||||
add_to_map(catch_result, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Map<import('../nodes/Element.js').default, NodeExistsValue>} result
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function has_definite_elements(result) {
|
||||
if (result.size === 0) return false;
|
||||
for (const exist of result.values()) {
|
||||
if (exist === NodeExist.Definitely) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Map<import('../nodes/Element.js').default, NodeExistsValue>} from
|
||||
* @param {Map<import('../nodes/Element.js').default, NodeExistsValue>} to
|
||||
* @returns {void}
|
||||
*/
|
||||
function add_to_map(from, to) {
|
||||
from.forEach((exist, element) => {
|
||||
to.set(element, higher_existence(exist, to.get(element)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NodeExistsValue | null} exist1
|
||||
* @param {NodeExistsValue | null} exist2
|
||||
* @returns {NodeExistsValue}
|
||||
*/
|
||||
function higher_existence(exist1, exist2) {
|
||||
if (exist1 === undefined || exist2 === undefined) return exist1 || exist2;
|
||||
return exist1 > exist2 ? exist1 : exist2;
|
||||
}
|
||||
|
||||
/** @param {Map<import('../nodes/Element.js').default, NodeExistsValue>} result */
|
||||
function mark_as_probably(result) {
|
||||
for (const key of result.keys()) {
|
||||
result.set(key, NodeExist.Probably);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../nodes/interfaces.js').INode[]} children
|
||||
* @param {boolean} adjacent_only
|
||||
*/
|
||||
function loop_child(children, adjacent_only) {
|
||||
/** @type {Map<import('../nodes/Element.js').default, NodeExistsValue>} */
|
||||
const result = new Map();
|
||||
for (let i = children.length - 1; i >= 0; i--) {
|
||||
const child = children[i];
|
||||
if (child.type === 'Element') {
|
||||
result.set(child, NodeExist.Definitely);
|
||||
if (adjacent_only) {
|
||||
break;
|
||||
}
|
||||
} else if (
|
||||
child.type === 'EachBlock' ||
|
||||
child.type === 'IfBlock' ||
|
||||
child.type === 'AwaitBlock'
|
||||
) {
|
||||
const child_result = get_possible_last_child(child, adjacent_only);
|
||||
add_to_map(child_result, result);
|
||||
if (adjacent_only && has_definite_elements(child_result)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class Block {
|
||||
/** @type {boolean} */
|
||||
host;
|
||||
|
||||
/** @type {boolean} */
|
||||
root;
|
||||
|
||||
/** @type {import('./private.js').CssNode} */
|
||||
combinator;
|
||||
|
||||
/** @type {import('./private.js').CssNode[]} */
|
||||
selectors;
|
||||
|
||||
/** @type {number} */
|
||||
start;
|
||||
|
||||
/** @type {number} */
|
||||
end;
|
||||
|
||||
/** @type {boolean} */
|
||||
should_encapsulate;
|
||||
|
||||
/** @param {import('./private.js').CssNode} combinator */
|
||||
constructor(combinator) {
|
||||
this.combinator = combinator;
|
||||
this.host = false;
|
||||
this.root = false;
|
||||
this.selectors = [];
|
||||
this.start = null;
|
||||
this.end = null;
|
||||
this.should_encapsulate = false;
|
||||
}
|
||||
|
||||
/** @param {import('./private.js').CssNode} selector */
|
||||
add(selector) {
|
||||
if (this.selectors.length === 0) {
|
||||
this.start = selector.start;
|
||||
this.host = selector.type === 'PseudoClassSelector' && selector.name === 'host';
|
||||
}
|
||||
this.root = this.root || (selector.type === 'PseudoClassSelector' && selector.name === 'root');
|
||||
this.selectors.push(selector);
|
||||
this.end = selector.end;
|
||||
}
|
||||
get global() {
|
||||
return (
|
||||
this.selectors.length >= 1 &&
|
||||
this.selectors[0].type === 'PseudoClassSelector' &&
|
||||
this.selectors[0].name === 'global' &&
|
||||
this.selectors.every(
|
||||
(selector) =>
|
||||
selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('./private.js').CssNode} selector */
|
||||
function group_selectors(selector) {
|
||||
/** @type {Block} */
|
||||
let block = new Block(null);
|
||||
const blocks = [block];
|
||||
selector.children.forEach((child) => {
|
||||
if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
|
||||
block = new Block(child);
|
||||
blocks.push(block);
|
||||
} else {
|
||||
block.add(child);
|
||||
}
|
||||
});
|
||||
return blocks;
|
||||
}
|
514
node_modules/svelte/src/compiler/compile/css/Stylesheet.js
generated
vendored
Normal file
514
node_modules/svelte/src/compiler/compile/css/Stylesheet.js
generated
vendored
Normal file
@ -0,0 +1,514 @@
|
||||
import MagicString from 'magic-string';
|
||||
import { walk } from 'estree-walker';
|
||||
import Selector from './Selector.js';
|
||||
import hash from '../utils/hash.js';
|
||||
import compiler_warnings from '../compiler_warnings.js';
|
||||
import { extract_ignores_above_position } from '../../utils/extract_svelte_ignore.js';
|
||||
import { push_array } from '../../utils/push_array.js';
|
||||
import { regex_only_whitespaces, regex_whitespace } from '../../utils/patterns.js';
|
||||
|
||||
const regex_css_browser_prefix = /^-((webkit)|(moz)|(o)|(ms))-/;
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {string}
|
||||
*/
|
||||
function remove_css_prefix(name) {
|
||||
return name.replace(regex_css_browser_prefix, '');
|
||||
}
|
||||
|
||||
/** @param {import('./private.js').CssNode} node */
|
||||
const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';
|
||||
|
||||
/**
|
||||
* @param {import('./private.js').CssNode} param
|
||||
* @returns {true}
|
||||
*/
|
||||
const at_rule_has_declaration = ({ block }) =>
|
||||
block && block.children && block.children.find((node) => node.type === 'Declaration');
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {number} start
|
||||
* @param {Declaration[]} declarations
|
||||
* @returns {number}
|
||||
*/
|
||||
function minify_declarations(code, start, declarations) {
|
||||
let c = start;
|
||||
declarations.forEach((declaration, i) => {
|
||||
const separator = i > 0 ? ';' : '';
|
||||
if (declaration.node.start - c > separator.length) {
|
||||
code.update(c, declaration.node.start, separator);
|
||||
}
|
||||
declaration.minify(code);
|
||||
c = declaration.node.end;
|
||||
});
|
||||
return c;
|
||||
}
|
||||
class Rule {
|
||||
/** @type {import('./Selector.js').default[]} */
|
||||
selectors;
|
||||
|
||||
/** @type {Declaration[]} */
|
||||
declarations;
|
||||
|
||||
/** @type {import('./private.js').CssNode} */
|
||||
node;
|
||||
|
||||
/** @type {Atrule} */
|
||||
parent;
|
||||
|
||||
/**
|
||||
* @param {import('./private.js').CssNode} node
|
||||
* @param {any} stylesheet
|
||||
* @param {Atrule} [parent]
|
||||
*/
|
||||
constructor(node, stylesheet, parent) {
|
||||
this.node = node;
|
||||
this.parent = parent;
|
||||
this.selectors = node.prelude.children.map((node) => new Selector(node, stylesheet));
|
||||
this.declarations = node.block.children.map((node) => new Declaration(node));
|
||||
}
|
||||
|
||||
/** @param {import('../nodes/Element.js').default} node */
|
||||
apply(node) {
|
||||
this.selectors.forEach((selector) => selector.apply(node)); // TODO move the logic in here?
|
||||
}
|
||||
|
||||
/** @param {boolean} dev */
|
||||
is_used(dev) {
|
||||
if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
|
||||
return true;
|
||||
if (this.declarations.length === 0) return dev;
|
||||
return this.selectors.some((s) => s.used);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {boolean} _dev
|
||||
*/
|
||||
minify(code, _dev) {
|
||||
let c = this.node.start;
|
||||
let started = false;
|
||||
this.selectors.forEach((selector) => {
|
||||
if (selector.used) {
|
||||
const separator = started ? ',' : '';
|
||||
if (selector.node.start - c > separator.length) {
|
||||
code.update(c, selector.node.start, separator);
|
||||
}
|
||||
selector.minify(code);
|
||||
c = selector.node.end;
|
||||
started = true;
|
||||
}
|
||||
});
|
||||
code.remove(c, this.node.block.start);
|
||||
c = this.node.block.start + 1;
|
||||
c = minify_declarations(code, c, this.declarations);
|
||||
code.remove(c, this.node.block.end - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {string} id
|
||||
* @param {Map<string, string>} keyframes
|
||||
* @param {number} max_amount_class_specificity_increased
|
||||
*/
|
||||
transform(code, id, keyframes, max_amount_class_specificity_increased) {
|
||||
if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
|
||||
return true;
|
||||
const attr = `.${id}`;
|
||||
this.selectors.forEach((selector) =>
|
||||
selector.transform(code, attr, max_amount_class_specificity_increased)
|
||||
);
|
||||
this.declarations.forEach((declaration) => declaration.transform(code, keyframes));
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate(component) {
|
||||
this.selectors.forEach((selector) => {
|
||||
selector.validate(component);
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {(selector: import('./Selector.js').default) => void} handler */
|
||||
warn_on_unused_selector(handler) {
|
||||
this.selectors.forEach((selector) => {
|
||||
if (!selector.used) handler(selector);
|
||||
});
|
||||
}
|
||||
get_max_amount_class_specificity_increased() {
|
||||
return Math.max(
|
||||
...this.selectors.map((selector) => selector.get_amount_class_specificity_increased())
|
||||
);
|
||||
}
|
||||
}
|
||||
class Declaration {
|
||||
/** @type {import('./private.js').CssNode} */
|
||||
node;
|
||||
|
||||
/** @param {import('./private.js').CssNode} node */
|
||||
constructor(node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {Map<string, string>} keyframes
|
||||
*/
|
||||
transform(code, keyframes) {
|
||||
const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase());
|
||||
if (property === 'animation' || property === 'animation-name') {
|
||||
this.node.value.children.forEach((block) => {
|
||||
if (block.type === 'Identifier') {
|
||||
const name = block.name;
|
||||
if (keyframes.has(name)) {
|
||||
code.update(block.start, block.end, keyframes.get(name));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('magic-string').default} code */
|
||||
minify(code) {
|
||||
if (!this.node.property) return; // @apply, and possibly other weird cases?
|
||||
const c = this.node.start + this.node.property.length;
|
||||
const first = this.node.value.children ? this.node.value.children[0] : this.node.value;
|
||||
// Don't minify whitespace in custom properties, since some browsers (Chromium < 99)
|
||||
// treat --foo: ; and --foo:; differently
|
||||
if (first.type === 'Raw' && regex_only_whitespaces.test(first.value)) return;
|
||||
let start = first.start;
|
||||
while (regex_whitespace.test(code.original[start])) start += 1;
|
||||
if (start - c > 1) {
|
||||
code.update(c, start, ':');
|
||||
}
|
||||
}
|
||||
}
|
||||
class Atrule {
|
||||
/** @type {import('./private.js').CssNode} */
|
||||
node;
|
||||
|
||||
/** @type {Array<Atrule | Rule>} */
|
||||
children;
|
||||
|
||||
/** @type {Declaration[]} */
|
||||
declarations;
|
||||
|
||||
/** @param {import('./private.js').CssNode} node */
|
||||
constructor(node) {
|
||||
this.node = node;
|
||||
this.children = [];
|
||||
this.declarations = [];
|
||||
}
|
||||
|
||||
/** @param {import('../nodes/Element.js').default} node */
|
||||
apply(node) {
|
||||
if (
|
||||
this.node.name === 'container' ||
|
||||
this.node.name === 'media' ||
|
||||
this.node.name === 'supports' ||
|
||||
this.node.name === 'layer'
|
||||
) {
|
||||
this.children.forEach((child) => {
|
||||
child.apply(node);
|
||||
});
|
||||
} else if (is_keyframes_node(this.node)) {
|
||||
this.children.forEach((/** @type {Rule} */ rule) => {
|
||||
rule.selectors.forEach((selector) => {
|
||||
selector.used = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {boolean} _dev */
|
||||
is_used(_dev) {
|
||||
return true; // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {boolean} dev
|
||||
*/
|
||||
minify(code, dev) {
|
||||
if (this.node.name === 'media') {
|
||||
const expression_char = code.original[this.node.prelude.start];
|
||||
let c = this.node.start + (expression_char === '(' ? 6 : 7);
|
||||
if (this.node.prelude.start > c) code.remove(c, this.node.prelude.start);
|
||||
this.node.prelude.children.forEach((query) => {
|
||||
// TODO minify queries
|
||||
c = query.end;
|
||||
});
|
||||
code.remove(c, this.node.block.start);
|
||||
} else if (this.node.name === 'supports') {
|
||||
let c = this.node.start + 9;
|
||||
if (this.node.prelude.start - c > 1) code.update(c, this.node.prelude.start, ' ');
|
||||
this.node.prelude.children.forEach((query) => {
|
||||
// TODO minify queries
|
||||
c = query.end;
|
||||
});
|
||||
code.remove(c, this.node.block.start);
|
||||
} else {
|
||||
let c = this.node.start + this.node.name.length + 1;
|
||||
if (this.node.prelude) {
|
||||
if (this.node.prelude.start - c > 1) code.update(c, this.node.prelude.start, ' ');
|
||||
c = this.node.prelude.end;
|
||||
}
|
||||
if (this.node.block && this.node.block.start - c > 0) {
|
||||
code.remove(c, this.node.block.start);
|
||||
}
|
||||
}
|
||||
// TODO other atrules
|
||||
if (this.node.block) {
|
||||
let c = this.node.block.start + 1;
|
||||
if (this.declarations.length) {
|
||||
c = minify_declarations(code, c, this.declarations);
|
||||
// if the atrule has children, leave the last declaration semicolon alone
|
||||
if (this.children.length) c++;
|
||||
}
|
||||
this.children.forEach((child) => {
|
||||
if (child.is_used(dev)) {
|
||||
code.remove(c, child.node.start);
|
||||
child.minify(code, dev);
|
||||
c = child.node.end;
|
||||
}
|
||||
});
|
||||
code.remove(c, this.node.block.end - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('magic-string').default} code
|
||||
* @param {string} id
|
||||
* @param {Map<string, string>} keyframes
|
||||
* @param {number} max_amount_class_specificity_increased
|
||||
*/
|
||||
transform(code, id, keyframes, max_amount_class_specificity_increased) {
|
||||
if (is_keyframes_node(this.node)) {
|
||||
this.node.prelude.children.forEach(({ type, name, start, end }) => {
|
||||
if (type === 'Identifier') {
|
||||
if (name.startsWith('-global-')) {
|
||||
code.remove(start, start + 8);
|
||||
this.children.forEach((/** @type {Rule} */ rule) => {
|
||||
rule.selectors.forEach((selector) => {
|
||||
selector.used = true;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
code.update(start, end, keyframes.get(name));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
this.children.forEach((child) => {
|
||||
child.transform(code, id, keyframes, max_amount_class_specificity_increased);
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate(component) {
|
||||
this.children.forEach((child) => {
|
||||
child.validate(component);
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {(selector: import('./Selector.js').default) => void} handler */
|
||||
warn_on_unused_selector(handler) {
|
||||
if (this.node.name !== 'media') return;
|
||||
this.children.forEach((child) => {
|
||||
child.warn_on_unused_selector(handler);
|
||||
});
|
||||
}
|
||||
get_max_amount_class_specificity_increased() {
|
||||
return Math.max(
|
||||
...this.children.map((rule) => rule.get_max_amount_class_specificity_increased())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {any} params */
|
||||
const get_default_css_hash = ({ css, hash }) => {
|
||||
return `svelte-${hash(css)}`;
|
||||
};
|
||||
export default class Stylesheet {
|
||||
/** @type {string} */
|
||||
source;
|
||||
|
||||
/** @type {import('../../interfaces.js').Ast} */
|
||||
ast;
|
||||
|
||||
/** @type {string} */
|
||||
filename;
|
||||
|
||||
/** @type {boolean} */
|
||||
dev;
|
||||
|
||||
/** @type {boolean} */
|
||||
has_styles;
|
||||
|
||||
/** @type {string} */
|
||||
id;
|
||||
|
||||
/** @type {Array<Rule | Atrule>} */
|
||||
children = [];
|
||||
|
||||
/** @type {Map<string, string>} */
|
||||
keyframes = new Map();
|
||||
|
||||
/** @type {Set<import('./private.js').CssNode>} */
|
||||
nodes_with_css_class = new Set();
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* source: string;
|
||||
* ast: import('../../interfaces.js').Ast;
|
||||
* filename: string | undefined;
|
||||
* component_name: string | undefined;
|
||||
* dev: boolean;
|
||||
* get_css_hash: import('../../interfaces.js').CssHashGetter;
|
||||
* }} params
|
||||
*/
|
||||
constructor({ source, ast, component_name, filename, dev, get_css_hash = get_default_css_hash }) {
|
||||
this.source = source;
|
||||
this.ast = ast;
|
||||
this.filename = filename;
|
||||
this.dev = dev;
|
||||
if (ast.css && ast.css.children.length) {
|
||||
this.id = get_css_hash({
|
||||
filename,
|
||||
name: component_name,
|
||||
css: ast.css.content.styles,
|
||||
hash
|
||||
});
|
||||
this.has_styles = true;
|
||||
|
||||
/** @type {Atrule[]} */
|
||||
const stack = [];
|
||||
let depth = 0;
|
||||
|
||||
/** @type {Atrule} */
|
||||
let current_atrule = null;
|
||||
walk(/** @type {any} */ (ast.css), {
|
||||
enter: (/** @type {any} */ node) => {
|
||||
if (node.type === 'Atrule') {
|
||||
const atrule = new Atrule(node);
|
||||
stack.push(atrule);
|
||||
if (current_atrule) {
|
||||
current_atrule.children.push(atrule);
|
||||
} else if (depth <= 1) {
|
||||
this.children.push(atrule);
|
||||
}
|
||||
if (is_keyframes_node(node)) {
|
||||
node.prelude.children.forEach((expression) => {
|
||||
if (expression.type === 'Identifier' && !expression.name.startsWith('-global-')) {
|
||||
this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
|
||||
}
|
||||
});
|
||||
} else if (at_rule_has_declaration(node)) {
|
||||
const at_rule_declarations = node.block.children
|
||||
.filter((node) => node.type === 'Declaration')
|
||||
.map((node) => new Declaration(node));
|
||||
push_array(atrule.declarations, at_rule_declarations);
|
||||
}
|
||||
current_atrule = atrule;
|
||||
}
|
||||
if (node.type === 'Rule') {
|
||||
const rule = new Rule(node, this, current_atrule);
|
||||
if (current_atrule) {
|
||||
current_atrule.children.push(rule);
|
||||
} else if (depth <= 1) {
|
||||
this.children.push(rule);
|
||||
}
|
||||
}
|
||||
depth += 1;
|
||||
},
|
||||
leave: (/** @type {any} */ node) => {
|
||||
if (node.type === 'Atrule') {
|
||||
stack.pop();
|
||||
current_atrule = stack[stack.length - 1];
|
||||
}
|
||||
depth -= 1;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.has_styles = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('../nodes/Element.js').default} node */
|
||||
apply(node) {
|
||||
if (!this.has_styles) return;
|
||||
for (let i = 0; i < this.children.length; i += 1) {
|
||||
const child = this.children[i];
|
||||
child.apply(node);
|
||||
}
|
||||
}
|
||||
reify() {
|
||||
this.nodes_with_css_class.forEach((node) => {
|
||||
node.add_css_class();
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {string} file */
|
||||
render(file) {
|
||||
if (!this.has_styles) {
|
||||
return { code: null, map: null };
|
||||
}
|
||||
const code = new MagicString(this.source);
|
||||
walk(/** @type {any} */ (this.ast.css), {
|
||||
enter: (/** @type {any} */ node) => {
|
||||
code.addSourcemapLocation(node.start);
|
||||
code.addSourcemapLocation(node.end);
|
||||
}
|
||||
});
|
||||
const max = Math.max(
|
||||
...this.children.map((rule) => rule.get_max_amount_class_specificity_increased())
|
||||
);
|
||||
this.children.forEach((child) => {
|
||||
child.transform(code, this.id, this.keyframes, max);
|
||||
});
|
||||
let c = 0;
|
||||
this.children.forEach((child) => {
|
||||
if (child.is_used(this.dev)) {
|
||||
code.remove(c, child.node.start);
|
||||
child.minify(code, this.dev);
|
||||
c = child.node.end;
|
||||
}
|
||||
});
|
||||
code.remove(c, this.source.length);
|
||||
return {
|
||||
code: code.toString(),
|
||||
map: code.generateMap({
|
||||
includeContent: true,
|
||||
source: this.filename,
|
||||
file
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
validate(component) {
|
||||
this.children.forEach((child) => {
|
||||
child.validate(component);
|
||||
});
|
||||
}
|
||||
|
||||
/** @param {import('../Component.js').default} component */
|
||||
warn_on_unused_selectors(component) {
|
||||
const ignores = !this.ast.css
|
||||
? []
|
||||
: extract_ignores_above_position(this.ast.css.start, this.ast.html.children);
|
||||
component.push_ignores(ignores);
|
||||
this.children.forEach((child) => {
|
||||
child.warn_on_unused_selector((selector) => {
|
||||
component.warn(
|
||||
selector.node,
|
||||
compiler_warnings.css_unused_selector(
|
||||
this.source.slice(selector.node.start, selector.node.end)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
component.pop_ignores();
|
||||
}
|
||||
}
|
16
node_modules/svelte/src/compiler/compile/css/gather_possible_values.js
generated
vendored
Normal file
16
node_modules/svelte/src/compiler/compile/css/gather_possible_values.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
export const UNKNOWN = {};
|
||||
|
||||
/**
|
||||
* @param {import("estree").Node} node
|
||||
* @param {Set<string | {}>} set
|
||||
*/
|
||||
export function gather_possible_values(node, set) {
|
||||
if (node.type === 'Literal') {
|
||||
set.add(node.value);
|
||||
} else if (node.type === 'ConditionalExpression') {
|
||||
gather_possible_values(node.consequent, set);
|
||||
gather_possible_values(node.alternate, set);
|
||||
} else {
|
||||
set.add(UNKNOWN);
|
||||
}
|
||||
}
|
6
node_modules/svelte/src/compiler/compile/css/private.d.ts
generated
vendored
Normal file
6
node_modules/svelte/src/compiler/compile/css/private.d.ts
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export interface CssNode {
|
||||
type: string;
|
||||
start: number;
|
||||
end: number;
|
||||
[prop_name: string]: any;
|
||||
}
|
155
node_modules/svelte/src/compiler/compile/index.js
generated
vendored
Normal file
155
node_modules/svelte/src/compiler/compile/index.js
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
import Stats from '../Stats.js';
|
||||
import parse from '../parse/index.js';
|
||||
import render_dom from './render_dom/index.js';
|
||||
import render_ssr from './render_ssr/index.js';
|
||||
import Component from './Component.js';
|
||||
import fuzzymatch from '../utils/fuzzymatch.js';
|
||||
import get_name_from_filename from './utils/get_name_from_filename.js';
|
||||
import { valid_namespaces } from '../utils/namespaces.js';
|
||||
|
||||
const valid_options = [
|
||||
'name',
|
||||
'filename',
|
||||
'sourcemap',
|
||||
'enableSourcemap',
|
||||
'generate',
|
||||
'errorMode',
|
||||
'varsReport',
|
||||
'outputFilename',
|
||||
'cssOutputFilename',
|
||||
'sveltePath',
|
||||
'dev',
|
||||
'accessors',
|
||||
'immutable',
|
||||
'hydratable',
|
||||
'legacy',
|
||||
'customElement',
|
||||
'namespace',
|
||||
'tag',
|
||||
'css',
|
||||
'loopGuardTimeout',
|
||||
'preserveComments',
|
||||
'preserveWhitespace',
|
||||
'cssHash',
|
||||
'discloseVersion'
|
||||
];
|
||||
const valid_css_values = [true, false, 'injected', 'external', 'none'];
|
||||
const regex_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
|
||||
const regex_starts_with_lowercase_character = /^[a-z]/;
|
||||
|
||||
let warned_of_format = false;
|
||||
let warned_boolean_css = false;
|
||||
|
||||
/**
|
||||
* @param {import('../interfaces.js').CompileOptions} options
|
||||
* @param {import('../interfaces.js').Warning[]} warnings
|
||||
*/
|
||||
function validate_options(options, warnings) {
|
||||
if (/** @type {any} */ (options).format) {
|
||||
if (!warned_of_format) {
|
||||
warned_of_format = true;
|
||||
console.warn(
|
||||
'The format option has been removed in Svelte 4, the compiler only outputs ESM now. Remove "format" from your compiler options. ' +
|
||||
'If you did not set this yourself, bump the version of your bundler plugin (vite-plugin-svelte/rollup-plugin-svelte/svelte-loader)'
|
||||
);
|
||||
}
|
||||
delete (/** @type {any} */ (options).format);
|
||||
}
|
||||
|
||||
const { name, filename, loopGuardTimeout, dev, namespace, css } = options;
|
||||
Object.keys(options).forEach((key) => {
|
||||
if (!valid_options.includes(key)) {
|
||||
const match = fuzzymatch(key, valid_options);
|
||||
let message = `Unrecognized option '${key}'`;
|
||||
if (match) message += ` (did you mean '${match}'?)`;
|
||||
throw new Error(message);
|
||||
}
|
||||
});
|
||||
if (name && !regex_valid_identifier.test(name)) {
|
||||
throw new Error(`options.name must be a valid identifier (got '${name}')`);
|
||||
}
|
||||
if (name && regex_starts_with_lowercase_character.test(name)) {
|
||||
const message = 'options.name should be capitalised';
|
||||
warnings.push({
|
||||
code: 'options-lowercase-name',
|
||||
message,
|
||||
filename,
|
||||
toString: () => message
|
||||
});
|
||||
}
|
||||
if (loopGuardTimeout && !dev) {
|
||||
const message = 'options.loopGuardTimeout is for options.dev = true only';
|
||||
warnings.push({
|
||||
code: 'options-loop-guard-timeout',
|
||||
message,
|
||||
filename,
|
||||
toString: () => message
|
||||
});
|
||||
}
|
||||
|
||||
if (css === true || css === false) {
|
||||
options.css = css === true ? 'injected' : 'external';
|
||||
if (!warned_boolean_css) {
|
||||
console.warn(
|
||||
`compilerOptions.css as a boolean is deprecated. Use '${options.css}' instead of ${css}.`
|
||||
);
|
||||
warned_boolean_css = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_css_values.includes(options.css)) {
|
||||
throw new Error(
|
||||
`compilerOptions.css must be 'injected', 'external' or 'none' (got '${options.css}').`
|
||||
);
|
||||
}
|
||||
|
||||
if (namespace && valid_namespaces.indexOf(namespace) === -1) {
|
||||
const match = fuzzymatch(namespace, valid_namespaces);
|
||||
if (match) {
|
||||
throw new Error(`Invalid namespace '${namespace}' (did you mean '${match}'?)`);
|
||||
} else {
|
||||
throw new Error(`Invalid namespace '${namespace}'`);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.discloseVersion == undefined) {
|
||||
options.discloseVersion = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `compile` takes your component source code, and turns it into a JavaScript module that exports a class.
|
||||
*
|
||||
* https://svelte.dev/docs/svelte-compiler#svelte-compile
|
||||
* @param {string} source
|
||||
* @param {import('../interfaces.js').CompileOptions} options
|
||||
*/
|
||||
export default function compile(source, options = {}) {
|
||||
options = Object.assign(
|
||||
{ generate: 'dom', dev: false, enableSourcemap: true, css: 'injected' },
|
||||
options
|
||||
);
|
||||
const stats = new Stats();
|
||||
const warnings = [];
|
||||
validate_options(options, warnings);
|
||||
stats.start('parse');
|
||||
const ast = parse(source, options);
|
||||
stats.stop('parse');
|
||||
stats.start('create component');
|
||||
const component = new Component(
|
||||
ast,
|
||||
source,
|
||||
options.name || get_name_from_filename(options.filename) || 'Component',
|
||||
options,
|
||||
stats,
|
||||
warnings
|
||||
);
|
||||
stats.stop('create component');
|
||||
const result =
|
||||
options.generate === false
|
||||
? null
|
||||
: options.generate === 'ssr'
|
||||
? render_ssr(component, options)
|
||||
: render_dom(component, options);
|
||||
return component.generate(result);
|
||||
}
|
2
node_modules/svelte/src/compiler/compile/internal_exports.js
generated
vendored
Normal file
2
node_modules/svelte/src/compiler/compile/internal_exports.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// This file is automatically generated
|
||||
export default new Set(["HtmlTag","HtmlTagHydration","ResizeObserverSingleton","SvelteComponent","SvelteComponentDev","SvelteComponentTyped","SvelteElement","action_destroyer","add_attribute","add_classes","add_flush_callback","add_iframe_resize_listener","add_location","add_render_callback","add_styles","add_transform","afterUpdate","append","append_dev","append_empty_stylesheet","append_hydration","append_hydration_dev","append_styles","assign","attr","attr_dev","attribute_to_object","beforeUpdate","bind","binding_callbacks","blank_object","bubble","check_outros","children","claim_comment","claim_component","claim_element","claim_html_tag","claim_space","claim_svg_element","claim_text","clear_loops","comment","component_subscribe","compute_rest_props","compute_slots","construct_svelte_component","construct_svelte_component_dev","contenteditable_truthy_values","createEventDispatcher","create_animation","create_bidirectional_transition","create_component","create_custom_element","create_in_transition","create_out_transition","create_slot","create_ssr_component","current_component","custom_event","dataset_dev","debug","destroy_block","destroy_component","destroy_each","detach","detach_after_dev","detach_before_dev","detach_between_dev","detach_dev","dirty_components","dispatch_dev","each","element","element_is","empty","end_hydrating","ensure_array_like","ensure_array_like_dev","escape","escape_attribute_value","escape_object","exclude_internal_props","fix_and_destroy_block","fix_and_outro_and_destroy_block","fix_position","flush","flush_render_callbacks","getAllContexts","getContext","get_all_dirty_from_scope","get_binding_group_value","get_current_component","get_custom_elements_slots","get_root_for_style","get_slot_changes","get_spread_object","get_spread_update","get_store_value","get_svelte_dataset","globals","group_outros","handle_promise","hasContext","has_prop","head_selector","identity","init","init_binding_group","init_binding_group_dynamic","insert","insert_dev","insert_hydration","insert_hydration_dev","intros","invalid_attribute_name_character","is_client","is_crossorigin","is_empty","is_function","is_promise","is_void","listen","listen_dev","loop","loop_guard","merge_ssr_styles","missing_component","mount_component","noop","not_equal","now","null_to_empty","object_without_properties","onDestroy","onMount","once","outro_and_destroy_block","prevent_default","prop_dev","query_selector_all","raf","resize_observer_border_box","resize_observer_content_box","resize_observer_device_pixel_content_box","run","run_all","safe_not_equal","schedule_update","select_multiple_value","select_option","select_options","select_value","self","setContext","set_attributes","set_current_component","set_custom_element_data","set_custom_element_data_map","set_data","set_data_contenteditable","set_data_contenteditable_dev","set_data_dev","set_data_maybe_contenteditable","set_data_maybe_contenteditable_dev","set_dynamic_element_data","set_input_type","set_input_value","set_now","set_raf","set_store_value","set_style","set_svg_attributes","space","split_css_unit","spread","src_url_equal","srcset_url_equal","start_hydrating","stop_immediate_propagation","stop_propagation","subscribe","svg_element","text","tick","time_ranges_to_array","to_number","toggle_class","transition_in","transition_out","trusted","update_await_block_branch","update_keyed_each","update_slot","update_slot_base","validate_component","validate_dynamic_element","validate_each_keys","validate_slots","validate_store","validate_void_dynamic_element","xlink_attr"]);
|
36
node_modules/svelte/src/compiler/compile/nodes/Action.js
generated
vendored
Normal file
36
node_modules/svelte/src/compiler/compile/nodes/Action.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
|
||||
/** @extends Node<'Action'> */
|
||||
export default class Action extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {boolean} */
|
||||
uses_context;
|
||||
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
template_scope;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component *
|
||||
* @param {import('./shared/Node.js').default} parent *
|
||||
* @param {import('./shared/TemplateScope.js').default} scope *
|
||||
* @param {import('../../interfaces.js').Directive} info undefined
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
const object = info.name.split('.')[0];
|
||||
component.warn_if_undefined(object, info, scope);
|
||||
this.name = info.name;
|
||||
component.add_reference(/** @type {any} */ (this), object);
|
||||
this.expression = info.expression
|
||||
? new Expression(component, this, scope, info.expression)
|
||||
: null;
|
||||
this.template_scope = scope;
|
||||
this.uses_context = this.expression && this.expression.uses_context;
|
||||
}
|
||||
}
|
43
node_modules/svelte/src/compiler/compile/nodes/Animation.js
generated
vendored
Normal file
43
node_modules/svelte/src/compiler/compile/nodes/Animation.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
/** @extends Node<'Animation'> */
|
||||
export default class Animation extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component *
|
||||
* @param {import('./Element.js').default} parent *
|
||||
* @param {import('./shared/TemplateScope.js').default} scope *
|
||||
* @param {import('../../interfaces.js').TemplateNode} info undefined
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
component.warn_if_undefined(info.name, info, scope);
|
||||
this.name = info.name;
|
||||
component.add_reference(/** @type {any} */ (this), info.name.split('.')[0]);
|
||||
if (parent.animation) {
|
||||
component.error(this, compiler_errors.duplicate_animation);
|
||||
return;
|
||||
}
|
||||
const block = parent.parent;
|
||||
if (!block || block.type !== 'EachBlock') {
|
||||
// TODO can we relax the 'immediate child' rule?
|
||||
component.error(this, compiler_errors.invalid_animation_immediate);
|
||||
return;
|
||||
}
|
||||
if (!block.key) {
|
||||
component.error(this, compiler_errors.invalid_animation_key);
|
||||
return;
|
||||
}
|
||||
/** @type {import('./EachBlock.js').default} */ (block).has_animation = true;
|
||||
this.expression = info.expression
|
||||
? new Expression(component, this, scope, info.expression, true)
|
||||
: null;
|
||||
}
|
||||
}
|
136
node_modules/svelte/src/compiler/compile/nodes/Attribute.js
generated
vendored
Normal file
136
node_modules/svelte/src/compiler/compile/nodes/Attribute.js
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
import { string_literal } from '../utils/stringify.js';
|
||||
import add_to_set from '../utils/add_to_set.js';
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import { x } from 'code-red';
|
||||
import compiler_warnings from '../compiler_warnings.js';
|
||||
|
||||
/** @extends Node<'Attribute' | 'Spread', import('./Element.js').default> */
|
||||
export default class Attribute extends Node {
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_spread;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_true;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_static;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {Array<import('./Text.js').default | import('./shared/Expression.js').default>} */
|
||||
chunks;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
dependencies;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope;
|
||||
|
||||
if (info.type === 'Spread') {
|
||||
this.name = null;
|
||||
this.is_spread = true;
|
||||
this.is_true = false;
|
||||
this.expression = new Expression(component, this, scope, info.expression);
|
||||
this.dependencies = this.expression.dependencies;
|
||||
this.chunks = null;
|
||||
this.is_static = false;
|
||||
} else {
|
||||
this.name = info.name;
|
||||
this.is_true = info.value === true;
|
||||
this.is_static = true;
|
||||
this.dependencies = new Set();
|
||||
this.chunks = this.is_true
|
||||
? []
|
||||
: info.value.map((node) => {
|
||||
if (node.type === 'Text') return node;
|
||||
this.is_static = false;
|
||||
const expression = new Expression(component, this, scope, node.expression);
|
||||
add_to_set(this.dependencies, expression.dependencies);
|
||||
return expression;
|
||||
});
|
||||
}
|
||||
|
||||
if (this.dependencies.size > 0) {
|
||||
parent.cannot_use_innerhtml();
|
||||
parent.not_static_content();
|
||||
}
|
||||
|
||||
// TODO Svelte 5: Think about moving this into the parser and make it an error
|
||||
if (
|
||||
this.name &&
|
||||
this.name.includes(':') &&
|
||||
!this.name.startsWith('xmlns:') &&
|
||||
!this.name.startsWith('xlink:') &&
|
||||
!this.name.startsWith('xml:')
|
||||
) {
|
||||
component.warn(this, compiler_warnings.illegal_attribute_character);
|
||||
}
|
||||
}
|
||||
get_dependencies() {
|
||||
if (this.is_spread) return this.expression.dynamic_dependencies();
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const dependencies = new Set();
|
||||
this.chunks.forEach((chunk) => {
|
||||
if (chunk.type === 'Expression') {
|
||||
add_to_set(dependencies, chunk.dynamic_dependencies());
|
||||
}
|
||||
});
|
||||
return Array.from(dependencies);
|
||||
}
|
||||
|
||||
/** @param {any} block */
|
||||
get_value(block) {
|
||||
if (this.is_true) return x`true`;
|
||||
if (this.chunks.length === 0) return x`""`;
|
||||
if (this.chunks.length === 1) {
|
||||
return this.chunks[0].type === 'Text'
|
||||
? string_literal(/** @type {import('./Text.js').default} */ (this.chunks[0]).data)
|
||||
: /** @type {import('./shared/Expression.js').default} */ (this.chunks[0]).manipulate(
|
||||
block
|
||||
);
|
||||
}
|
||||
let expression = this.chunks
|
||||
.map(
|
||||
/** @param {any} chunk */ (chunk) =>
|
||||
chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block)
|
||||
)
|
||||
.reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
|
||||
if (this.chunks[0].type !== 'Text') {
|
||||
expression = x`"" + ${expression}`;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
get_static_value() {
|
||||
if (!this.is_static) return null;
|
||||
return this.is_true
|
||||
? true
|
||||
: this.chunks[0]
|
||||
? // method should be called only when `is_static = true`
|
||||
/** @type {import('./Text.js').default} */ (this.chunks[0]).data
|
||||
: '';
|
||||
}
|
||||
should_cache() {
|
||||
return this.is_static
|
||||
? false
|
||||
: this.chunks.length === 1
|
||||
? // @ts-ignore todo: probably error
|
||||
this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name)
|
||||
: true;
|
||||
}
|
||||
}
|
74
node_modules/svelte/src/compiler/compile/nodes/AwaitBlock.js
generated
vendored
Normal file
74
node_modules/svelte/src/compiler/compile/nodes/AwaitBlock.js
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
import Node from './shared/Node.js';
|
||||
import PendingBlock from './PendingBlock.js';
|
||||
import ThenBlock from './ThenBlock.js';
|
||||
import CatchBlock from './CatchBlock.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import { unpack_destructuring } from './shared/Context.js';
|
||||
|
||||
/** @extends Node<'AwaitBlock'> */
|
||||
export default class AwaitBlock extends Node {
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('./shared/Context.js').Context[]} */
|
||||
then_contexts;
|
||||
|
||||
/** @type {import('./shared/Context.js').Context[]} */
|
||||
catch_contexts;
|
||||
|
||||
/** @type {import('estree').Node | null} */
|
||||
then_node;
|
||||
|
||||
/** @type {import('estree').Node | null} */
|
||||
catch_node;
|
||||
|
||||
/** @type {import('./PendingBlock.js').default} */
|
||||
pending;
|
||||
|
||||
/** @type {import('./ThenBlock.js').default} */
|
||||
then;
|
||||
|
||||
/** @type {import('./CatchBlock.js').default} */
|
||||
catch;
|
||||
|
||||
/** @type {Map<string, import('estree').Node>} */
|
||||
context_rest_properties = new Map();
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
this.expression = new Expression(component, this, scope, info.expression);
|
||||
this.then_node = info.value;
|
||||
this.catch_node = info.error;
|
||||
if (this.then_node) {
|
||||
this.then_contexts = [];
|
||||
unpack_destructuring({
|
||||
contexts: this.then_contexts,
|
||||
node: info.value,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties: this.context_rest_properties
|
||||
});
|
||||
}
|
||||
if (this.catch_node) {
|
||||
this.catch_contexts = [];
|
||||
unpack_destructuring({
|
||||
contexts: this.catch_contexts,
|
||||
node: info.error,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties: this.context_rest_properties
|
||||
});
|
||||
}
|
||||
this.pending = new PendingBlock(component, this, scope, info.pending);
|
||||
this.then = new ThenBlock(component, this, scope, info.then);
|
||||
this.catch = new CatchBlock(component, this, scope, info.catch);
|
||||
}
|
||||
}
|
132
node_modules/svelte/src/compiler/compile/nodes/Binding.js
generated
vendored
Normal file
132
node_modules/svelte/src/compiler/compile/nodes/Binding.js
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
import Node from './shared/Node.js';
|
||||
import get_object from '../utils/get_object.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import { regex_dimensions, regex_box_size } from '../../utils/patterns.js';
|
||||
import { clone } from '../../utils/clone.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import compiler_warnings from '../compiler_warnings.js';
|
||||
|
||||
// TODO this should live in a specific binding
|
||||
const read_only_media_attributes = new Set([
|
||||
'duration',
|
||||
'buffered',
|
||||
'seekable',
|
||||
'played',
|
||||
'seeking',
|
||||
'ended',
|
||||
'videoHeight',
|
||||
'videoWidth',
|
||||
'naturalWidth',
|
||||
'naturalHeight',
|
||||
'readyState'
|
||||
]);
|
||||
|
||||
/** @extends Node<'Binding'> */
|
||||
export default class Binding extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('estree').Node} */
|
||||
raw_expression; // TODO exists only for bind:this — is there a more elegant solution?
|
||||
|
||||
/** @type {boolean} */
|
||||
is_contextual;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_readonly;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./Element.js').default | import('./InlineComponent.js').default | import('./Window.js').default | import('./Document.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
if (info.expression.type !== 'Identifier' && info.expression.type !== 'MemberExpression') {
|
||||
component.error(info, compiler_errors.invalid_directive_value);
|
||||
return;
|
||||
}
|
||||
this.name = info.name;
|
||||
this.expression = new Expression(component, this, scope, info.expression);
|
||||
this.raw_expression = clone(info.expression);
|
||||
const { name } = get_object(this.expression.node);
|
||||
this.is_contextual = Array.from(this.expression.references).some((name) =>
|
||||
scope.names.has(name)
|
||||
);
|
||||
if (this.is_contextual) this.validate_binding_rest_properties(scope);
|
||||
// make sure we track this as a mutable ref
|
||||
if (scope.is_let(name)) {
|
||||
component.error(this, compiler_errors.invalid_binding_let);
|
||||
return;
|
||||
} else if (scope.names.has(name)) {
|
||||
if (scope.is_await(name)) {
|
||||
component.error(this, compiler_errors.invalid_binding_await);
|
||||
return;
|
||||
}
|
||||
if (scope.is_const(name)) {
|
||||
component.error(this, compiler_errors.invalid_binding_const);
|
||||
}
|
||||
scope.dependencies_for_name.get(name).forEach((name) => {
|
||||
const variable = component.var_lookup.get(name);
|
||||
if (variable) {
|
||||
variable.mutated = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const variable = component.var_lookup.get(name);
|
||||
if (!variable || variable.global) {
|
||||
component.error(
|
||||
/** @type {any} */ (this.expression.node),
|
||||
compiler_errors.binding_undeclared(name)
|
||||
);
|
||||
return;
|
||||
}
|
||||
variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true;
|
||||
if (info.expression.type === 'Identifier' && !variable.writable) {
|
||||
component.error(
|
||||
/** @type {any} */ (this.expression.node),
|
||||
compiler_errors.invalid_binding_writable
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const type = parent.get_static_attribute_value('type');
|
||||
this.is_readonly =
|
||||
regex_dimensions.test(this.name) ||
|
||||
regex_box_size.test(this.name) ||
|
||||
(is_element(parent) &&
|
||||
((parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
|
||||
(parent.name === 'input' && type === 'file'))) /* TODO others? */;
|
||||
}
|
||||
is_readonly_media_attribute() {
|
||||
return read_only_media_attributes.has(this.name);
|
||||
}
|
||||
|
||||
/** @param {import('./shared/TemplateScope.js').default} scope */
|
||||
validate_binding_rest_properties(scope) {
|
||||
this.expression.references.forEach((name) => {
|
||||
const each_block = scope.get_owner(name);
|
||||
if (each_block && each_block.type === 'EachBlock') {
|
||||
const rest_node = each_block.context_rest_properties.get(name);
|
||||
if (rest_node) {
|
||||
this.component.warn(
|
||||
/** @type {any} */ (rest_node),
|
||||
compiler_warnings.invalid_rest_eachblock_binding(name)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./shared/Node.js').default} node
|
||||
* @returns {node is import('./Element.js').default}
|
||||
*/
|
||||
function is_element(node) {
|
||||
return !!(/** @type {any} */ (node).is_media_node);
|
||||
}
|
31
node_modules/svelte/src/compiler/compile/nodes/Body.js
generated
vendored
Normal file
31
node_modules/svelte/src/compiler/compile/nodes/Body.js
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
import Node from './shared/Node.js';
|
||||
import EventHandler from './EventHandler.js';
|
||||
import Action from './Action.js';
|
||||
|
||||
/** @extends Node<'Body'> */
|
||||
export default class Body extends Node {
|
||||
/** @type {import('./EventHandler.js').default[]} */
|
||||
handlers = [];
|
||||
|
||||
/** @type {import('./Action.js').default[]} */
|
||||
actions = [];
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').Element} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
info.attributes.forEach((node) => {
|
||||
if (node.type === 'EventHandler') {
|
||||
this.handlers.push(new EventHandler(component, this, scope, node));
|
||||
} else if (node.type === 'Action') {
|
||||
this.actions.push(new Action(component, this, scope, node));
|
||||
} else {
|
||||
// TODO there shouldn't be anything else here...
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
32
node_modules/svelte/src/compiler/compile/nodes/CatchBlock.js
generated
vendored
Normal file
32
node_modules/svelte/src/compiler/compile/nodes/CatchBlock.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
import get_const_tags from './shared/get_const_tags.js';
|
||||
|
||||
/** @extends AbstractBlock<'CatchBlock'> */
|
||||
export default class CatchBlock extends AbstractBlock {
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {import('./ConstTag.js').default[]} */
|
||||
const_tags;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./AwaitBlock.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope.child();
|
||||
if (parent.catch_node) {
|
||||
parent.catch_contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
this.scope.add(context.key.name, parent.expression.dependencies, this);
|
||||
});
|
||||
}
|
||||
[this.const_tags, this.children] = get_const_tags(info.children, component, this, parent);
|
||||
if (!info.skip) {
|
||||
this.warn_if_empty_block();
|
||||
}
|
||||
}
|
||||
}
|
25
node_modules/svelte/src/compiler/compile/nodes/Class.js
generated
vendored
Normal file
25
node_modules/svelte/src/compiler/compile/nodes/Class.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
|
||||
/** @extends Node<'Class'> */
|
||||
export default class Class extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.name = info.name;
|
||||
this.expression = info.expression
|
||||
? new Expression(component, this, scope, info.expression)
|
||||
: null;
|
||||
}
|
||||
}
|
22
node_modules/svelte/src/compiler/compile/nodes/Comment.js
generated
vendored
Normal file
22
node_modules/svelte/src/compiler/compile/nodes/Comment.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
import Node from './shared/Node.js';
|
||||
|
||||
/** @extends Node<'Comment'> */
|
||||
export default class Comment extends Node {
|
||||
/** @type {string} */
|
||||
data;
|
||||
|
||||
/** @type {string[]} */
|
||||
ignores;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.data = info.data;
|
||||
this.ignores = info.ignores;
|
||||
}
|
||||
}
|
104
node_modules/svelte/src/compiler/compile/nodes/ConstTag.js
generated
vendored
Normal file
104
node_modules/svelte/src/compiler/compile/nodes/ConstTag.js
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import { unpack_destructuring } from './shared/Context.js';
|
||||
import { walk } from 'estree-walker';
|
||||
import { extract_identifiers } from 'periscopic';
|
||||
import is_reference from 'is-reference';
|
||||
import get_object from '../utils/get_object.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
const allowed_parents = new Set([
|
||||
'EachBlock',
|
||||
'CatchBlock',
|
||||
'ThenBlock',
|
||||
'InlineComponent',
|
||||
'SlotTemplate',
|
||||
'IfBlock',
|
||||
'ElseBlock'
|
||||
]);
|
||||
|
||||
/** @extends Node<'ConstTag'> */
|
||||
export default class ConstTag extends Node {
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('./shared/Context.js').Context[]} */
|
||||
contexts = [];
|
||||
|
||||
/** @type {import('../../interfaces.js').ConstTag} */
|
||||
node;
|
||||
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {Map<string, import('estree').Node>} */
|
||||
context_rest_properties = new Map();
|
||||
|
||||
/** @type {Set<string>} */
|
||||
assignees = new Set();
|
||||
|
||||
/** @type {Set<string>} */
|
||||
dependencies = new Set();
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./interfaces.js').INodeAllowConstTag} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').ConstTag} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
if (!allowed_parents.has(parent.type)) {
|
||||
component.error(info, compiler_errors.invalid_const_placement);
|
||||
}
|
||||
this.node = info;
|
||||
this.scope = scope;
|
||||
const { assignees, dependencies } = this;
|
||||
extract_identifiers(info.expression.left).forEach(({ name }) => {
|
||||
assignees.add(name);
|
||||
const owner = this.scope.get_owner(name);
|
||||
if (owner === parent) {
|
||||
component.error(info, compiler_errors.invalid_const_declaration(name));
|
||||
}
|
||||
});
|
||||
walk(info.expression.right, {
|
||||
/**
|
||||
* @type {import('estree-walker').SyncHandler}
|
||||
*/
|
||||
enter(node, parent) {
|
||||
if (
|
||||
is_reference(
|
||||
/** @type {import('is-reference').NodeWithPropertyDefinition} */ (node),
|
||||
/** @type {import('is-reference').NodeWithPropertyDefinition} */ (parent)
|
||||
)
|
||||
) {
|
||||
const identifier = get_object(node);
|
||||
const { name } = identifier;
|
||||
dependencies.add(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
parse_expression() {
|
||||
unpack_destructuring({
|
||||
contexts: this.contexts,
|
||||
node: this.node.expression.left,
|
||||
scope: this.scope,
|
||||
component: this.component,
|
||||
context_rest_properties: this.context_rest_properties
|
||||
});
|
||||
this.expression = new Expression(this.component, this, this.scope, this.node.expression.right);
|
||||
this.contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
const owner = this.scope.get_owner(context.key.name);
|
||||
if (owner && owner.type === 'ConstTag' && owner.parent === this.parent) {
|
||||
this.component.error(
|
||||
this.node,
|
||||
compiler_errors.invalid_const_declaration(context.key.name)
|
||||
);
|
||||
}
|
||||
this.scope.add(context.key.name, this.expression.dependencies, this);
|
||||
});
|
||||
}
|
||||
}
|
23
node_modules/svelte/src/compiler/compile/nodes/DebugTag.js
generated
vendored
Normal file
23
node_modules/svelte/src/compiler/compile/nodes/DebugTag.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
|
||||
/** @extends Node<'DebugTag'> */
|
||||
export default class DebugTag extends Node {
|
||||
/** @type {import('./shared/Expression.js').default[]} */
|
||||
expressions;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./interfaces.js').INode} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.expressions = info.identifiers.map(
|
||||
/** @param {import('estree').Node} node */ (node) => {
|
||||
return new Expression(component, parent, scope, node);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
75
node_modules/svelte/src/compiler/compile/nodes/Document.js
generated
vendored
Normal file
75
node_modules/svelte/src/compiler/compile/nodes/Document.js
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Binding from './Binding.js';
|
||||
import EventHandler from './EventHandler.js';
|
||||
import fuzzymatch from '../../utils/fuzzymatch.js';
|
||||
import Action from './Action.js';
|
||||
import list from '../../utils/list.js';
|
||||
import compiler_warnings from '../compiler_warnings.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
const valid_bindings = ['fullscreenElement', 'visibilityState'];
|
||||
|
||||
/** @extends Node<'Document'> */
|
||||
export default class Document extends Node {
|
||||
/** @type {import('./EventHandler.js').default[]} */
|
||||
handlers = [];
|
||||
|
||||
/** @type {import('./Binding.js').default[]} */
|
||||
bindings = [];
|
||||
|
||||
/** @type {import('./Action.js').default[]} */
|
||||
actions = [];
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').Element} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
info.attributes.forEach((node) => {
|
||||
if (node.type === 'EventHandler') {
|
||||
this.handlers.push(new EventHandler(component, this, scope, node));
|
||||
} else if (node.type === 'Binding') {
|
||||
if (!~valid_bindings.indexOf(node.name)) {
|
||||
const match = fuzzymatch(node.name, valid_bindings);
|
||||
if (match) {
|
||||
return component.error(
|
||||
node,
|
||||
compiler_errors.invalid_binding_on(
|
||||
node.name,
|
||||
'<svelte:document>',
|
||||
` (did you mean '${match}'?)`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return component.error(
|
||||
node,
|
||||
compiler_errors.invalid_binding_on(
|
||||
node.name,
|
||||
'<svelte:document>',
|
||||
` — valid bindings are ${list(valid_bindings)}`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
this.bindings.push(new Binding(component, this, scope, node));
|
||||
} else if (node.type === 'Action') {
|
||||
this.actions.push(new Action(component, this, scope, node));
|
||||
} else {
|
||||
// TODO there shouldn't be anything else here...
|
||||
}
|
||||
});
|
||||
this.validate();
|
||||
}
|
||||
|
||||
/** @private */
|
||||
validate() {
|
||||
const handlers_map = new Set();
|
||||
this.handlers.forEach((handler) => handlers_map.add(handler.name));
|
||||
if (handlers_map.has('mouseenter') || handlers_map.has('mouseleave')) {
|
||||
this.component.warn(this, compiler_warnings.avoid_mouse_events_on_document);
|
||||
}
|
||||
}
|
||||
}
|
114
node_modules/svelte/src/compiler/compile/nodes/EachBlock.js
generated
vendored
Normal file
114
node_modules/svelte/src/compiler/compile/nodes/EachBlock.js
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
import ElseBlock from './ElseBlock.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
import { unpack_destructuring } from './shared/Context.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import get_const_tags from './shared/get_const_tags.js';
|
||||
|
||||
/** @extends AbstractBlock<'EachBlock'> */
|
||||
export default class EachBlock extends AbstractBlock {
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('estree').Node} */
|
||||
context_node;
|
||||
|
||||
/** @type {string} */
|
||||
iterations;
|
||||
|
||||
/** @type {string} */
|
||||
index;
|
||||
|
||||
/** @type {string} */
|
||||
context;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
key;
|
||||
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {import('./shared/Context.js').Context[]} */
|
||||
contexts;
|
||||
|
||||
/** @type {import('./ConstTag.js').default[]} */
|
||||
const_tags;
|
||||
|
||||
/** @type {boolean} */
|
||||
has_animation;
|
||||
/** */
|
||||
has_binding = false;
|
||||
/** */
|
||||
has_index_binding = false;
|
||||
|
||||
/** @type {Map<string, import('estree').Node>} */
|
||||
context_rest_properties;
|
||||
|
||||
/** @type {import('./ElseBlock.js').default} */
|
||||
else;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('estree').Node} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
this.expression = new Expression(component, this, scope, info.expression);
|
||||
this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
|
||||
this.context_node = info.context;
|
||||
this.index = info.index;
|
||||
this.scope = scope.child();
|
||||
this.context_rest_properties = new Map();
|
||||
this.contexts = [];
|
||||
unpack_destructuring({
|
||||
contexts: this.contexts,
|
||||
node: info.context,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties: this.context_rest_properties
|
||||
});
|
||||
this.contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
this.scope.add(context.key.name, this.expression.dependencies, this);
|
||||
});
|
||||
if (this.index) {
|
||||
// index can only change if this is a keyed each block
|
||||
const dependencies = info.key ? this.expression.dependencies : new Set([]);
|
||||
this.scope.add(this.index, dependencies, this);
|
||||
}
|
||||
this.key = info.key ? new Expression(component, this, this.scope, info.key) : null;
|
||||
this.has_animation = false;
|
||||
[this.const_tags, this.children] = get_const_tags(info.children, component, this, this);
|
||||
if (this.has_animation) {
|
||||
this.children = this.children.filter(
|
||||
(child) => !is_empty_node(child) && !is_comment_node(child)
|
||||
);
|
||||
if (this.children.length !== 1) {
|
||||
const child = this.children.find(
|
||||
(child) => !!(/** @type {import('./Element.js').default} */ (child).animation)
|
||||
);
|
||||
component.error(
|
||||
/** @type {import('./Element.js').default} */ (child).animation,
|
||||
compiler_errors.invalid_animation_sole
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.warn_if_empty_block();
|
||||
this.else = info.else ? new ElseBlock(component, this, this.scope, info.else) : null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('./interfaces.js').INode} node */
|
||||
function is_empty_node(node) {
|
||||
return node.type === 'Text' && node.data.trim() === '';
|
||||
}
|
||||
|
||||
/** @param {import('./interfaces.js').INode} node */
|
||||
function is_comment_node(node) {
|
||||
return node.type === 'Comment';
|
||||
}
|
1450
node_modules/svelte/src/compiler/compile/nodes/Element.js
generated
vendored
Normal file
1450
node_modules/svelte/src/compiler/compile/nodes/Element.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
24
node_modules/svelte/src/compiler/compile/nodes/ElseBlock.js
generated
vendored
Normal file
24
node_modules/svelte/src/compiler/compile/nodes/ElseBlock.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
import get_const_tags from './shared/get_const_tags.js';
|
||||
|
||||
/** @extends AbstractBlock<'ElseBlock'> */
|
||||
export default class ElseBlock extends AbstractBlock {
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {import('./ConstTag.js').default[]} */
|
||||
const_tags;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope.child();
|
||||
[this.const_tags, this.children] = get_const_tags(info.children, component, this, this);
|
||||
this.warn_if_empty_block();
|
||||
}
|
||||
}
|
82
node_modules/svelte/src/compiler/compile/nodes/EventHandler.js
generated
vendored
Normal file
82
node_modules/svelte/src/compiler/compile/nodes/EventHandler.js
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import { sanitize } from '../../utils/names.js';
|
||||
|
||||
const regex_contains_term_function_expression = /FunctionExpression/;
|
||||
|
||||
/** @extends Node<'EventHandler'> */
|
||||
export default class EventHandler extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
modifiers;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
handler_name;
|
||||
/** */
|
||||
uses_context = false;
|
||||
/** */
|
||||
can_make_passive = false;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} template_scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, template_scope, info) {
|
||||
super(component, parent, template_scope, info);
|
||||
this.name = info.name;
|
||||
this.modifiers = new Set(info.modifiers);
|
||||
if (info.expression) {
|
||||
this.expression = new Expression(component, this, template_scope, info.expression);
|
||||
this.uses_context = this.expression.uses_context;
|
||||
if (
|
||||
regex_contains_term_function_expression.test(info.expression.type) &&
|
||||
info.expression.params.length === 0
|
||||
) {
|
||||
// TODO make this detection more accurate — if `event.preventDefault` isn't called, and
|
||||
// `event` is passed to another function, we can make it passive
|
||||
this.can_make_passive = true;
|
||||
} else if (info.expression.type === 'Identifier') {
|
||||
let node = component.node_for_declaration.get(info.expression.name);
|
||||
if (node) {
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
// for `const handleClick = () => {...}`, we want the [arrow] function expression node
|
||||
const declarator = node.declarations.find(
|
||||
(d) => /** @type {import('estree').Identifier} */ (d.id).name === info.expression.name
|
||||
);
|
||||
node = declarator && declarator.init;
|
||||
}
|
||||
if (
|
||||
node &&
|
||||
(node.type === 'FunctionExpression' ||
|
||||
node.type === 'FunctionDeclaration' ||
|
||||
node.type === 'ArrowFunctionExpression') &&
|
||||
node.params.length === 0
|
||||
) {
|
||||
this.can_make_passive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
|
||||
}
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
get reassigned() {
|
||||
if (!this.expression) {
|
||||
return false;
|
||||
}
|
||||
const node = this.expression.node;
|
||||
if (regex_contains_term_function_expression.test(node.type)) {
|
||||
return false;
|
||||
}
|
||||
return this.expression.dynamic_dependencies().length > 0;
|
||||
}
|
||||
}
|
26
node_modules/svelte/src/compiler/compile/nodes/Fragment.js
generated
vendored
Normal file
26
node_modules/svelte/src/compiler/compile/nodes/Fragment.js
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
import Node from './shared/Node.js';
|
||||
import map_children from './shared/map_children.js';
|
||||
import TemplateScope from './shared/TemplateScope.js';
|
||||
|
||||
/** @extends Node<'Fragment'> */
|
||||
export default class Fragment extends Node {
|
||||
/** @type {import('../render_dom/Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('./interfaces.js').INode[]} */
|
||||
children;
|
||||
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, info) {
|
||||
const scope = new TemplateScope();
|
||||
super(component, null, scope, info);
|
||||
this.scope = scope;
|
||||
this.children = map_children(component, this, scope, info.children);
|
||||
}
|
||||
}
|
40
node_modules/svelte/src/compiler/compile/nodes/Head.js
generated
vendored
Normal file
40
node_modules/svelte/src/compiler/compile/nodes/Head.js
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
import Node from './shared/Node.js';
|
||||
import map_children from './shared/map_children.js';
|
||||
import hash from '../utils/hash.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import { regex_non_whitespace_character } from '../../utils/patterns.js';
|
||||
|
||||
/** @extends Node<'Head'> */
|
||||
export default class Head extends Node {
|
||||
/** @type {any[]} */
|
||||
children; // TODO
|
||||
|
||||
/** @type {string} */
|
||||
id;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.cannot_use_innerhtml();
|
||||
if (info.attributes.length) {
|
||||
component.error(info.attributes[0], compiler_errors.invalid_attribute_head);
|
||||
return;
|
||||
}
|
||||
this.children = map_children(
|
||||
component,
|
||||
parent,
|
||||
scope,
|
||||
info.children.filter((child) => {
|
||||
return child.type !== 'Text' || regex_non_whitespace_character.test(child.data);
|
||||
})
|
||||
);
|
||||
if (this.children.length > 0) {
|
||||
this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
|
||||
}
|
||||
}
|
||||
}
|
36
node_modules/svelte/src/compiler/compile/nodes/IfBlock.js
generated
vendored
Normal file
36
node_modules/svelte/src/compiler/compile/nodes/IfBlock.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import ElseBlock from './ElseBlock.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
import get_const_tags from './shared/get_const_tags.js';
|
||||
|
||||
/** @extends AbstractBlock<'IfBlock'> */
|
||||
export default class IfBlock extends AbstractBlock {
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('./ElseBlock.js').default} */
|
||||
else;
|
||||
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {import('./ConstTag.js').default[]} */
|
||||
const_tags;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope.child();
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
this.expression = new Expression(component, this, this.scope, info.expression);
|
||||
[this.const_tags, this.children] = get_const_tags(info.children, component, this, this);
|
||||
this.else = info.else ? new ElseBlock(component, this, scope, info.else) : null;
|
||||
this.warn_if_empty_block();
|
||||
}
|
||||
}
|
199
node_modules/svelte/src/compiler/compile/nodes/InlineComponent.js
generated
vendored
Normal file
199
node_modules/svelte/src/compiler/compile/nodes/InlineComponent.js
generated
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Attribute from './Attribute.js';
|
||||
import map_children from './shared/map_children.js';
|
||||
import Binding from './Binding.js';
|
||||
import EventHandler from './EventHandler.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import { regex_only_whitespaces } from '../../utils/patterns.js';
|
||||
|
||||
/** @extends Node<'InlineComponent'> */
|
||||
export default class InlineComponent extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {import('./Binding.js').default[]} */
|
||||
bindings = [];
|
||||
|
||||
/** @type {import('./EventHandler.js').default[]} */
|
||||
handlers = [];
|
||||
|
||||
/** @type {import('./Attribute.js').default[]} */
|
||||
css_custom_properties = [];
|
||||
|
||||
/** @type {import('./interfaces.js').INode[]} */
|
||||
children;
|
||||
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {string} */
|
||||
namespace;
|
||||
|
||||
/** @type {Attribute[]} */
|
||||
let_attributes;
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
|
||||
const name = info.name.split('.')[0]; // accommodate namespaces
|
||||
component.warn_if_undefined(name, info, scope);
|
||||
component.add_reference(/** @type {any} */ (this), name);
|
||||
}
|
||||
this.name = info.name;
|
||||
this.namespace = get_namespace(parent, component.namespace);
|
||||
this.expression =
|
||||
this.name === 'svelte:component'
|
||||
? new Expression(component, this, scope, info.expression)
|
||||
: null;
|
||||
|
||||
const let_attributes = (this.let_attributes = []);
|
||||
info.attributes.forEach(
|
||||
/** @param {import('../../interfaces.js').BaseDirective | import('../../interfaces.js').Attribute | import('../../interfaces.js').SpreadAttribute} node */ (
|
||||
node
|
||||
) => {
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (node.type) {
|
||||
case 'Action':
|
||||
return component.error(node, compiler_errors.invalid_action);
|
||||
case 'Attribute':
|
||||
if (node.name.startsWith('--')) {
|
||||
this.css_custom_properties.push(new Attribute(component, this, scope, node));
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
case 'Spread':
|
||||
this.attributes.push(new Attribute(component, this, scope, node));
|
||||
break;
|
||||
case 'Binding':
|
||||
this.bindings.push(new Binding(component, this, scope, node));
|
||||
break;
|
||||
case 'Class':
|
||||
return component.error(node, compiler_errors.invalid_class);
|
||||
case 'EventHandler':
|
||||
this.handlers.push(new EventHandler(component, this, scope, node));
|
||||
break;
|
||||
case 'Let':
|
||||
let_attributes.push(node);
|
||||
break;
|
||||
case 'Transition':
|
||||
return component.error(node, compiler_errors.invalid_transition);
|
||||
case 'StyleDirective':
|
||||
return component.error(node, compiler_errors.invalid_component_style_directive);
|
||||
case 'Animation':
|
||||
return component.error(node, compiler_errors.invalid_animation);
|
||||
default:
|
||||
throw new Error(`Not implemented: ${node.type}`);
|
||||
}
|
||||
/* eslint-enable no-fallthrough */
|
||||
}
|
||||
);
|
||||
|
||||
this.scope = scope;
|
||||
|
||||
this.handlers.forEach((handler) => {
|
||||
handler.modifiers.forEach((modifier) => {
|
||||
if (modifier !== 'once') {
|
||||
return component.error(handler, compiler_errors.invalid_event_modifier_component);
|
||||
}
|
||||
});
|
||||
});
|
||||
const children = [];
|
||||
for (let i = info.children.length - 1; i >= 0; i--) {
|
||||
const child = info.children[i];
|
||||
if (child.type === 'SlotTemplate') {
|
||||
children.push(child);
|
||||
info.children.splice(i, 1);
|
||||
} else if (
|
||||
(child.type === 'Element' || child.type === 'InlineComponent' || child.type === 'Slot') &&
|
||||
child.attributes.find((attribute) => attribute.name === 'slot')
|
||||
) {
|
||||
const slot_template = {
|
||||
start: child.start,
|
||||
end: child.end,
|
||||
type: 'SlotTemplate',
|
||||
name: 'svelte:fragment',
|
||||
attributes: [],
|
||||
children: [child]
|
||||
};
|
||||
// transfer attributes
|
||||
for (let i = child.attributes.length - 1; i >= 0; i--) {
|
||||
const attribute = child.attributes[i];
|
||||
if (attribute.type === 'Let') {
|
||||
slot_template.attributes.push(attribute);
|
||||
child.attributes.splice(i, 1);
|
||||
} else if (attribute.type === 'Attribute' && attribute.name === 'slot') {
|
||||
slot_template.attributes.push(attribute);
|
||||
}
|
||||
}
|
||||
// transfer const
|
||||
for (let i = child.children.length - 1; i >= 0; i--) {
|
||||
const child_child = child.children[i];
|
||||
if (child_child.type === 'ConstTag') {
|
||||
slot_template.children.push(child_child);
|
||||
child.children.splice(i, 1);
|
||||
}
|
||||
}
|
||||
children.push(slot_template);
|
||||
info.children.splice(i, 1);
|
||||
} else if (child.type === 'Comment' && children.length > 0) {
|
||||
children[children.length - 1].children.unshift(child);
|
||||
}
|
||||
}
|
||||
if (info.children.some((node) => not_whitespace_text(node))) {
|
||||
children.push({
|
||||
start: info.start,
|
||||
end: info.end,
|
||||
type: 'SlotTemplate',
|
||||
name: 'svelte:fragment',
|
||||
attributes: [],
|
||||
children: info.children
|
||||
});
|
||||
}
|
||||
|
||||
if (let_attributes.length) {
|
||||
// copy let: attribute from <Component /> to <svelte:fragment slot="default" />
|
||||
// as they are for `slot="default"` only
|
||||
children.forEach((child) => {
|
||||
const slot = child.attributes.find((attribute) => attribute.name === 'slot');
|
||||
if (!slot || slot.value[0].data === 'default') {
|
||||
child.attributes.push(...let_attributes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.children = map_children(component, this, this.scope, children);
|
||||
}
|
||||
get slot_template_name() {
|
||||
return /** @type {string} */ (
|
||||
this.attributes.find((attribute) => attribute.name === 'slot').get_static_value()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {any} node */
|
||||
function not_whitespace_text(node) {
|
||||
return !(node.type === 'Text' && regex_only_whitespaces.test(node.data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {string} explicit_namespace
|
||||
*/
|
||||
function get_namespace(parent, explicit_namespace) {
|
||||
const parent_element = parent.find_nearest(/^Element/);
|
||||
if (!parent_element) {
|
||||
return explicit_namespace;
|
||||
}
|
||||
return parent_element.namespace;
|
||||
}
|
24
node_modules/svelte/src/compiler/compile/nodes/KeyBlock.js
generated
vendored
Normal file
24
node_modules/svelte/src/compiler/compile/nodes/KeyBlock.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
import Expression from './shared/Expression.js';
|
||||
import map_children from './shared/map_children.js';
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
|
||||
/** @extends AbstractBlock<'KeyBlock'> */
|
||||
export default class KeyBlock extends AbstractBlock {
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
this.expression = new Expression(component, this, scope, info.expression);
|
||||
this.children = map_children(component, this, scope, info.children);
|
||||
this.warn_if_empty_block();
|
||||
}
|
||||
}
|
52
node_modules/svelte/src/compiler/compile/nodes/Let.js
generated
vendored
Normal file
52
node_modules/svelte/src/compiler/compile/nodes/Let.js
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
import Node from './shared/Node.js';
|
||||
import { walk } from 'estree-walker';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']);
|
||||
|
||||
/** @extends Node<'Let'> */
|
||||
export default class Let extends Node {
|
||||
/** @type {import('estree').Identifier} */
|
||||
name;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
value;
|
||||
|
||||
/** @type {string[]} */
|
||||
names = [];
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.name = { type: 'Identifier', name: info.name };
|
||||
const { names } = this;
|
||||
if (info.expression) {
|
||||
this.value = info.expression;
|
||||
walk(info.expression, {
|
||||
/** @param {import('estree').Identifier | import('estree').BasePattern} node */
|
||||
enter(node) {
|
||||
if (!applicable.has(node.type)) {
|
||||
return component.error(/** @type {any} */ (node), compiler_errors.invalid_let);
|
||||
}
|
||||
if (node.type === 'Identifier') {
|
||||
names.push(/** @type {import('estree').Identifier} */ (node).name);
|
||||
}
|
||||
// slightly unfortunate hack
|
||||
if (node.type === 'ArrayExpression') {
|
||||
node.type = 'ArrayPattern';
|
||||
}
|
||||
if (node.type === 'ObjectExpression') {
|
||||
node.type = 'ObjectPattern';
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
names.push(this.name.name);
|
||||
}
|
||||
}
|
||||
}
|
4
node_modules/svelte/src/compiler/compile/nodes/MustacheTag.js
generated
vendored
Normal file
4
node_modules/svelte/src/compiler/compile/nodes/MustacheTag.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import Tag from './shared/Tag.js';
|
||||
|
||||
/** @extends Tag<'MustacheTag'> */
|
||||
export default class MustacheTag extends Tag {}
|
4
node_modules/svelte/src/compiler/compile/nodes/Options.js
generated
vendored
Normal file
4
node_modules/svelte/src/compiler/compile/nodes/Options.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import Node from './shared/Node.js';
|
||||
|
||||
/** @extends Node<'Options'> */
|
||||
export default class Options extends Node {}
|
19
node_modules/svelte/src/compiler/compile/nodes/PendingBlock.js
generated
vendored
Normal file
19
node_modules/svelte/src/compiler/compile/nodes/PendingBlock.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
import map_children from './shared/map_children.js';
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
|
||||
/** @extends AbstractBlock<'PendingBlock'> */
|
||||
export default class PendingBlock extends AbstractBlock {
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.children = map_children(component, parent, scope, info.children);
|
||||
if (!info.skip) {
|
||||
this.warn_if_empty_block();
|
||||
}
|
||||
}
|
||||
}
|
16
node_modules/svelte/src/compiler/compile/nodes/RawMustacheTag.js
generated
vendored
Normal file
16
node_modules/svelte/src/compiler/compile/nodes/RawMustacheTag.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import Tag from './shared/Tag.js';
|
||||
|
||||
/** @extends Tag<'RawMustacheTag'> */
|
||||
export default class RawMustacheTag extends Tag {
|
||||
/**
|
||||
* @param {any} component
|
||||
* @param {any} parent
|
||||
* @param {any} scope
|
||||
* @param {any} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
}
|
||||
}
|
46
node_modules/svelte/src/compiler/compile/nodes/Slot.js
generated
vendored
Normal file
46
node_modules/svelte/src/compiler/compile/nodes/Slot.js
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
import Element from './Element.js';
|
||||
import Attribute from './Attribute.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
/** @extends Element */
|
||||
export default class Slot extends Element {
|
||||
/** @type {'Slot'} */
|
||||
// @ts-ignore Slot elements have the 'Slot' type, but TypeScript doesn't allow us to have 'Slot' when it extends Element
|
||||
type = 'Slot';
|
||||
|
||||
/** @type {string} */
|
||||
slot_name;
|
||||
|
||||
/** @type {Map<string, import('./Attribute.js').default>} */
|
||||
values = new Map();
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./interfaces.js').INode} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
info.attributes.forEach((attr) => {
|
||||
if (attr.type !== 'Attribute' && attr.type !== 'Spread') {
|
||||
return component.error(attr, compiler_errors.invalid_slot_directive);
|
||||
}
|
||||
if (attr.name === 'name') {
|
||||
if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
|
||||
return component.error(attr, compiler_errors.dynamic_slot_name);
|
||||
}
|
||||
this.slot_name = attr.value[0].data;
|
||||
if (this.slot_name === 'default') {
|
||||
return component.error(attr, compiler_errors.invalid_slot_name);
|
||||
}
|
||||
}
|
||||
this.values.set(attr.name, new Attribute(component, this, scope, attr));
|
||||
});
|
||||
if (!this.slot_name) this.slot_name = 'default';
|
||||
|
||||
component.slots.set(this.slot_name, this);
|
||||
this.cannot_use_innerhtml();
|
||||
this.not_static_content();
|
||||
}
|
||||
}
|
75
node_modules/svelte/src/compiler/compile/nodes/SlotTemplate.js
generated
vendored
Normal file
75
node_modules/svelte/src/compiler/compile/nodes/SlotTemplate.js
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Let from './Let.js';
|
||||
import Attribute from './Attribute.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import get_const_tags from './shared/get_const_tags.js';
|
||||
|
||||
/** @extends Node<'SlotTemplate'> */
|
||||
export default class SlotTemplate extends Node {
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {import('./interfaces.js').INode[]} */
|
||||
children;
|
||||
|
||||
/** @type {import('./Let.js').default[]} */
|
||||
lets = [];
|
||||
|
||||
/** @type {import('./ConstTag.js').default[]} */
|
||||
const_tags;
|
||||
|
||||
/** @type {import('./Attribute.js').default} */
|
||||
slot_attribute;
|
||||
|
||||
/** @type {string} */
|
||||
slot_template_name = 'default';
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./interfaces.js').INode} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {any} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.validate_slot_template_placement();
|
||||
scope = scope.child();
|
||||
info.attributes.forEach((node) => {
|
||||
switch (node.type) {
|
||||
case 'Let': {
|
||||
const l = new Let(component, this, scope, node);
|
||||
this.lets.push(l);
|
||||
const dependencies = new Set([l.name.name]);
|
||||
l.names.forEach((name) => {
|
||||
scope.add(name, dependencies, this);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'Attribute': {
|
||||
if (node.name === 'slot') {
|
||||
this.slot_attribute = new Attribute(component, this, scope, node);
|
||||
if (!this.slot_attribute.is_static) {
|
||||
return component.error(node, compiler_errors.invalid_slot_attribute);
|
||||
}
|
||||
const value = this.slot_attribute.get_static_value();
|
||||
if (typeof value === 'boolean') {
|
||||
return component.error(node, compiler_errors.invalid_slot_attribute_value_missing);
|
||||
}
|
||||
this.slot_template_name = /** @type {string} */ (value);
|
||||
break;
|
||||
}
|
||||
throw new Error(`Invalid attribute '${node.name}' in <svelte:fragment>`);
|
||||
}
|
||||
default:
|
||||
throw new Error(`Not implemented: ${node.type}`);
|
||||
}
|
||||
});
|
||||
this.scope = scope;
|
||||
[this.const_tags, this.children] = get_const_tags(info.children, component, this, this);
|
||||
}
|
||||
validate_slot_template_placement() {
|
||||
if (this.parent.type !== 'InlineComponent') {
|
||||
return this.component.error(this, compiler_errors.invalid_slotted_content_fragment);
|
||||
}
|
||||
}
|
||||
}
|
64
node_modules/svelte/src/compiler/compile/nodes/StyleDirective.js
generated
vendored
Normal file
64
node_modules/svelte/src/compiler/compile/nodes/StyleDirective.js
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
import list from '../../utils/list.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
import { nodes_to_template_literal } from '../utils/nodes_to_template_literal.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import Node from './shared/Node.js';
|
||||
|
||||
const valid_modifiers = new Set(['important']);
|
||||
|
||||
/** @extends Node<'StyleDirective'> */
|
||||
export default class StyleDirective extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
modifiers;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {boolean} */
|
||||
should_cache;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.name = info.name;
|
||||
this.modifiers = new Set(info.modifiers);
|
||||
for (const modifier of this.modifiers) {
|
||||
if (!valid_modifiers.has(modifier)) {
|
||||
component.error(
|
||||
this,
|
||||
compiler_errors.invalid_style_directive_modifier(list([...valid_modifiers]))
|
||||
);
|
||||
}
|
||||
}
|
||||
// Convert the value array to an expression so it's easier to handle
|
||||
// the StyleDirective going forward.
|
||||
if (info.value === true || (info.value.length === 1 && info.value[0].type === 'MustacheTag')) {
|
||||
const identifier =
|
||||
info.value === true
|
||||
? {
|
||||
type: 'Identifier',
|
||||
start: info.end - info.name.length,
|
||||
end: info.end,
|
||||
name: info.name
|
||||
}
|
||||
: info.value[0].expression;
|
||||
this.expression = new Expression(component, this, scope, identifier);
|
||||
this.should_cache = false;
|
||||
} else {
|
||||
const raw_expression = nodes_to_template_literal(info.value);
|
||||
this.expression = new Expression(component, this, scope, raw_expression);
|
||||
this.should_cache = raw_expression.expressions.length > 0;
|
||||
}
|
||||
}
|
||||
get important() {
|
||||
return this.modifiers.has('important');
|
||||
}
|
||||
}
|
68
node_modules/svelte/src/compiler/compile/nodes/Text.js
generated
vendored
Normal file
68
node_modules/svelte/src/compiler/compile/nodes/Text.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
import Node from './shared/Node.js';
|
||||
import { regex_non_whitespace_character } from '../../utils/patterns.js';
|
||||
|
||||
// Whitespace inside one of these elements will not result in
|
||||
// a whitespace node being created in any circumstances. (This
|
||||
// list is almost certainly very incomplete)
|
||||
const elements_without_text = new Set(['audio', 'datalist', 'dl', 'optgroup', 'select', 'video']);
|
||||
const regex_ends_with_svg = /svg$/;
|
||||
const regex_non_whitespace_characters = /[\S\u00A0]/;
|
||||
|
||||
/** @extends Node<'Text'> */
|
||||
export default class Text extends Node {
|
||||
/** @type {string} */
|
||||
data;
|
||||
|
||||
/** @type {boolean} */
|
||||
synthetic;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./interfaces.js').INode} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.data = info.data;
|
||||
this.synthetic = info.synthetic || false;
|
||||
}
|
||||
should_skip() {
|
||||
if (regex_non_whitespace_character.test(this.data)) return false;
|
||||
const parent_element = this.find_nearest(/(?:Element|InlineComponent|SlotTemplate|Head)/);
|
||||
if (!parent_element) return false;
|
||||
if (parent_element.type === 'Head') return true;
|
||||
if (parent_element.type === 'InlineComponent')
|
||||
return parent_element.children.length === 1 && this === parent_element.children[0];
|
||||
// svg namespace exclusions
|
||||
if (regex_ends_with_svg.test(parent_element.namespace)) {
|
||||
if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan') return false;
|
||||
}
|
||||
return parent_element.namespace || elements_without_text.has(parent_element.name);
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
keep_space() {
|
||||
if (this.component.component_options.preserveWhitespace) return true;
|
||||
return this.within_pre();
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
within_pre() {
|
||||
let node = this.parent;
|
||||
while (node) {
|
||||
if (node.type === 'Element' && node.name === 'pre') {
|
||||
return true;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
use_space() {
|
||||
if (this.component.compile_options.preserveWhitespace) return false;
|
||||
if (regex_non_whitespace_characters.test(this.data)) return false;
|
||||
return !this.within_pre();
|
||||
}
|
||||
}
|
32
node_modules/svelte/src/compiler/compile/nodes/ThenBlock.js
generated
vendored
Normal file
32
node_modules/svelte/src/compiler/compile/nodes/ThenBlock.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import AbstractBlock from './shared/AbstractBlock.js';
|
||||
import get_const_tags from './shared/get_const_tags.js';
|
||||
|
||||
/** @extends AbstractBlock<'ThenBlock'> */
|
||||
export default class ThenBlock extends AbstractBlock {
|
||||
/** @type {import('./shared/TemplateScope.js').default} */
|
||||
scope;
|
||||
|
||||
/** @type {import('./ConstTag.js').default[]} */
|
||||
const_tags;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./AwaitBlock.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope.child();
|
||||
if (parent.then_node) {
|
||||
parent.then_contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
this.scope.add(context.key.name, parent.expression.dependencies, this);
|
||||
});
|
||||
}
|
||||
[this.const_tags, this.children] = get_const_tags(info.children, component, this, parent);
|
||||
if (!info.skip) {
|
||||
this.warn_if_empty_block();
|
||||
}
|
||||
}
|
||||
}
|
36
node_modules/svelte/src/compiler/compile/nodes/Title.js
generated
vendored
Normal file
36
node_modules/svelte/src/compiler/compile/nodes/Title.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import Node from './shared/Node.js';
|
||||
import map_children from './shared/map_children.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
/** @extends Node<'Title'> */
|
||||
export default class Title extends Node {
|
||||
/** @type {import('./shared/map_children.js').Children} */
|
||||
children;
|
||||
|
||||
/** @type {boolean} */
|
||||
should_cache;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
this.children = map_children(component, parent, scope, info.children);
|
||||
if (info.attributes.length > 0) {
|
||||
component.error(info.attributes[0], compiler_errors.illegal_attribute_title);
|
||||
return;
|
||||
}
|
||||
info.children.forEach((child) => {
|
||||
if (child.type !== 'Text' && child.type !== 'MustacheTag') {
|
||||
return component.error(child, compiler_errors.illegal_structure_title);
|
||||
}
|
||||
});
|
||||
this.should_cache =
|
||||
info.children.length === 1
|
||||
? info.children[0].type !== 'Identifier' || scope.names.has(info.children[0].name)
|
||||
: true;
|
||||
}
|
||||
}
|
44
node_modules/svelte/src/compiler/compile/nodes/Transition.js
generated
vendored
Normal file
44
node_modules/svelte/src/compiler/compile/nodes/Transition.js
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Expression from './shared/Expression.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
/** @extends Node<'Transition'> */
|
||||
export default class Transition extends Node {
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {string} */
|
||||
directive;
|
||||
|
||||
/** @type {import('./shared/Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_local;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./Element.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
component.warn_if_undefined(info.name, info, scope);
|
||||
this.name = info.name;
|
||||
component.add_reference(/** @type {any} */ (this), info.name.split('.')[0]);
|
||||
this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
|
||||
this.is_local = !info.modifiers.includes('global');
|
||||
if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
|
||||
const parent_transition = parent.intro || parent.outro;
|
||||
component.error(
|
||||
info,
|
||||
compiler_errors.duplicate_transition(this.directive, parent_transition.directive)
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.expression = info.expression
|
||||
? new Expression(component, this, scope, info.expression)
|
||||
: null;
|
||||
}
|
||||
}
|
84
node_modules/svelte/src/compiler/compile/nodes/Window.js
generated
vendored
Normal file
84
node_modules/svelte/src/compiler/compile/nodes/Window.js
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
import Node from './shared/Node.js';
|
||||
import Binding from './Binding.js';
|
||||
import EventHandler from './EventHandler.js';
|
||||
import flatten_reference from '../utils/flatten_reference.js';
|
||||
import fuzzymatch from '../../utils/fuzzymatch.js';
|
||||
import list from '../../utils/list.js';
|
||||
import Action from './Action.js';
|
||||
import compiler_errors from '../compiler_errors.js';
|
||||
|
||||
const valid_bindings = [
|
||||
'innerWidth',
|
||||
'innerHeight',
|
||||
'outerWidth',
|
||||
'outerHeight',
|
||||
'scrollX',
|
||||
'scrollY',
|
||||
'devicePixelRatio',
|
||||
'online'
|
||||
];
|
||||
|
||||
/** @extends Node<'Window'> */
|
||||
export default class Window extends Node {
|
||||
/** @type {import('./EventHandler.js').default[]} */
|
||||
handlers = [];
|
||||
|
||||
/** @type {import('./Binding.js').default[]} */
|
||||
bindings = [];
|
||||
|
||||
/** @type {import('./Action.js').default[]} */
|
||||
actions = [];
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('./shared/Node.js').default} parent
|
||||
* @param {import('./shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
info.attributes.forEach((node) => {
|
||||
if (node.type === 'EventHandler') {
|
||||
this.handlers.push(new EventHandler(component, this, scope, node));
|
||||
} else if (node.type === 'Binding') {
|
||||
if (node.expression.type !== 'Identifier') {
|
||||
const { parts } = flatten_reference(node.expression);
|
||||
// TODO is this constraint necessary?
|
||||
return component.error(node.expression, compiler_errors.invalid_binding_window(parts));
|
||||
}
|
||||
if (!~valid_bindings.indexOf(node.name)) {
|
||||
const match =
|
||||
node.name === 'width'
|
||||
? 'innerWidth'
|
||||
: node.name === 'height'
|
||||
? 'innerHeight'
|
||||
: fuzzymatch(node.name, valid_bindings);
|
||||
if (match) {
|
||||
return component.error(
|
||||
node,
|
||||
compiler_errors.invalid_binding_on(
|
||||
node.name,
|
||||
'<svelte:window>',
|
||||
` (did you mean '${match}'?)`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return component.error(
|
||||
node,
|
||||
compiler_errors.invalid_binding_on(
|
||||
node.name,
|
||||
'<svelte:window>',
|
||||
` — valid bindings are ${list(valid_bindings)}`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
this.bindings.push(new Binding(component, this, scope, node));
|
||||
} else if (node.type === 'Action') {
|
||||
this.actions.push(new Action(component, this, scope, node));
|
||||
} else {
|
||||
// TODO there shouldn't be anything else here...
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
83
node_modules/svelte/src/compiler/compile/nodes/interfaces.d.ts
generated
vendored
Normal file
83
node_modules/svelte/src/compiler/compile/nodes/interfaces.d.ts
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
import Tag from './shared/Tag';
|
||||
import Action from './Action';
|
||||
import Animation from './Animation';
|
||||
import Attribute from './Attribute';
|
||||
import AwaitBlock from './AwaitBlock';
|
||||
import Binding from './Binding';
|
||||
import Body from './Body';
|
||||
import CatchBlock from './CatchBlock';
|
||||
import Class from './Class';
|
||||
import StyleDirective from './StyleDirective';
|
||||
import Comment from './Comment';
|
||||
import ConstTag from './ConstTag';
|
||||
import DebugTag from './DebugTag';
|
||||
import Document from './Document';
|
||||
import EachBlock from './EachBlock';
|
||||
import Element from './Element';
|
||||
import ElseBlock from './ElseBlock';
|
||||
import EventHandler from './EventHandler';
|
||||
import Fragment from './Fragment';
|
||||
import Head from './Head';
|
||||
import IfBlock from './IfBlock';
|
||||
import InlineComponent from './InlineComponent';
|
||||
import KeyBlock from './KeyBlock';
|
||||
import Let from './Let';
|
||||
import MustacheTag from './MustacheTag';
|
||||
import Options from './Options';
|
||||
import PendingBlock from './PendingBlock';
|
||||
import RawMustacheTag from './RawMustacheTag';
|
||||
import Slot from './Slot';
|
||||
import SlotTemplate from './SlotTemplate';
|
||||
import Text from './Text';
|
||||
import ThenBlock from './ThenBlock';
|
||||
import Title from './Title';
|
||||
import Transition from './Transition';
|
||||
import Window from './Window';
|
||||
|
||||
// note: to write less types each of types in union below should have type defined as literal
|
||||
// https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions
|
||||
export type INode =
|
||||
| Action
|
||||
| Animation
|
||||
| Attribute
|
||||
| AwaitBlock
|
||||
| Binding
|
||||
| Body
|
||||
| CatchBlock
|
||||
| Class
|
||||
| Comment
|
||||
| ConstTag
|
||||
| DebugTag
|
||||
| Document
|
||||
| EachBlock
|
||||
| Element
|
||||
| ElseBlock
|
||||
| EventHandler
|
||||
| Fragment
|
||||
| Head
|
||||
| IfBlock
|
||||
| InlineComponent
|
||||
| KeyBlock
|
||||
| Let
|
||||
| MustacheTag
|
||||
| Options
|
||||
| PendingBlock
|
||||
| RawMustacheTag
|
||||
| Slot
|
||||
| SlotTemplate
|
||||
| StyleDirective
|
||||
| Tag
|
||||
| Text
|
||||
| ThenBlock
|
||||
| Title
|
||||
| Transition
|
||||
| Window;
|
||||
|
||||
export type INodeAllowConstTag =
|
||||
| IfBlock
|
||||
| ElseBlock
|
||||
| EachBlock
|
||||
| CatchBlock
|
||||
| ThenBlock
|
||||
| InlineComponent
|
||||
| SlotTemplate;
|
33
node_modules/svelte/src/compiler/compile/nodes/shared/AbstractBlock.js
generated
vendored
Normal file
33
node_modules/svelte/src/compiler/compile/nodes/shared/AbstractBlock.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
import Node from './Node.js';
|
||||
import compiler_warnings from '../../compiler_warnings.js';
|
||||
|
||||
const regex_non_whitespace_characters = /[^ \r\n\f\v\t]/;
|
||||
|
||||
/**
|
||||
* @template {string} Type
|
||||
* @extends Node<Type>
|
||||
*/
|
||||
export default class AbstractBlock extends Node {
|
||||
/** @type {import('../../render_dom/Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('../interfaces.js').INode[]} */
|
||||
children;
|
||||
|
||||
/**
|
||||
* @param {import('../../Component.js').default} component
|
||||
* @param {any} parent
|
||||
* @param {any} scope
|
||||
* @param {any} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
}
|
||||
warn_if_empty_block() {
|
||||
if (!this.children || this.children.length > 1) return;
|
||||
const child = this.children[0];
|
||||
if (!child || (child.type === 'Text' && !regex_non_whitespace_characters.test(child.data))) {
|
||||
this.component.warn(this, compiler_warnings.empty_block);
|
||||
}
|
||||
}
|
||||
}
|
249
node_modules/svelte/src/compiler/compile/nodes/shared/Context.js
generated
vendored
Normal file
249
node_modules/svelte/src/compiler/compile/nodes/shared/Context.js
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
import { x } from 'code-red';
|
||||
import { walk } from 'estree-walker';
|
||||
import is_reference from 'is-reference';
|
||||
import { clone } from '../../../utils/clone.js';
|
||||
import flatten_reference from '../../utils/flatten_reference.js';
|
||||
/**
|
||||
* @param {{
|
||||
* contexts: Context[];
|
||||
* node: import('estree').Pattern;
|
||||
* modifier?: DestructuredVariable['modifier'];
|
||||
* default_modifier?: DestructuredVariable['default_modifier'];
|
||||
* scope: import('./TemplateScope.js').default;
|
||||
* component: import('../../Component.js').default;
|
||||
* context_rest_properties: Map<string, import('estree').Node>;
|
||||
* in_rest_element?: boolean;
|
||||
* }} params
|
||||
*/
|
||||
export function unpack_destructuring({
|
||||
contexts,
|
||||
node,
|
||||
modifier = (node) => node,
|
||||
default_modifier = (node) => node,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element = false
|
||||
}) {
|
||||
if (!node) return;
|
||||
if (node.type === 'Identifier') {
|
||||
contexts.push({
|
||||
type: 'DestructuredVariable',
|
||||
key: /** @type {import('estree').Identifier} */ (node),
|
||||
modifier,
|
||||
default_modifier
|
||||
});
|
||||
if (in_rest_element) {
|
||||
context_rest_properties.set(node.name, node);
|
||||
}
|
||||
component.used_names.add(node.name);
|
||||
} else if (node.type === 'ArrayPattern') {
|
||||
node.elements.forEach((element, i) => {
|
||||
if (!element) {
|
||||
return;
|
||||
} else if (element.type === 'RestElement') {
|
||||
unpack_destructuring({
|
||||
contexts,
|
||||
node: element.argument,
|
||||
modifier: (node) =>
|
||||
/** @type {import('estree').Node} */ (x`${modifier(node)}.slice(${i})`),
|
||||
default_modifier,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element: true
|
||||
});
|
||||
} else if (element.type === 'AssignmentPattern') {
|
||||
const n = contexts.length;
|
||||
mark_referenced(element.right, scope, component);
|
||||
unpack_destructuring({
|
||||
contexts,
|
||||
node: element.left,
|
||||
modifier: (node) => x`${modifier(node)}[${i}]`,
|
||||
default_modifier: (node, to_ctx) =>
|
||||
/** @type {import('estree').Node} */ (
|
||||
x`${node} !== undefined ? ${node} : ${update_reference(
|
||||
contexts,
|
||||
n,
|
||||
element.right,
|
||||
to_ctx
|
||||
)}`
|
||||
),
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element
|
||||
});
|
||||
} else {
|
||||
unpack_destructuring({
|
||||
contexts,
|
||||
node: element,
|
||||
modifier: (node) => /** @type {import('estree').Node} */ (x`${modifier(node)}[${i}]`),
|
||||
default_modifier,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (node.type === 'ObjectPattern') {
|
||||
const used_properties = [];
|
||||
node.properties.forEach((property) => {
|
||||
if (property.type === 'RestElement') {
|
||||
unpack_destructuring({
|
||||
contexts,
|
||||
node: property.argument,
|
||||
modifier: (node) =>
|
||||
/** @type {import('estree').Node} */ (
|
||||
x`@object_without_properties(${modifier(node)}, [${used_properties}])`
|
||||
),
|
||||
default_modifier,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element: true
|
||||
});
|
||||
} else if (property.type === 'Property') {
|
||||
const key = property.key;
|
||||
const value = property.value;
|
||||
|
||||
/** @type {(node: import('estree').Node) => import('estree').Node} */
|
||||
let new_modifier;
|
||||
if (property.computed) {
|
||||
// e.g { [computedProperty]: ... }
|
||||
const property_name = component.get_unique_name('computed_property');
|
||||
contexts.push({
|
||||
type: 'ComputedProperty',
|
||||
property_name,
|
||||
key
|
||||
});
|
||||
new_modifier = (node) => x`${modifier(node)}[${property_name}]`;
|
||||
used_properties.push(x`${property_name}`);
|
||||
} else if (key.type === 'Identifier') {
|
||||
// e.g. { someProperty: ... }
|
||||
const property_name = key.name;
|
||||
new_modifier = (node) => x`${modifier(node)}.${property_name}`;
|
||||
used_properties.push(x`"${property_name}"`);
|
||||
} else if (key.type === 'Literal') {
|
||||
// e.g. { "property-in-quotes": ... } or { 14: ... }
|
||||
const property_name = key.value;
|
||||
new_modifier = (node) => x`${modifier(node)}["${property_name}"]`;
|
||||
used_properties.push(x`"${property_name}"`);
|
||||
}
|
||||
if (value.type === 'AssignmentPattern') {
|
||||
// e.g. { property = default } or { property: newName = default }
|
||||
const n = contexts.length;
|
||||
mark_referenced(value.right, scope, component);
|
||||
unpack_destructuring({
|
||||
contexts,
|
||||
node: value.left,
|
||||
modifier: new_modifier,
|
||||
default_modifier: (node, to_ctx) =>
|
||||
/** @type {import('estree').Node} */ (
|
||||
x`${node} !== undefined ? ${node} : ${update_reference(
|
||||
contexts,
|
||||
n,
|
||||
value.right,
|
||||
to_ctx
|
||||
)}`
|
||||
),
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element
|
||||
});
|
||||
} else {
|
||||
// e.g. { property } or { property: newName }
|
||||
unpack_destructuring({
|
||||
contexts,
|
||||
node: value,
|
||||
modifier: new_modifier,
|
||||
default_modifier,
|
||||
scope,
|
||||
component,
|
||||
context_rest_properties,
|
||||
in_rest_element
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Context[]} contexts
|
||||
* @param {number} n
|
||||
* @param {import('estree').Expression} expression
|
||||
* @param {(name: string) => import('estree').Node} to_ctx
|
||||
* @returns {import('estree').Node}
|
||||
*/
|
||||
function update_reference(contexts, n, expression, to_ctx) {
|
||||
/** @param {import('estree').Identifier} node */
|
||||
const find_from_context = (node) => {
|
||||
for (let i = n; i < contexts.length; i++) {
|
||||
const cur_context = contexts[i];
|
||||
if (cur_context.type !== 'DestructuredVariable') continue;
|
||||
const { key } = cur_context;
|
||||
if (node.name === key.name) {
|
||||
throw new Error(`Cannot access '${node.name}' before initialization`);
|
||||
}
|
||||
}
|
||||
return to_ctx(node.name);
|
||||
};
|
||||
if (expression.type === 'Identifier') {
|
||||
return find_from_context(expression);
|
||||
}
|
||||
// NOTE: avoid unnecessary deep clone?
|
||||
expression = /** @type {import('estree').Expression} */ (clone(expression));
|
||||
walk(expression, {
|
||||
enter(node, parent) {
|
||||
if (
|
||||
is_reference(
|
||||
/** @type {import('is-reference').NodeWithPropertyDefinition} */ (node),
|
||||
/** @type {import('is-reference').NodeWithPropertyDefinition} */ (parent)
|
||||
)
|
||||
) {
|
||||
this.replace(find_from_context(/** @type {import('estree').Identifier} */ (node)));
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
});
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('estree').Node} node
|
||||
* @param {import('./TemplateScope.js').default} scope
|
||||
* @param {import('../../Component.js').default} component
|
||||
*/
|
||||
function mark_referenced(node, scope, component) {
|
||||
walk(node, {
|
||||
enter(node, parent) {
|
||||
if (is_reference(node, parent)) {
|
||||
const { name } = flatten_reference(node);
|
||||
if (!scope.is_let(name) && !scope.names.has(name)) {
|
||||
component.add_reference(node, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @typedef {DestructuredVariable | ComputedProperty} Context */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ComputedProperty
|
||||
* @property {'ComputedProperty'} type
|
||||
* @property {import('estree').Identifier} property_name
|
||||
* @property {import('estree').Expression|import('estree').PrivateIdentifier} key
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} DestructuredVariable
|
||||
* @property {'DestructuredVariable'} type
|
||||
* @property {import('estree').Identifier} key
|
||||
* @property {string} [name]
|
||||
* @property {(node:import('estree').Node)=>import('estree').Node} modifier
|
||||
* @property {(node:import('estree').Node,to_ctx:(name:string)=>import('estree').Node)=>import('estree').Node} default_modifier
|
||||
*/
|
474
node_modules/svelte/src/compiler/compile/nodes/shared/Expression.js
generated
vendored
Normal file
474
node_modules/svelte/src/compiler/compile/nodes/shared/Expression.js
generated
vendored
Normal file
@ -0,0 +1,474 @@
|
||||
import { walk } from 'estree-walker';
|
||||
import is_reference from 'is-reference';
|
||||
import flatten_reference from '../../utils/flatten_reference.js';
|
||||
import { create_scopes, extract_names } from '../../utils/scope.js';
|
||||
import { sanitize } from '../../../utils/names.js';
|
||||
import get_object from '../../utils/get_object.js';
|
||||
import is_dynamic from '../../render_dom/wrappers/shared/is_dynamic.js';
|
||||
import { b } from 'code-red';
|
||||
import { invalidate } from '../../render_dom/invalidate.js';
|
||||
import { is_reserved_keyword } from '../../utils/reserved_keywords.js';
|
||||
import replace_object from '../../utils/replace_object.js';
|
||||
import is_contextual from './is_contextual.js';
|
||||
import { clone } from '../../../utils/clone.js';
|
||||
import compiler_errors from '../../compiler_errors.js';
|
||||
|
||||
const regex_contains_term_function_expression = /FunctionExpression/;
|
||||
|
||||
export default class Expression {
|
||||
/** @type {'Expression'} */
|
||||
type = 'Expression';
|
||||
|
||||
/** @type {import('../../Component.js').default} */
|
||||
component;
|
||||
|
||||
/** @type {import('../interfaces.js').INode} */
|
||||
owner;
|
||||
|
||||
/** @type {import('estree').Node} */
|
||||
node;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
references = new Set();
|
||||
|
||||
/**
|
||||
* Dependencies declared in the script block
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
dependencies = new Set();
|
||||
|
||||
/**
|
||||
* Dependencies declared in the HTML-like template section
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
contextual_dependencies = new Set();
|
||||
|
||||
/** @type {import('./TemplateScope.js').default} */
|
||||
template_scope;
|
||||
|
||||
/** @type {import('../../utils/scope.js').Scope} */
|
||||
scope;
|
||||
|
||||
/** @type {WeakMap<import('estree').Node, import('../../utils/scope.js').Scope>} */
|
||||
scope_map;
|
||||
|
||||
/** @type {Array<import('estree').Node | import('estree').Node[]>} */
|
||||
declarations = [];
|
||||
|
||||
/** @type {boolean} */
|
||||
uses_context = false;
|
||||
|
||||
/** @type {import('estree').Node} */
|
||||
manipulated;
|
||||
|
||||
/**
|
||||
* @param {import('../../Component.js').default} component *
|
||||
* @param {import('../interfaces.js').INode} owner *
|
||||
* @param {import('./TemplateScope.js').default} template_scope *
|
||||
* @param {import('estree').Node} info *
|
||||
* @param {boolean} [lazy] undefined
|
||||
*/
|
||||
constructor(component, owner, template_scope, info, lazy) {
|
||||
// TODO revert to direct property access in prod?
|
||||
Object.defineProperties(this, {
|
||||
component: {
|
||||
value: component
|
||||
}
|
||||
});
|
||||
this.node = info;
|
||||
this.template_scope = template_scope;
|
||||
this.owner = owner;
|
||||
const { dependencies, contextual_dependencies, references } = this;
|
||||
let { map, scope } = create_scopes(info);
|
||||
this.scope = scope;
|
||||
this.scope_map = map;
|
||||
const expression = this;
|
||||
let function_expression;
|
||||
|
||||
// discover dependencies, but don't change the code yet
|
||||
walk(info, {
|
||||
/**
|
||||
* @param {any} node
|
||||
* @param {import('estree').Node} parent
|
||||
* @param {string} key
|
||||
*/
|
||||
enter(node, parent, key) {
|
||||
// don't manipulate shorthand props twice
|
||||
if (key === 'key' && /** @type {import('estree').Property} */ (parent).shorthand) return;
|
||||
// don't manipulate `import.meta`, `new.target`
|
||||
if (node.type === 'MetaProperty') return this.skip();
|
||||
if (map.has(node)) {
|
||||
scope = map.get(node);
|
||||
}
|
||||
if (!function_expression && regex_contains_term_function_expression.test(node.type)) {
|
||||
function_expression = node;
|
||||
}
|
||||
if (is_reference(node, parent)) {
|
||||
const { name, nodes } = flatten_reference(node);
|
||||
references.add(name);
|
||||
if (scope.has(name)) return;
|
||||
if (name[0] === '$') {
|
||||
const store_name = name.slice(1);
|
||||
if (template_scope.names.has(store_name) || scope.has(store_name)) {
|
||||
return component.error(node, compiler_errors.contextual_store);
|
||||
}
|
||||
}
|
||||
if (template_scope.is_let(name)) {
|
||||
if (!lazy) {
|
||||
contextual_dependencies.add(name);
|
||||
dependencies.add(name);
|
||||
}
|
||||
} else if (template_scope.names.has(name)) {
|
||||
expression.uses_context = true;
|
||||
contextual_dependencies.add(name);
|
||||
const owner = template_scope.get_owner(name);
|
||||
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));
|
||||
}
|
||||
} else {
|
||||
if (!lazy) {
|
||||
const variable = component.var_lookup.get(name);
|
||||
if (!variable || !variable.imported || variable.mutated || variable.reassigned) {
|
||||
dependencies.add(name);
|
||||
}
|
||||
}
|
||||
component.add_reference(node, name);
|
||||
component.warn_if_undefined(name, nodes[0], template_scope, owner);
|
||||
}
|
||||
this.skip();
|
||||
}
|
||||
// track any assignments from template expressions as mutable
|
||||
let names;
|
||||
let deep = false;
|
||||
if (function_expression) {
|
||||
if (node.type === 'AssignmentExpression') {
|
||||
deep = node.left.type === 'MemberExpression';
|
||||
names = extract_names(deep ? get_object(node.left) : node.left);
|
||||
} else if (node.type === 'UpdateExpression') {
|
||||
deep = node.argument.type === 'MemberExpression';
|
||||
names = extract_names(get_object(node.argument));
|
||||
}
|
||||
}
|
||||
if (names) {
|
||||
names.forEach((name) => {
|
||||
if (template_scope.names.has(name)) {
|
||||
if (template_scope.is_const(name)) {
|
||||
component.error(node, compiler_errors.invalid_const_update(name));
|
||||
}
|
||||
template_scope.dependencies_for_name.get(name).forEach((name) => {
|
||||
const variable = component.var_lookup.get(name);
|
||||
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
|
||||
});
|
||||
const each_block = template_scope.get_owner(name);
|
||||
/** @type {import('../EachBlock.js').default} */ (each_block).has_binding = true;
|
||||
} else {
|
||||
component.add_reference(node, name);
|
||||
const variable = component.var_lookup.get(name);
|
||||
if (variable) {
|
||||
variable[deep ? 'mutated' : 'reassigned'] = true;
|
||||
}
|
||||
|
||||
const declaration = scope.find_owner(name)?.declarations.get(name);
|
||||
if (declaration) {
|
||||
if (
|
||||
/** @type {import('estree').VariableDeclaration} */ (declaration).kind ===
|
||||
'const' &&
|
||||
!deep
|
||||
) {
|
||||
component.error(node, {
|
||||
code: 'assignment-to-const',
|
||||
message: 'You are assigning to a const'
|
||||
});
|
||||
}
|
||||
} else if (variable && variable.writable === false && !deep) {
|
||||
component.error(node, {
|
||||
code: 'assignment-to-const',
|
||||
message: 'You are assigning to a const'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/** @type {import('estree-walker').SyncHandler} */
|
||||
leave(node) {
|
||||
if (map.has(node)) {
|
||||
scope = scope.parent;
|
||||
}
|
||||
if (node === function_expression) {
|
||||
function_expression = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
dynamic_dependencies() {
|
||||
return Array.from(this.dependencies).filter((name) => {
|
||||
if (this.template_scope.is_let(name)) return true;
|
||||
if (is_reserved_keyword(name)) return true;
|
||||
const variable = this.component.var_lookup.get(name);
|
||||
return is_dynamic(variable);
|
||||
});
|
||||
}
|
||||
dynamic_contextual_dependencies() {
|
||||
return Array.from(this.contextual_dependencies).filter((name) => {
|
||||
return Array.from(this.template_scope.dependencies_for_name.get(name)).some(
|
||||
(variable_name) => {
|
||||
const variable = this.component.var_lookup.get(variable_name);
|
||||
return is_dynamic(variable);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
// TODO move this into a render-dom wrapper?
|
||||
|
||||
/**
|
||||
* @param {import('../../render_dom/Block.js').default} [block]
|
||||
* @param {string | void} [ctx]
|
||||
*/
|
||||
manipulate(block, ctx) {
|
||||
// TODO ideally we wouldn't end up calling this method
|
||||
// multiple times
|
||||
if (this.manipulated) return this.manipulated;
|
||||
const { component, declarations, scope_map: map, template_scope, owner } = this;
|
||||
let scope = this.scope;
|
||||
|
||||
/** @type {import('estree').FunctionExpression | import('estree').ArrowFunctionExpression | null} */
|
||||
let function_expression;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
let dependencies;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
let contextual_dependencies;
|
||||
const node = walk(this.node, {
|
||||
/** @type {import('estree-walker').SyncHandler} */
|
||||
enter(node, parent) {
|
||||
if (node.type === 'Property' && node.shorthand) {
|
||||
node.value = clone(node.value);
|
||||
node.shorthand = false;
|
||||
}
|
||||
if (map.has(node)) {
|
||||
scope = map.get(node);
|
||||
}
|
||||
if (node.type === 'Identifier' && is_reference(node, parent)) {
|
||||
const { name } = flatten_reference(node);
|
||||
if (scope.has(name)) return;
|
||||
if (function_expression) {
|
||||
if (template_scope.names.has(name)) {
|
||||
contextual_dependencies.add(name);
|
||||
template_scope.dependencies_for_name.get(name).forEach((dependency) => {
|
||||
dependencies.add(dependency);
|
||||
});
|
||||
} else {
|
||||
dependencies.add(name);
|
||||
component.add_reference(node, name); // TODO is this redundant/misplaced?
|
||||
}
|
||||
} else if (is_contextual(component, template_scope, name)) {
|
||||
const reference = block.renderer.reference(node, ctx);
|
||||
this.replace(reference);
|
||||
}
|
||||
this.skip();
|
||||
}
|
||||
if (!function_expression) {
|
||||
if (node.type === 'AssignmentExpression') {
|
||||
// TODO should this be a warning/error? `<p>{foo = 1}</p>`
|
||||
}
|
||||
if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
|
||||
function_expression = node;
|
||||
dependencies = new Set();
|
||||
contextual_dependencies = new Set();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @type {import('estree-walker').SyncHandler} */
|
||||
leave(node, parent) {
|
||||
if (map.has(node)) scope = scope.parent;
|
||||
if (node === function_expression) {
|
||||
const id = component.get_unique_name(sanitize(get_function_name(node, owner)));
|
||||
const declaration = b`const ${id} = ${node}`;
|
||||
const extract_functions = () => {
|
||||
const deps = Array.from(contextual_dependencies);
|
||||
const function_expression = /** @type {import('estree').FunctionExpression} */ (node);
|
||||
const has_args = function_expression.params.length > 0;
|
||||
function_expression.params = [
|
||||
...deps.map(
|
||||
(name) => /** @type {import('estree').Identifier} */ ({ type: 'Identifier', name })
|
||||
),
|
||||
...function_expression.params
|
||||
];
|
||||
const context_args = deps.map((name) => block.renderer.reference(name, ctx));
|
||||
component.partly_hoisted.push(declaration);
|
||||
block.renderer.add_to_context(id.name);
|
||||
const callee = block.renderer.reference(id);
|
||||
this.replace(id);
|
||||
const func_declaration = has_args
|
||||
? b`function ${id}(...args) {
|
||||
return ${callee}(${context_args}, ...args);
|
||||
}`
|
||||
: b`function ${id}() {
|
||||
return ${callee}(${context_args});
|
||||
}`;
|
||||
return { deps, func_declaration };
|
||||
};
|
||||
if (owner.type === 'ConstTag') {
|
||||
// we need a combo block/init recipe
|
||||
if (contextual_dependencies.size === 0) {
|
||||
let child_scope = scope;
|
||||
walk(node, {
|
||||
/** @type {import('estree-walker').SyncHandler} */
|
||||
enter(node, parent) {
|
||||
if (map.has(node)) child_scope = map.get(node);
|
||||
if (node.type === 'Identifier' && is_reference(node, parent)) {
|
||||
if (child_scope.has(node.name)) return;
|
||||
this.replace(block.renderer.reference(node, ctx));
|
||||
}
|
||||
},
|
||||
|
||||
/** @param {import('estree').Node} node */
|
||||
leave(node) {
|
||||
if (map.has(node)) child_scope = child_scope.parent;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const { func_declaration } = extract_functions();
|
||||
this.replace(func_declaration[0]);
|
||||
}
|
||||
} else if (dependencies.size === 0 && contextual_dependencies.size === 0) {
|
||||
// we can hoist this out of the component completely
|
||||
component.fully_hoisted.push(declaration);
|
||||
this.replace(id);
|
||||
component.add_var(node, {
|
||||
name: id.name,
|
||||
internal: true,
|
||||
hoistable: true,
|
||||
referenced: true
|
||||
});
|
||||
} 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 {
|
||||
// we need a combo block/init recipe
|
||||
const { deps, func_declaration } = extract_functions();
|
||||
if (owner.type === 'Attribute' && owner.parent.name === 'slot') {
|
||||
/** @type {Set<import('../interfaces.js').INode>} */
|
||||
const dep_scopes = new Set(deps.map((name) => template_scope.get_owner(name)));
|
||||
// find the nearest scopes
|
||||
|
||||
/** @type {import('../interfaces.js').INode} */
|
||||
let node = owner.parent;
|
||||
while (node && !dep_scopes.has(node)) {
|
||||
node = node.parent;
|
||||
}
|
||||
const func_expression = func_declaration[0];
|
||||
|
||||
if (node.type === 'SlotTemplate') {
|
||||
// <svelte:fragment let:data />
|
||||
this.replace(func_expression);
|
||||
} else {
|
||||
// {#each}, {#await}
|
||||
const func_id = component.get_unique_name(id.name + '_func');
|
||||
block.renderer.add_to_context(func_id.name, true);
|
||||
// rename #ctx -> child_ctx;
|
||||
walk(func_expression, {
|
||||
/** @param {import('estree').Node} node */
|
||||
enter(node) {
|
||||
if (node.type === 'Identifier' && node.name === '#ctx') {
|
||||
node.name = 'child_ctx';
|
||||
}
|
||||
}
|
||||
});
|
||||
// add to get_xxx_context
|
||||
// child_ctx[x] = function () { ... }
|
||||
/** @type {import('../EachBlock.js').default} */ (
|
||||
template_scope.get_owner(deps[0])
|
||||
).contexts.push({
|
||||
type: 'DestructuredVariable',
|
||||
key: func_id,
|
||||
modifier: () => func_expression,
|
||||
default_modifier: (node) => node
|
||||
});
|
||||
this.replace(block.renderer.reference(func_id));
|
||||
}
|
||||
} else {
|
||||
declarations.push(func_declaration);
|
||||
}
|
||||
}
|
||||
function_expression = null;
|
||||
dependencies = null;
|
||||
contextual_dependencies = null;
|
||||
if (parent && parent.type === 'Property') {
|
||||
parent.method = false;
|
||||
}
|
||||
}
|
||||
if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
|
||||
const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
|
||||
const object_name = get_object(assignee).name;
|
||||
if (scope.has(object_name)) return;
|
||||
// normally (`a = 1`, `b.c = 2`), there'll be a single name
|
||||
// (a or b). In destructuring cases (`[d, e] = [e, d]`) there
|
||||
// may be more, in which case we need to tack the extra ones
|
||||
// onto the initial function call
|
||||
const names = new Set(extract_names(/** @type {import('estree').Node} */ (assignee)));
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const traced = new Set();
|
||||
names.forEach((name) => {
|
||||
const dependencies = template_scope.dependencies_for_name.get(name);
|
||||
if (dependencies) {
|
||||
dependencies.forEach((name) => traced.add(name));
|
||||
} else {
|
||||
traced.add(name);
|
||||
}
|
||||
});
|
||||
const context = block.bindings.get(object_name);
|
||||
if (context) {
|
||||
// for `{#each array as item}`
|
||||
// replace `item = 1` to `each_array[each_index] = 1`, this allow us to mutate the array
|
||||
// rather than mutating the local `item` variable
|
||||
const { snippet, object, property } = context;
|
||||
|
||||
/** @type {any} */
|
||||
const replaced = replace_object(assignee, snippet);
|
||||
if (node.type === 'AssignmentExpression') {
|
||||
node.left = replaced;
|
||||
} else {
|
||||
node.argument = replaced;
|
||||
}
|
||||
contextual_dependencies.add(object.name);
|
||||
contextual_dependencies.add(property.name);
|
||||
}
|
||||
this.replace(invalidate(block.renderer, scope, node, traced));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (declarations.length > 0) {
|
||||
block.maintain_context = true;
|
||||
declarations.forEach((declaration) => {
|
||||
block.chunks.init.push(declaration);
|
||||
});
|
||||
}
|
||||
return (this.manipulated = /** @type {import('estree').Node} */ (node));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('estree').Node} _node
|
||||
* @param {import('../interfaces.js').INode} parent
|
||||
*/
|
||||
function get_function_name(_node, parent) {
|
||||
if (parent.type === 'EventHandler') {
|
||||
return `${parent.name}_handler`;
|
||||
}
|
||||
if (parent.type === 'Action') {
|
||||
return `${parent.name}_function`;
|
||||
}
|
||||
return 'func';
|
||||
}
|
113
node_modules/svelte/src/compiler/compile/nodes/shared/Node.js
generated
vendored
Normal file
113
node_modules/svelte/src/compiler/compile/nodes/shared/Node.js
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @template {string} Type
|
||||
* @template {import('../interfaces.js').INode} [Parent=import('../interfaces.js').INode]
|
||||
*/
|
||||
export default class Node {
|
||||
/**
|
||||
* @readonly
|
||||
* @type {number}
|
||||
*/
|
||||
start;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
* @type {number}
|
||||
*/
|
||||
end;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
* @type {import('../../Component.js').default}
|
||||
*/
|
||||
component;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
* @type {Parent}
|
||||
*/
|
||||
parent;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
* @type {Type}
|
||||
*/
|
||||
type;
|
||||
|
||||
/** @type {import('../interfaces.js').INode} */
|
||||
prev;
|
||||
|
||||
/** @type {import('../interfaces.js').INode} */
|
||||
next;
|
||||
|
||||
/** @type {boolean} */
|
||||
can_use_innerhtml;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_static_content;
|
||||
|
||||
/** @type {string} */
|
||||
var;
|
||||
|
||||
/** @type {import('../Attribute.js').default[]} */
|
||||
attributes = [];
|
||||
|
||||
/**
|
||||
* @param {import('../../Component.js').default} component
|
||||
* @param {Node} parent
|
||||
* @param {any} _scope
|
||||
* @param {import('../../../interfaces.js').TemplateNode} info
|
||||
*/
|
||||
constructor(component, parent, _scope, info) {
|
||||
this.start = info.start;
|
||||
this.end = info.end;
|
||||
this.type = /** @type {Type} */ (info.type);
|
||||
// this makes properties non-enumerable, which makes logging
|
||||
// bearable. might have a performance cost. TODO remove in prod?
|
||||
Object.defineProperties(this, {
|
||||
component: {
|
||||
value: component
|
||||
},
|
||||
parent: {
|
||||
value: parent
|
||||
}
|
||||
});
|
||||
this.can_use_innerhtml = true;
|
||||
this.is_static_content = true;
|
||||
}
|
||||
cannot_use_innerhtml() {
|
||||
if (this.can_use_innerhtml !== false) {
|
||||
this.can_use_innerhtml = false;
|
||||
if (this.parent) this.parent.cannot_use_innerhtml();
|
||||
}
|
||||
}
|
||||
not_static_content() {
|
||||
this.is_static_content = false;
|
||||
if (this.parent) this.parent.not_static_content();
|
||||
}
|
||||
|
||||
/** @param {RegExp} selector */
|
||||
find_nearest(selector) {
|
||||
if (selector.test(this.type)) return this;
|
||||
if (this.parent) return this.parent.find_nearest(selector);
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
get_static_attribute_value(name) {
|
||||
const attribute = this.attributes.find(
|
||||
/** @param {import('../Attribute.js').default} attr */
|
||||
(attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === name
|
||||
);
|
||||
if (!attribute) return null;
|
||||
if (attribute.is_true) return true;
|
||||
if (attribute.chunks.length === 0) return '';
|
||||
if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
|
||||
return /** @type {import('../Text.js').default} */ (attribute.chunks[0]).data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @param {string} type */
|
||||
has_ancestor(type) {
|
||||
return this.parent ? this.parent.type === type || this.parent.has_ancestor(type) : false;
|
||||
}
|
||||
}
|
41
node_modules/svelte/src/compiler/compile/nodes/shared/Tag.js
generated
vendored
Normal file
41
node_modules/svelte/src/compiler/compile/nodes/shared/Tag.js
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
import Node from './Node.js';
|
||||
import Expression from './Expression.js';
|
||||
|
||||
/**
|
||||
* @template {'MustacheTag' | 'RawMustacheTag'} [Type='MustacheTag' | 'RawMustacheTag']
|
||||
* @extends Node<Type>
|
||||
*/
|
||||
export default class Tag extends Node {
|
||||
/** @type {import('./Expression.js').default} */
|
||||
expression;
|
||||
|
||||
/** @type {boolean} */
|
||||
should_cache;
|
||||
|
||||
/**
|
||||
* @param {any} component
|
||||
* @param {any} parent
|
||||
* @param {any} scope
|
||||
* @param {any} info
|
||||
*/
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
component.tags.push(this);
|
||||
this.cannot_use_innerhtml();
|
||||
this.expression = new Expression(component, this, scope, info.expression);
|
||||
this.should_cache =
|
||||
info.expression.type !== 'Identifier' ||
|
||||
(this.expression.dependencies.size && scope.names.has(info.expression.name));
|
||||
}
|
||||
is_dependencies_static() {
|
||||
return (
|
||||
this.expression.dynamic_contextual_dependencies().length === 0 &&
|
||||
this.expression.dynamic_dependencies().length === 0
|
||||
);
|
||||
}
|
||||
check_if_content_dynamic() {
|
||||
if (!this.is_dependencies_static()) {
|
||||
this.not_static_content();
|
||||
}
|
||||
}
|
||||
}
|
83
node_modules/svelte/src/compiler/compile/nodes/shared/TemplateScope.js
generated
vendored
Normal file
83
node_modules/svelte/src/compiler/compile/nodes/shared/TemplateScope.js
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/** The scope of constructs within the Svelte template */
|
||||
export default class TemplateScope {
|
||||
/**
|
||||
* @typedef {import('../EachBlock').default
|
||||
* | import('../ThenBlock').default
|
||||
* | import('../CatchBlock').default
|
||||
* | import('../InlineComponent').default
|
||||
* | import('../Element').default
|
||||
* | import('../SlotTemplate').default
|
||||
* | import('../ConstTag').default} NodeWithScope
|
||||
*/
|
||||
|
||||
/** @type {Set<string>} */
|
||||
names;
|
||||
|
||||
/** @type {Map<string, Set<string>>} */
|
||||
dependencies_for_name;
|
||||
|
||||
/** @type {Map<string, NodeWithScope>} */
|
||||
owners = new Map();
|
||||
|
||||
/** @type {TemplateScope} */
|
||||
parent;
|
||||
|
||||
/** @param {TemplateScope} [parent] undefined */
|
||||
constructor(parent) {
|
||||
this.parent = parent;
|
||||
this.names = new Set(parent ? parent.names : []);
|
||||
this.dependencies_for_name = new Map(parent ? parent.dependencies_for_name : []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} name
|
||||
* @param {Set<string>} dependencies
|
||||
* @param {any} owner
|
||||
*/
|
||||
add(name, dependencies, owner) {
|
||||
this.names.add(name);
|
||||
this.dependencies_for_name.set(name, dependencies);
|
||||
this.owners.set(name, owner);
|
||||
return this;
|
||||
}
|
||||
child() {
|
||||
const child = new TemplateScope(this);
|
||||
return child;
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
is_top_level(name) {
|
||||
return !this.parent || (!this.names.has(name) && this.parent.is_top_level(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {NodeWithScope}
|
||||
*/
|
||||
get_owner(name) {
|
||||
return this.owners.get(name) || (this.parent && this.parent.get_owner(name));
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
is_let(name) {
|
||||
const owner = this.get_owner(name);
|
||||
return (
|
||||
owner &&
|
||||
(owner.type === 'Element' ||
|
||||
owner.type === 'InlineComponent' ||
|
||||
owner.type === 'SlotTemplate')
|
||||
);
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
is_await(name) {
|
||||
const owner = this.get_owner(name);
|
||||
return owner && (owner.type === 'ThenBlock' || owner.type === 'CatchBlock');
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
is_const(name) {
|
||||
const owner = this.get_owner(name);
|
||||
return owner && owner.type === 'ConstTag';
|
||||
}
|
||||
}
|
95
node_modules/svelte/src/compiler/compile/nodes/shared/get_const_tags.js
generated
vendored
Normal file
95
node_modules/svelte/src/compiler/compile/nodes/shared/get_const_tags.js
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
import ConstTag from '../ConstTag.js';
|
||||
import map_children from './map_children.js';
|
||||
import check_graph_for_cycles from '../../utils/check_graph_for_cycles.js';
|
||||
import compiler_errors from '../../compiler_errors.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../../interfaces.js').TemplateNode[]} children
|
||||
* @param {import('../../Component.js').default} component
|
||||
* @param {import('../interfaces.js').INodeAllowConstTag} node
|
||||
* @param {import('../interfaces.js').INode} parent
|
||||
* @returns {[ConstTag[], Array<Exclude<import('../interfaces.js').INode, ConstTag>>]}
|
||||
*/
|
||||
export default function get_const_tags(children, component, node, parent) {
|
||||
/** @type {import('../../../interfaces.js').ConstTag[]} */
|
||||
const const_tags = [];
|
||||
|
||||
/** @type {Array<Exclude<import('../../../interfaces.js').TemplateNode, import('../../../interfaces.js').ConstTag>>} */
|
||||
const others = [];
|
||||
for (const child of children) {
|
||||
if (child.type === 'ConstTag') {
|
||||
const_tags.push(/** @type {import('../../../interfaces.js').ConstTag} */ (child));
|
||||
} else {
|
||||
others.push(child);
|
||||
}
|
||||
}
|
||||
const consts_nodes = const_tags.map((tag) => new ConstTag(component, node, node.scope, tag));
|
||||
const sorted_consts_nodes = sort_consts_nodes(consts_nodes, component);
|
||||
sorted_consts_nodes.forEach((node) => node.parse_expression());
|
||||
const children_nodes = map_children(component, parent, node.scope, others);
|
||||
return [
|
||||
sorted_consts_nodes,
|
||||
/** @type {Array<Exclude<import('../interfaces.js').INode, ConstTag>>} */ (children_nodes)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ConstTag[]} consts_nodes
|
||||
* @param {import('../../Component.js').default} component
|
||||
*/
|
||||
function sort_consts_nodes(consts_nodes, component) {
|
||||
/** @typedef {{ assignees: Set<string>; dependencies: Set<string>; node: ConstTag; }} ConstNode */
|
||||
|
||||
/** @type {ConstNode[]} */
|
||||
const sorted_consts_nodes = [];
|
||||
|
||||
/** @type {ConstNode[]} */
|
||||
const unsorted_consts_nodes = consts_nodes.map((node) => {
|
||||
return {
|
||||
assignees: node.assignees,
|
||||
dependencies: node.dependencies,
|
||||
node
|
||||
};
|
||||
});
|
||||
const lookup = new Map();
|
||||
unsorted_consts_nodes.forEach((node) => {
|
||||
node.assignees.forEach((name) => {
|
||||
if (!lookup.has(name)) {
|
||||
lookup.set(name, []);
|
||||
}
|
||||
lookup.get(name).push(node);
|
||||
});
|
||||
});
|
||||
const cycle = check_graph_for_cycles(
|
||||
unsorted_consts_nodes.reduce((acc, node) => {
|
||||
node.assignees.forEach((v) => {
|
||||
node.dependencies.forEach((w) => {
|
||||
if (!node.assignees.has(w)) {
|
||||
acc.push([v, w]);
|
||||
}
|
||||
});
|
||||
});
|
||||
return acc;
|
||||
}, [])
|
||||
);
|
||||
if (cycle && cycle.length) {
|
||||
const node_list = lookup.get(cycle[0]);
|
||||
const node = node_list[0];
|
||||
component.error(node.node, compiler_errors.cyclical_const_tags(cycle));
|
||||
}
|
||||
|
||||
/** @param {ConstNode} node */
|
||||
const add_node = (node) => {
|
||||
if (sorted_consts_nodes.includes(node)) return;
|
||||
node.dependencies.forEach((name) => {
|
||||
if (node.assignees.has(name)) return;
|
||||
const earlier_nodes = lookup.get(name);
|
||||
if (earlier_nodes) {
|
||||
earlier_nodes.forEach(add_node);
|
||||
}
|
||||
});
|
||||
sorted_consts_nodes.push(node);
|
||||
};
|
||||
unsorted_consts_nodes.forEach(add_node);
|
||||
return sorted_consts_nodes.map((node) => node.node);
|
||||
}
|
17
node_modules/svelte/src/compiler/compile/nodes/shared/is_contextual.js
generated
vendored
Normal file
17
node_modules/svelte/src/compiler/compile/nodes/shared/is_contextual.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
import { is_reserved_keyword } from '../../utils/reserved_keywords.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../Component.js').default} component
|
||||
* @param {import('./TemplateScope.js').default} scope
|
||||
* @param {string} name
|
||||
*/
|
||||
export default function is_contextual(component, scope, name) {
|
||||
if (is_reserved_keyword(name)) return true;
|
||||
// if it's a name below root scope, it's contextual
|
||||
if (!scope.is_top_level(name)) return true;
|
||||
const variable = component.var_lookup.get(name);
|
||||
// hoistables, module declarations, and imports are non-contextual
|
||||
if (!variable || variable.hoistable) return false;
|
||||
// assume contextual
|
||||
return true;
|
||||
}
|
96
node_modules/svelte/src/compiler/compile/nodes/shared/map_children.js
generated
vendored
Normal file
96
node_modules/svelte/src/compiler/compile/nodes/shared/map_children.js
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
import AwaitBlock from '../AwaitBlock.js';
|
||||
import Body from '../Body.js';
|
||||
import ConstTag from '../ConstTag.js';
|
||||
import Comment from '../Comment.js';
|
||||
import EachBlock from '../EachBlock.js';
|
||||
import Document from '../Document.js';
|
||||
import Element from '../Element.js';
|
||||
import Head from '../Head.js';
|
||||
import IfBlock from '../IfBlock.js';
|
||||
import InlineComponent from '../InlineComponent.js';
|
||||
import KeyBlock from '../KeyBlock.js';
|
||||
import MustacheTag from '../MustacheTag.js';
|
||||
import Options from '../Options.js';
|
||||
import RawMustacheTag from '../RawMustacheTag.js';
|
||||
import DebugTag from '../DebugTag.js';
|
||||
import Slot from '../Slot.js';
|
||||
import SlotTemplate from '../SlotTemplate.js';
|
||||
import Text from '../Text.js';
|
||||
import Title from '../Title.js';
|
||||
import Window from '../Window.js';
|
||||
import { push_array } from '../../../utils/push_array.js';
|
||||
|
||||
/** @typedef {ReturnType<typeof map_children>} Children */
|
||||
|
||||
/** @param {any} type */
|
||||
function get_constructor(type) {
|
||||
switch (type) {
|
||||
case 'AwaitBlock':
|
||||
return AwaitBlock;
|
||||
case 'Body':
|
||||
return Body;
|
||||
case 'Comment':
|
||||
return Comment;
|
||||
case 'ConstTag':
|
||||
return ConstTag;
|
||||
case 'Document':
|
||||
return Document;
|
||||
case 'EachBlock':
|
||||
return EachBlock;
|
||||
case 'Element':
|
||||
return Element;
|
||||
case 'Head':
|
||||
return Head;
|
||||
case 'IfBlock':
|
||||
return IfBlock;
|
||||
case 'InlineComponent':
|
||||
return InlineComponent;
|
||||
case 'KeyBlock':
|
||||
return KeyBlock;
|
||||
case 'MustacheTag':
|
||||
return MustacheTag;
|
||||
case 'Options':
|
||||
return Options;
|
||||
case 'RawMustacheTag':
|
||||
return RawMustacheTag;
|
||||
case 'DebugTag':
|
||||
return DebugTag;
|
||||
case 'Slot':
|
||||
return Slot;
|
||||
case 'SlotTemplate':
|
||||
return SlotTemplate;
|
||||
case 'Text':
|
||||
return Text;
|
||||
case 'Title':
|
||||
return Title;
|
||||
case 'Window':
|
||||
return Window;
|
||||
default:
|
||||
throw new Error(`Not implemented: ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} component
|
||||
* @param {any} parent
|
||||
* @param {any} scope
|
||||
* @param {import('../../../interfaces.js').TemplateNode[]} children
|
||||
*/
|
||||
export default function map_children(component, parent, scope, children) {
|
||||
let last = null;
|
||||
let ignores = [];
|
||||
return children.map((child) => {
|
||||
const constructor = get_constructor(child.type);
|
||||
const use_ignores = child.type !== 'Text' && child.type !== 'Comment' && ignores.length;
|
||||
if (use_ignores) component.push_ignores(ignores);
|
||||
const node = new constructor(component, parent, scope, child);
|
||||
if (use_ignores) component.pop_ignores(), (ignores = []);
|
||||
if (node.type === 'Comment' && node.ignores.length) {
|
||||
push_array(ignores, node.ignores);
|
||||
}
|
||||
if (last) last.next = node;
|
||||
node.prev = last;
|
||||
last = node;
|
||||
return node;
|
||||
});
|
||||
}
|
532
node_modules/svelte/src/compiler/compile/render_dom/Block.js
generated
vendored
Normal file
532
node_modules/svelte/src/compiler/compile/render_dom/Block.js
generated
vendored
Normal file
@ -0,0 +1,532 @@
|
||||
import { b, x } from 'code-red';
|
||||
import { is_head } from './wrappers/shared/is_head.js';
|
||||
import { regex_double_quotes } from '../../utils/patterns.js';
|
||||
import { flatten } from '../../utils/flatten.js';
|
||||
|
||||
export default class Block {
|
||||
/**
|
||||
* @typedef {Object} Bindings
|
||||
* @property {import('estree').Identifier} object
|
||||
* @property {import('estree').Identifier} property
|
||||
* @property {import('estree').Node} snippet
|
||||
* @property {string} store
|
||||
* @property {(node:import('estree').Node) => import('estree').Node} modifier
|
||||
*/
|
||||
/**
|
||||
* @typedef {Object} BlockOptions
|
||||
* @property {Block} [parent]
|
||||
* @property {import('estree').Identifier} name
|
||||
* @property {string} type
|
||||
* @property {import('./Renderer.js').default} [renderer]
|
||||
* @property {string} [comment]
|
||||
* @property {import('estree').Identifier} [key]
|
||||
* @property {Map<string,Bindings>} [bindings]
|
||||
* @property {Set<string>} [dependencies]
|
||||
*/
|
||||
|
||||
/** @type {Block} */
|
||||
parent;
|
||||
|
||||
/** @type {import('./Renderer.js').default} */
|
||||
renderer;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
name;
|
||||
|
||||
/** @type {string} */
|
||||
type;
|
||||
|
||||
/** @type {string} */
|
||||
comment;
|
||||
|
||||
/** @type {import('./wrappers/shared/Wrapper.js').default[]} */
|
||||
wrappers;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
key;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
first;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
dependencies = new Set();
|
||||
|
||||
/** @type {Map<string, Bindings>} */
|
||||
bindings;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
binding_group_initialised = new Set();
|
||||
|
||||
/** @type {Set<import('./Renderer.js').BindingGroup>} */
|
||||
binding_groups = new Set();
|
||||
/**
|
||||
* @type {{
|
||||
* declarations: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* init: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* create: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* claim: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* hydrate: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* mount: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* measure: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* restore_measurements: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* fix: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* animate: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* intro: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* update: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* outro: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* destroy: Array<import('estree').Node | import('estree').Node[]>;
|
||||
* }}
|
||||
*/
|
||||
chunks;
|
||||
|
||||
/** @type {import('estree').Node[]} */
|
||||
event_listeners = [];
|
||||
|
||||
/** @type {boolean} */
|
||||
maintain_context;
|
||||
|
||||
/** @type {boolean} */
|
||||
has_animation;
|
||||
|
||||
/** @type {boolean} */
|
||||
has_intros;
|
||||
|
||||
/** @type {boolean} */
|
||||
has_outros;
|
||||
|
||||
/** @type {boolean} */
|
||||
has_intro_method; // could have the method without the transition, due to siblings
|
||||
|
||||
/** @type {boolean} */
|
||||
has_outro_method;
|
||||
|
||||
/** @type {number} */
|
||||
outros;
|
||||
|
||||
/** @type {Map<string, import('estree').Identifier>} */
|
||||
aliases;
|
||||
|
||||
/** @type {Map<string, { id: import('estree').Identifier; init?: import('estree').Node }>} */
|
||||
variables = new Map();
|
||||
|
||||
/** @type {(name: string) => import('estree').Identifier} */
|
||||
get_unique_name;
|
||||
/** */
|
||||
has_update_method = false;
|
||||
|
||||
/** @type {{ element_var: string; condition_expression?: any }} */
|
||||
autofocus;
|
||||
|
||||
/** @param {BlockOptions} options */
|
||||
constructor(options) {
|
||||
this.parent = options.parent;
|
||||
this.renderer = options.renderer;
|
||||
this.name = options.name;
|
||||
this.type = options.type;
|
||||
this.comment = options.comment;
|
||||
this.wrappers = [];
|
||||
// for keyed each blocks
|
||||
this.key = options.key;
|
||||
this.first = null;
|
||||
this.bindings = options.bindings;
|
||||
this.chunks = {
|
||||
declarations: [],
|
||||
init: [],
|
||||
create: [],
|
||||
claim: [],
|
||||
hydrate: [],
|
||||
mount: [],
|
||||
measure: [],
|
||||
restore_measurements: [],
|
||||
fix: [],
|
||||
animate: [],
|
||||
intro: [],
|
||||
update: [],
|
||||
outro: [],
|
||||
destroy: []
|
||||
};
|
||||
this.has_animation = false;
|
||||
this.has_intro_method = false; // a block could have an intro method but not intro transitions, e.g. if a sibling block has intros
|
||||
this.has_outro_method = false;
|
||||
this.outros = 0;
|
||||
this.get_unique_name = this.renderer.component.get_unique_name_maker();
|
||||
this.aliases = new Map();
|
||||
if (this.key) this.aliases.set('key', this.get_unique_name('key'));
|
||||
}
|
||||
|
||||
assign_variable_names() {
|
||||
/** @type {Set<string>} */
|
||||
const seen = new Set();
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const dupes = new Set();
|
||||
let i = this.wrappers.length;
|
||||
while (i--) {
|
||||
const wrapper = this.wrappers[i];
|
||||
if (!wrapper.var) continue;
|
||||
if (seen.has(wrapper.var.name)) {
|
||||
dupes.add(wrapper.var.name);
|
||||
}
|
||||
seen.add(wrapper.var.name);
|
||||
}
|
||||
const counts = new Map();
|
||||
i = this.wrappers.length;
|
||||
while (i--) {
|
||||
const wrapper = this.wrappers[i];
|
||||
if (!wrapper.var) continue;
|
||||
let suffix = '';
|
||||
if (dupes.has(wrapper.var.name)) {
|
||||
const i = counts.get(wrapper.var.name) || 0;
|
||||
counts.set(wrapper.var.name, i + 1);
|
||||
suffix = i;
|
||||
}
|
||||
wrapper.var.name = this.get_unique_name(wrapper.var.name + suffix).name;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {Set<string>} dependencies */
|
||||
add_dependencies(dependencies) {
|
||||
dependencies.forEach((dependency) => {
|
||||
this.dependencies.add(dependency);
|
||||
});
|
||||
this.has_update_method = true;
|
||||
if (this.parent) {
|
||||
this.parent.add_dependencies(dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('estree').Identifier} id
|
||||
* @param {import('estree').Node} render_statement
|
||||
* @param {import('estree').Node} claim_statement
|
||||
* @param {import('estree').Node} parent_node
|
||||
* @param {boolean} [no_detach]
|
||||
*/
|
||||
add_element(id, render_statement, claim_statement, parent_node, no_detach) {
|
||||
this.add_variable(id);
|
||||
this.chunks.create.push(b`${id} = ${render_statement};`);
|
||||
if (this.renderer.options.hydratable) {
|
||||
this.chunks.claim.push(b`${id} = ${claim_statement || render_statement};`);
|
||||
}
|
||||
if (parent_node) {
|
||||
this.chunks.mount.push(b`@append(${parent_node}, ${id});`);
|
||||
if (is_head(parent_node) && !no_detach) this.chunks.destroy.push(b`@detach(${id});`);
|
||||
} else {
|
||||
this.chunks.mount.push(b`@insert(#target, ${id}, #anchor);`);
|
||||
if (!no_detach) this.chunks.destroy.push(b`if (detaching) @detach(${id});`);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {boolean} [local] */
|
||||
add_intro(local) {
|
||||
this.has_intros = this.has_intro_method = true;
|
||||
if (!local && this.parent) this.parent.add_intro();
|
||||
}
|
||||
|
||||
/** @param {boolean} [local] */
|
||||
add_outro(local) {
|
||||
this.has_outros = this.has_outro_method = true;
|
||||
this.outros += 1;
|
||||
if (!local && this.parent) this.parent.add_outro();
|
||||
}
|
||||
|
||||
add_animation() {
|
||||
this.has_animation = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('estree').Identifier} id
|
||||
* @param {import('estree').Node} [init]
|
||||
*/
|
||||
add_variable(id, init) {
|
||||
if (this.variables.has(id.name)) {
|
||||
throw new Error(`Variable '${id.name}' already initialised with a different value`);
|
||||
}
|
||||
this.variables.set(id.name, { id, init });
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
alias(name) {
|
||||
if (!this.aliases.has(name)) {
|
||||
this.aliases.set(name, this.get_unique_name(name));
|
||||
}
|
||||
return this.aliases.get(name);
|
||||
}
|
||||
|
||||
/** @param {BlockOptions} options */
|
||||
child(options) {
|
||||
return new Block(Object.assign({}, this, { key: null }, options, { parent: this }));
|
||||
}
|
||||
|
||||
/** @param {any} [key] */
|
||||
get_contents(key) {
|
||||
const { dev } = this.renderer.options;
|
||||
if (this.has_outros) {
|
||||
this.add_variable({ type: 'Identifier', name: '#current' });
|
||||
if (this.chunks.intro.length > 0) {
|
||||
this.chunks.intro.push(b`#current = true;`);
|
||||
this.chunks.mount.push(b`#current = true;`);
|
||||
}
|
||||
if (this.chunks.outro.length > 0) {
|
||||
this.chunks.outro.push(b`#current = false;`);
|
||||
}
|
||||
}
|
||||
if (this.autofocus) {
|
||||
if (this.autofocus.condition_expression) {
|
||||
this.chunks.mount.push(
|
||||
b`if (${this.autofocus.condition_expression}) ${this.autofocus.element_var}.focus();`
|
||||
);
|
||||
} else {
|
||||
this.chunks.mount.push(b`${this.autofocus.element_var}.focus();`);
|
||||
}
|
||||
}
|
||||
this.render_binding_groups();
|
||||
this.render_listeners();
|
||||
|
||||
/** @type {Record<string, any>} */
|
||||
const properties = {};
|
||||
const noop = x`@noop`;
|
||||
properties.key = key;
|
||||
if (this.first) {
|
||||
properties.first = x`null`;
|
||||
this.chunks.hydrate.push(b`this.first = ${this.first};`);
|
||||
}
|
||||
if (this.chunks.create.length === 0 && this.chunks.hydrate.length === 0) {
|
||||
properties.create = noop;
|
||||
} else {
|
||||
const hydrate =
|
||||
this.chunks.hydrate.length > 0 &&
|
||||
(this.renderer.options.hydratable ? b`this.h();` : this.chunks.hydrate);
|
||||
properties.create = x`function #create() {
|
||||
${this.chunks.create}
|
||||
${hydrate}
|
||||
}`;
|
||||
}
|
||||
if (this.renderer.options.hydratable || this.chunks.claim.length > 0) {
|
||||
if (this.chunks.claim.length === 0 && this.chunks.hydrate.length === 0) {
|
||||
properties.claim = noop;
|
||||
} else {
|
||||
properties.claim = x`function #claim(#nodes) {
|
||||
${this.chunks.claim}
|
||||
${this.renderer.options.hydratable && this.chunks.hydrate.length > 0 && b`this.h();`}
|
||||
}`;
|
||||
}
|
||||
}
|
||||
if (this.renderer.options.hydratable && this.chunks.hydrate.length > 0) {
|
||||
properties.hydrate = x`function #hydrate() {
|
||||
${this.chunks.hydrate}
|
||||
}`;
|
||||
}
|
||||
if (this.chunks.mount.length === 0) {
|
||||
properties.mount = noop;
|
||||
} else if (this.event_listeners.length === 0) {
|
||||
properties.mount = x`function #mount(#target, #anchor) {
|
||||
${this.chunks.mount}
|
||||
}`;
|
||||
} else {
|
||||
properties.mount = x`function #mount(#target, #anchor) {
|
||||
${this.chunks.mount}
|
||||
}`;
|
||||
}
|
||||
if (this.has_update_method || this.maintain_context) {
|
||||
if (this.chunks.update.length === 0 && !this.maintain_context) {
|
||||
properties.update = noop;
|
||||
} else {
|
||||
const ctx = this.maintain_context ? x`#new_ctx` : x`#ctx`;
|
||||
|
||||
/** @type {import('estree').Identifier | import('estree').ArrayPattern} */
|
||||
let dirty = { type: 'Identifier', name: '#dirty' };
|
||||
if (!this.renderer.context_overflow && !this.parent) {
|
||||
dirty = { type: 'ArrayPattern', elements: [dirty] };
|
||||
}
|
||||
properties.update = x`function #update(${ctx}, ${dirty}) {
|
||||
${this.maintain_context && b`#ctx = ${ctx};`}
|
||||
${this.chunks.update}
|
||||
}`;
|
||||
}
|
||||
}
|
||||
if (this.has_animation) {
|
||||
properties.measure = x`function #measure() {
|
||||
${this.chunks.measure}
|
||||
}`;
|
||||
if (this.chunks.restore_measurements.length) {
|
||||
properties.restore_measurements = x`function #restore_measurements(#measurement) {
|
||||
${this.chunks.restore_measurements}
|
||||
}`;
|
||||
}
|
||||
properties.fix = x`function #fix() {
|
||||
${this.chunks.fix}
|
||||
}`;
|
||||
properties.animate = x`function #animate() {
|
||||
${this.chunks.animate}
|
||||
}`;
|
||||
}
|
||||
if (this.has_intro_method || this.has_outro_method) {
|
||||
if (this.chunks.intro.length === 0) {
|
||||
properties.intro = noop;
|
||||
} else {
|
||||
properties.intro = x`function #intro(#local) {
|
||||
${this.has_outros && b`if (#current) return;`}
|
||||
${this.chunks.intro}
|
||||
}`;
|
||||
}
|
||||
if (this.chunks.outro.length === 0) {
|
||||
properties.outro = noop;
|
||||
} else {
|
||||
properties.outro = x`function #outro(#local) {
|
||||
${this.chunks.outro}
|
||||
}`;
|
||||
}
|
||||
}
|
||||
if (this.chunks.destroy.length === 0) {
|
||||
properties.destroy = noop;
|
||||
} else {
|
||||
const dispose_elements = [];
|
||||
// Coalesce if blocks with the same condition
|
||||
const others = flatten(this.chunks.destroy).filter(
|
||||
/** @param {import('estree').Node} node */
|
||||
(node) => {
|
||||
if (
|
||||
node.type === 'IfStatement' &&
|
||||
node.test.type === 'Identifier' &&
|
||||
node.test.name === 'detaching'
|
||||
) {
|
||||
dispose_elements.push(node.consequent);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
properties.destroy = x`function #destroy(detaching) {
|
||||
${dispose_elements.length ? b`if (detaching) { ${dispose_elements} }` : null}
|
||||
${others}
|
||||
}`;
|
||||
}
|
||||
if (!this.renderer.component.compile_options.dev) {
|
||||
// allow shorthand names
|
||||
for (const name in properties) {
|
||||
const property = properties[name];
|
||||
if (property) property.id = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {any} */
|
||||
const return_value = x`{
|
||||
key: ${properties.key},
|
||||
first: ${properties.first},
|
||||
c: ${properties.create},
|
||||
l: ${properties.claim},
|
||||
h: ${properties.hydrate},
|
||||
m: ${properties.mount},
|
||||
p: ${properties.update},
|
||||
r: ${properties.measure},
|
||||
s: ${properties.restore_measurements},
|
||||
f: ${properties.fix},
|
||||
a: ${properties.animate},
|
||||
i: ${properties.intro},
|
||||
o: ${properties.outro},
|
||||
d: ${properties.destroy}
|
||||
}`;
|
||||
const block = dev && this.get_unique_name('block');
|
||||
const body = b`
|
||||
${this.chunks.declarations}
|
||||
|
||||
${Array.from(this.variables.values()).map(({ id, init }) => {
|
||||
return init ? b`let ${id} = ${init}` : b`let ${id}`;
|
||||
})}
|
||||
|
||||
${this.chunks.init}
|
||||
|
||||
${
|
||||
dev
|
||||
? b`
|
||||
const ${block} = ${return_value};
|
||||
@dispatch_dev("SvelteRegisterBlock", {
|
||||
block: ${block},
|
||||
id: ${this.name || 'create_fragment'}.name,
|
||||
type: "${this.type}",
|
||||
source: "${this.comment ? this.comment.replace(regex_double_quotes, '\\"') : ''}",
|
||||
ctx: #ctx
|
||||
});
|
||||
return ${block};`
|
||||
: b`
|
||||
return ${return_value};`
|
||||
}
|
||||
`;
|
||||
return body;
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
has_content() {
|
||||
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 ||
|
||||
this.has_animation
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const key = this.key && this.get_unique_name('key');
|
||||
|
||||
/** @type {any[]} */
|
||||
const args = [x`#ctx`];
|
||||
if (key) args.unshift(key);
|
||||
const fn = b`function ${this.name}(${args}) {
|
||||
${this.get_contents(key)}
|
||||
}`;
|
||||
return this.comment
|
||||
? b`
|
||||
// ${this.comment}
|
||||
${fn}`
|
||||
: fn;
|
||||
}
|
||||
|
||||
/** @param {string} chunk */
|
||||
render_listeners(chunk = '') {
|
||||
if (this.event_listeners.length > 0) {
|
||||
this.add_variable({ type: 'Identifier', name: '#mounted' });
|
||||
this.chunks.destroy.push(b`#mounted = false`);
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
const dispose = {
|
||||
type: 'Identifier',
|
||||
name: `#dispose${chunk}`
|
||||
};
|
||||
this.add_variable(dispose);
|
||||
if (this.event_listeners.length === 1) {
|
||||
this.chunks.mount.push(b`
|
||||
if (!#mounted) {
|
||||
${dispose} = ${this.event_listeners[0]};
|
||||
#mounted = true;
|
||||
}
|
||||
`);
|
||||
this.chunks.destroy.push(b`${dispose}();`);
|
||||
} else {
|
||||
this.chunks.mount.push(b`
|
||||
if (!#mounted) {
|
||||
${dispose} = [
|
||||
${this.event_listeners}
|
||||
];
|
||||
#mounted = true;
|
||||
}
|
||||
`);
|
||||
this.chunks.destroy.push(b`@run_all(${dispose});`);
|
||||
}
|
||||
}
|
||||
}
|
||||
render_binding_groups() {
|
||||
for (const binding_group of this.binding_groups) {
|
||||
binding_group.render(this);
|
||||
}
|
||||
}
|
||||
}
|
335
node_modules/svelte/src/compiler/compile/render_dom/Renderer.js
generated
vendored
Normal file
335
node_modules/svelte/src/compiler/compile/render_dom/Renderer.js
generated
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
import Block from './Block.js';
|
||||
import FragmentWrapper from './wrappers/Fragment.js';
|
||||
import { x } from 'code-red';
|
||||
import flatten_reference from '../utils/flatten_reference.js';
|
||||
import { reserved_keywords } from '../utils/reserved_keywords.js';
|
||||
import { renderer_invalidate } from './invalidate.js';
|
||||
|
||||
export default class Renderer {
|
||||
/**
|
||||
* @typedef {Object} ContextMember
|
||||
* @property {string} name
|
||||
* @property {import('estree').Literal} index
|
||||
* @property {boolean} is_contextual
|
||||
* @property {boolean} is_non_contextual
|
||||
* @property {import('../../interfaces.js').Var} variable
|
||||
* @property {number} priority
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Array<{
|
||||
* n: number;
|
||||
* names: string[];
|
||||
* }>} BitMasks
|
||||
*/
|
||||
|
||||
/** @type {import('../Component.js').default} */
|
||||
component; // TODO Maybe Renderer shouldn't know about Component?
|
||||
|
||||
/** @type {import('../../interfaces.js').CompileOptions} */
|
||||
options;
|
||||
|
||||
/** @type {ContextMember[]} */
|
||||
context = [];
|
||||
|
||||
/** @type {ContextMember[]} */
|
||||
initial_context = [];
|
||||
|
||||
/** @type {Map<string, ContextMember>} */
|
||||
context_lookup = new Map();
|
||||
|
||||
/** @type {boolean} */
|
||||
context_overflow;
|
||||
|
||||
/** @type {Array<import('./Block.js').default | import('estree').Node | import('estree').Node[]>} */
|
||||
blocks = [];
|
||||
|
||||
/** @type {Set<string>} */
|
||||
readonly = new Set();
|
||||
|
||||
/** @type {Array<import('estree').Node | import('estree').Node[]>} */
|
||||
meta_bindings = []; // initial values for e.g. window.innerWidth, if there's a <svelte:window> meta tag
|
||||
|
||||
/** @type {Map<string, BindingGroup>} */
|
||||
binding_groups = new Map();
|
||||
|
||||
/** @type {import('./Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('./wrappers/Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
file_var;
|
||||
|
||||
/**
|
||||
* Use this for stack traces. It is 1-based and acts on pre-processed sources.
|
||||
* Use `meta_locate` for metadata on DOM elements.
|
||||
* @type {(c: number) => { line: number; column: number }}
|
||||
*/
|
||||
locate;
|
||||
|
||||
/**
|
||||
* Use this for metadata on DOM elements. It is 1-based and acts on sources that have not been pre-processed.
|
||||
* Use `locate` for source mappings.
|
||||
* @type {(c: number) => { line: number; column: number }}
|
||||
*/
|
||||
meta_locate;
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('../../interfaces.js').CompileOptions} options
|
||||
*/
|
||||
constructor(component, options) {
|
||||
this.component = component;
|
||||
this.options = options;
|
||||
this.locate = component.locate; // TODO messy
|
||||
this.meta_locate = component.meta_locate; // TODO messy
|
||||
this.file_var = options.dev && this.component.get_unique_name('file');
|
||||
component.vars
|
||||
.filter((v) => !v.hoistable || (v.export_name && !v.module))
|
||||
.forEach((v) => this.add_to_context(v.name));
|
||||
// ensure store values are included in context
|
||||
component.vars.filter((v) => v.subscribable).forEach((v) => this.add_to_context(`$${v.name}`));
|
||||
reserved_keywords.forEach((keyword) => {
|
||||
if (component.var_lookup.has(keyword)) {
|
||||
this.add_to_context(keyword);
|
||||
}
|
||||
});
|
||||
if (component.slots.size > 0) {
|
||||
this.add_to_context('$$scope');
|
||||
this.add_to_context('#slots');
|
||||
}
|
||||
// main block
|
||||
this.block = new Block({
|
||||
renderer: this,
|
||||
name: null,
|
||||
type: 'component',
|
||||
key: null,
|
||||
bindings: new Map(),
|
||||
dependencies: new Set()
|
||||
});
|
||||
this.block.has_update_method = true;
|
||||
this.fragment = new FragmentWrapper(
|
||||
this,
|
||||
this.block,
|
||||
component.fragment.children,
|
||||
null,
|
||||
true,
|
||||
null
|
||||
);
|
||||
// TODO messy
|
||||
this.blocks.forEach((block) => {
|
||||
if (block instanceof Block) {
|
||||
block.assign_variable_names();
|
||||
}
|
||||
});
|
||||
this.block.assign_variable_names();
|
||||
this.fragment.render(this.block, null, /** @type {import('estree').Identifier} */ (x`#nodes`));
|
||||
this.context_overflow = this.context.length > 31;
|
||||
this.context.forEach((member) => {
|
||||
const { variable } = member;
|
||||
if (variable) {
|
||||
member.priority += 2;
|
||||
if (variable.mutated || variable.reassigned) member.priority += 4;
|
||||
// these determine whether variable is included in initial context
|
||||
// array, so must have the highest priority
|
||||
if (variable.is_reactive_dependency && (variable.mutated || variable.reassigned))
|
||||
member.priority += 16;
|
||||
if (variable.export_name) member.priority += 32;
|
||||
if (variable.referenced) member.priority += 64;
|
||||
} else if (member.is_non_contextual) {
|
||||
// determine whether variable is included in initial context
|
||||
// array, so must have the highest priority
|
||||
member.priority += 8;
|
||||
}
|
||||
if (!member.is_contextual) {
|
||||
member.priority += 1;
|
||||
}
|
||||
});
|
||||
this.context.sort(
|
||||
(a, b) =>
|
||||
b.priority - a.priority ||
|
||||
/** @type {number} */ (a.index.value) - /** @type {number} */ (b.index.value)
|
||||
);
|
||||
this.context.forEach((member, i) => (member.index.value = i));
|
||||
let i = this.context.length;
|
||||
while (i--) {
|
||||
const member = this.context[i];
|
||||
if (member.variable) {
|
||||
if (
|
||||
member.variable.referenced ||
|
||||
member.variable.export_name ||
|
||||
(member.variable.is_reactive_dependency &&
|
||||
(member.variable.mutated || member.variable.reassigned))
|
||||
)
|
||||
break;
|
||||
} else if (member.is_non_contextual) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.initial_context = this.context.slice(0, i + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {any} contextual
|
||||
*/
|
||||
add_to_context(name, contextual = false) {
|
||||
if (!this.context_lookup.has(name)) {
|
||||
/** @type {ContextMember} */
|
||||
const member = {
|
||||
name,
|
||||
index: { type: 'Literal', value: this.context.length },
|
||||
is_contextual: false,
|
||||
is_non_contextual: false,
|
||||
variable: null,
|
||||
priority: 0
|
||||
};
|
||||
this.context_lookup.set(name, member);
|
||||
this.context.push(member);
|
||||
}
|
||||
const member = this.context_lookup.get(name);
|
||||
if (contextual) {
|
||||
member.is_contextual = true;
|
||||
} else {
|
||||
member.is_non_contextual = true;
|
||||
member.variable = this.component.var_lookup.get(name);
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {unknown} [value]
|
||||
* @param {boolean} main_execution_context
|
||||
*/
|
||||
invalidate(name, value, main_execution_context = false) {
|
||||
return renderer_invalidate(this, name, value, main_execution_context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} names
|
||||
* @param {any} is_reactive_declaration
|
||||
* @returns {import('estree').Expression}
|
||||
*/
|
||||
dirty(names, is_reactive_declaration = false) {
|
||||
const renderer = this;
|
||||
const dirty = /** @type {| import('estree').Identifier
|
||||
| import('estree').MemberExpression} */ (
|
||||
is_reactive_declaration ? x`$$self.$$.dirty` : x`#dirty`
|
||||
);
|
||||
const get_bitmask = () => {
|
||||
/** @type {BitMasks} */
|
||||
const bitmask = [];
|
||||
names.forEach((name) => {
|
||||
const member = renderer.context_lookup.get(name);
|
||||
if (!member) return;
|
||||
if (member.index.value === -1) {
|
||||
throw new Error('unset index');
|
||||
}
|
||||
const value = /** @type {number} */ (member.index.value);
|
||||
const i = (value / 31) | 0;
|
||||
const n = 1 << value % 31;
|
||||
if (!bitmask[i]) bitmask[i] = { n: 0, names: [] };
|
||||
bitmask[i].n |= n;
|
||||
bitmask[i].names.push(name);
|
||||
});
|
||||
return bitmask;
|
||||
};
|
||||
// TODO: context-overflow make it less gross
|
||||
return /** @type {any} */ ({
|
||||
// Using a ParenthesizedExpression allows us to create
|
||||
// the expression lazily. TODO would be better if
|
||||
// context was determined before rendering, so that
|
||||
// this indirection was unnecessary
|
||||
type: 'ParenthesizedExpression',
|
||||
get expression() {
|
||||
const bitmask = get_bitmask();
|
||||
if (!bitmask.length) {
|
||||
return /** @type {import('estree').BinaryExpression} */ (
|
||||
x`${dirty} & /*${names.join(', ')}*/ 0`
|
||||
);
|
||||
}
|
||||
if (renderer.context_overflow) {
|
||||
return bitmask
|
||||
.map((b, i) => ({ b, i }))
|
||||
.filter(({ b }) => b)
|
||||
.map(({ b, i }) => x`${dirty}[${i}] & /*${b.names.join(', ')}*/ ${b.n}`)
|
||||
.reduce((lhs, rhs) => x`${lhs} | ${rhs}`);
|
||||
}
|
||||
return /** @type {import('estree').BinaryExpression} */ (
|
||||
x`${dirty} & /*${names.join(', ')}*/ ${bitmask[0].n}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
// NOTE: this method may be called before this.context_overflow / this.context is fully defined
|
||||
// therefore, they can only be evaluated later in a getter function
|
||||
|
||||
/** @returns {import('estree').UnaryExpression | import('estree').ArrayExpression} */
|
||||
get_initial_dirty() {
|
||||
const _this = this;
|
||||
// TODO: context-overflow make it less gross
|
||||
|
||||
/** @type {import('estree').UnaryExpression} */
|
||||
const val = /** @type {import('estree').UnaryExpression} */ (x`-1`);
|
||||
return {
|
||||
get type() {
|
||||
return _this.context_overflow ? 'ArrayExpression' : 'UnaryExpression';
|
||||
},
|
||||
// as [-1]
|
||||
get elements() {
|
||||
const elements = [];
|
||||
for (let i = 0; i < _this.context.length; i += 31) {
|
||||
elements.push(val);
|
||||
}
|
||||
return elements;
|
||||
},
|
||||
// as -1
|
||||
operator: val.operator,
|
||||
prefix: val.prefix,
|
||||
argument: val.argument
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | import('estree').Identifier | import('estree').MemberExpression} node
|
||||
* @param {string | void} ctx
|
||||
*/
|
||||
reference(node, ctx = '#ctx') {
|
||||
if (typeof node === 'string') {
|
||||
node = { type: 'Identifier', name: node };
|
||||
}
|
||||
const { name, nodes } = flatten_reference(node);
|
||||
const member = this.context_lookup.get(name);
|
||||
// TODO is this correct?
|
||||
if (this.component.var_lookup.get(name)) {
|
||||
this.component.add_reference(node, name);
|
||||
}
|
||||
if (member !== undefined) {
|
||||
const replacement = /** @type {import('estree').MemberExpression} */ (
|
||||
x`/*${member.name}*/ ${ctx}[${member.index}]`
|
||||
);
|
||||
if (nodes[0].loc) replacement.object.loc = nodes[0].loc;
|
||||
nodes[0] = replacement;
|
||||
return nodes.reduce((lhs, rhs) => x`${lhs}.${rhs}`);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/** @param {import('./Block.js').default | import('estree').Node | import('estree').Node[]} block */
|
||||
remove_block(block) {
|
||||
this.blocks.splice(this.blocks.indexOf(block), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} BindingGroup
|
||||
* @property {(to_reference?:boolean)=>import('estree').Node} binding_group
|
||||
* @property {string[]} contexts
|
||||
* @property {Set<string>} list_dependencies
|
||||
* @property {string} keypath
|
||||
* @property {(block:Block,element:import('estree').PrivateIdentifier) => void} add_element
|
||||
* @property {(block:Block)=>void} render
|
||||
*/
|
623
node_modules/svelte/src/compiler/compile/render_dom/index.js
generated
vendored
Normal file
623
node_modules/svelte/src/compiler/compile/render_dom/index.js
generated
vendored
Normal file
@ -0,0 +1,623 @@
|
||||
import { b, x, p } from 'code-red';
|
||||
import Renderer from './Renderer.js';
|
||||
import { walk } from 'estree-walker';
|
||||
import { extract_names } from 'periscopic';
|
||||
import { invalidate } from './invalidate.js';
|
||||
import { apply_preprocessor_sourcemap } from '../../utils/mapped_code.js';
|
||||
import { flatten } from '../../utils/flatten.js';
|
||||
import check_enable_sourcemap from '../utils/check_enable_sourcemap.js';
|
||||
import { push_array } from '../../utils/push_array.js';
|
||||
|
||||
/**
|
||||
* @param {import('../Component.js').default} component
|
||||
* @param {import('../../interfaces.js').CompileOptions} options
|
||||
* @returns {{ js: import('estree').Node[]; css: import('../../interfaces.js').CssResult; }}
|
||||
*/
|
||||
export default function dom(component, options) {
|
||||
const { name } = component;
|
||||
const renderer = new Renderer(component, options);
|
||||
const { block } = renderer;
|
||||
block.has_outro_method = true;
|
||||
/** @type {import('estree').Node[][]} */
|
||||
const body = [];
|
||||
if (renderer.file_var) {
|
||||
const file = component.file ? x`"${component.file}"` : x`undefined`;
|
||||
body.push(b`const ${renderer.file_var} = ${file};`);
|
||||
}
|
||||
const css = component.stylesheet.render(options.filename);
|
||||
const css_sourcemap_enabled = check_enable_sourcemap(options.enableSourcemap, 'css');
|
||||
if (css_sourcemap_enabled) {
|
||||
css.map = apply_preprocessor_sourcemap(
|
||||
options.filename,
|
||||
css.map,
|
||||
/** @type {string | import('@ampproject/remapping').RawSourceMap | import('@ampproject/remapping').DecodedSourceMap} */ (
|
||||
options.sourcemap
|
||||
)
|
||||
);
|
||||
} else {
|
||||
css.map = null;
|
||||
}
|
||||
const styles =
|
||||
css_sourcemap_enabled && component.stylesheet.has_styles && options.dev
|
||||
? `${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */`
|
||||
: css.code;
|
||||
const add_css = component.get_unique_name('add_css');
|
||||
const should_add_css = !!styles && (options.customElement || options.css === 'injected');
|
||||
if (should_add_css) {
|
||||
body.push(b`
|
||||
function ${add_css}(target) {
|
||||
@append_styles(target, "${component.stylesheet.id}", "${styles}");
|
||||
}
|
||||
`);
|
||||
}
|
||||
// fix order
|
||||
// TODO the deconflicted names of blocks are reversed... should set them here
|
||||
const blocks = renderer.blocks.slice().reverse();
|
||||
push_array(
|
||||
body,
|
||||
blocks.map((block) => {
|
||||
// TODO this is a horrible mess — renderer.blocks
|
||||
// contains a mixture of Blocks and Nodes
|
||||
if (/** @type {import('./Block.js').default} */ (block).render)
|
||||
return /** @type {import('./Block.js').default} */ (block).render();
|
||||
return block;
|
||||
})
|
||||
);
|
||||
if (options.dev && !options.hydratable) {
|
||||
block.chunks.claim.push(
|
||||
b`throw new @_Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`
|
||||
);
|
||||
}
|
||||
const uses_slots = component.var_lookup.has('$$slots');
|
||||
|
||||
/** @type {import('estree').Node[] | undefined} */
|
||||
let compute_slots;
|
||||
if (uses_slots) {
|
||||
compute_slots = b`
|
||||
const $$slots = @compute_slots(#slots);
|
||||
`;
|
||||
}
|
||||
const uses_props = component.var_lookup.has('$$props');
|
||||
const uses_rest = component.var_lookup.has('$$restProps');
|
||||
const $$props = uses_props || uses_rest ? '$$new_props' : '$$props';
|
||||
const props = component.vars.filter((variable) => !variable.module && variable.export_name);
|
||||
const writable_props = props.filter((variable) => variable.writable);
|
||||
const omit_props_names = component.get_unique_name('omit_props_names');
|
||||
const compute_rest = x`@compute_rest_props($$props, ${omit_props_names.name})`;
|
||||
const rest = uses_rest
|
||||
? b`
|
||||
const ${omit_props_names.name} = [${props.map((prop) => `"${prop.export_name}"`).join(',')}];
|
||||
let $$restProps = ${compute_rest};
|
||||
`
|
||||
: null;
|
||||
const set =
|
||||
uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0
|
||||
? x`
|
||||
${$$props} => {
|
||||
${
|
||||
uses_props &&
|
||||
renderer.invalidate(
|
||||
'$$props',
|
||||
x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`
|
||||
)
|
||||
}
|
||||
${
|
||||
uses_rest &&
|
||||
!uses_props &&
|
||||
x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`
|
||||
}
|
||||
${uses_rest && renderer.invalidate('$$restProps', x`$$restProps = ${compute_rest}`)}
|
||||
${writable_props.map(
|
||||
(prop) =>
|
||||
b`if ('${prop.export_name}' in ${$$props}) ${renderer.invalidate(
|
||||
prop.name,
|
||||
x`${prop.name} = ${$$props}.${prop.export_name}`
|
||||
)};`
|
||||
)}
|
||||
${
|
||||
component.slots.size > 0 &&
|
||||
b`if ('$$scope' in ${$$props}) ${renderer.invalidate(
|
||||
'$$scope',
|
||||
x`$$scope = ${$$props}.$$scope`
|
||||
)};`
|
||||
}
|
||||
}
|
||||
`
|
||||
: null;
|
||||
const accessors = [];
|
||||
const not_equal = component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`;
|
||||
|
||||
/** @type {import('estree').Node[] | import('estree').Node} */
|
||||
let missing_props_check;
|
||||
|
||||
/** @type {import('estree').Expression} */
|
||||
let inject_state;
|
||||
|
||||
/** @type {import('estree').Expression} */
|
||||
let capture_state;
|
||||
|
||||
/** @type {import('estree').Node[] | import('estree').Node} */
|
||||
let props_inject;
|
||||
props.forEach((prop) => {
|
||||
const variable = component.var_lookup.get(prop.name);
|
||||
if (!variable.writable || component.component_options.accessors) {
|
||||
accessors.push({
|
||||
type: 'MethodDefinition',
|
||||
kind: 'get',
|
||||
key: { type: 'Identifier', name: prop.export_name },
|
||||
value: x`function() {
|
||||
return ${
|
||||
prop.hoistable
|
||||
? prop.name
|
||||
: x`this.$$.ctx[${renderer.context_lookup.get(prop.name).index}]`
|
||||
}
|
||||
}`
|
||||
});
|
||||
} else if (component.compile_options.dev) {
|
||||
accessors.push({
|
||||
type: 'MethodDefinition',
|
||||
kind: 'get',
|
||||
key: { type: 'Identifier', name: prop.export_name },
|
||||
value: x`function() {
|
||||
throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
|
||||
}`
|
||||
});
|
||||
}
|
||||
if (component.component_options.accessors) {
|
||||
if (variable.writable && !renderer.readonly.has(prop.name)) {
|
||||
accessors.push({
|
||||
type: 'MethodDefinition',
|
||||
kind: 'set',
|
||||
key: { type: 'Identifier', name: prop.export_name },
|
||||
value: x`function(${prop.name}) {
|
||||
this.$$set({ ${prop.export_name}: ${prop.name} });
|
||||
@flush();
|
||||
}`
|
||||
});
|
||||
} else if (component.compile_options.dev) {
|
||||
accessors.push({
|
||||
type: 'MethodDefinition',
|
||||
kind: 'set',
|
||||
key: { type: 'Identifier', name: prop.export_name },
|
||||
value: x`function(value) {
|
||||
throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
|
||||
}`
|
||||
});
|
||||
}
|
||||
} else if (component.compile_options.dev) {
|
||||
accessors.push({
|
||||
type: 'MethodDefinition',
|
||||
kind: 'set',
|
||||
key: { type: 'Identifier', name: prop.export_name },
|
||||
value: x`function(value) {
|
||||
throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
|
||||
}`
|
||||
});
|
||||
}
|
||||
});
|
||||
component.instance_exports_from.forEach((exports_from) => {
|
||||
const import_declaration = {
|
||||
...exports_from,
|
||||
type: 'ImportDeclaration',
|
||||
specifiers: [],
|
||||
source: exports_from.source
|
||||
};
|
||||
component.imports.push(/** @type {import('estree').ImportDeclaration} */ (import_declaration));
|
||||
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 '<svelte:options accessors/>'");
|
||||
}`
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if (component.compile_options.dev) {
|
||||
// checking that expected ones were passed
|
||||
const expected = props.filter((prop) => prop.writable && !prop.initialised);
|
||||
if (expected.length) {
|
||||
missing_props_check = b`
|
||||
$$self.$$.on_mount.push(function () {
|
||||
${expected.map(
|
||||
(prop) => b`
|
||||
if (${prop.name} === undefined && !(('${prop.export_name}' in $$props) || $$self.$$.bound[$$self.$$.props['${prop.export_name}']])) {
|
||||
@_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
|
||||
}`
|
||||
)}
|
||||
});
|
||||
`;
|
||||
}
|
||||
const capturable_vars = component.vars.filter(
|
||||
(v) => !v.internal && !v.global && !v.name.startsWith('$$')
|
||||
);
|
||||
if (capturable_vars.length > 0) {
|
||||
capture_state = x`() => ({ ${capturable_vars.map((prop) => p`${prop.name}`)} })`;
|
||||
}
|
||||
const injectable_vars = capturable_vars.filter(
|
||||
(v) => !v.module && v.writable && v.name[0] !== '$'
|
||||
);
|
||||
if (uses_props || injectable_vars.length > 0) {
|
||||
inject_state = x`
|
||||
${$$props} => {
|
||||
${
|
||||
uses_props &&
|
||||
renderer.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), $$new_props)`)
|
||||
}
|
||||
${injectable_vars.map(
|
||||
(v) =>
|
||||
b`if ('${v.name}' in $$props) ${renderer.invalidate(
|
||||
v.name,
|
||||
x`${v.name} = ${$$props}.${v.name}`
|
||||
)};`
|
||||
)}
|
||||
}
|
||||
`;
|
||||
props_inject = b`
|
||||
if ($$props && "$$inject" in $$props) {
|
||||
$$self.$inject_state($$props.$$inject);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
// instrument assignments
|
||||
if (component.ast.instance) {
|
||||
let scope = component.instance_scope;
|
||||
const map = component.instance_scope_map;
|
||||
|
||||
/** @type {import('estree').Node | null} */
|
||||
let execution_context = null;
|
||||
walk(component.ast.instance.content, {
|
||||
enter(node) {
|
||||
if (map.has(node)) {
|
||||
scope = /** @type {import('periscopic').Scope} */ (map.get(node));
|
||||
if (!execution_context && !scope.block) {
|
||||
execution_context = node;
|
||||
}
|
||||
} else if (
|
||||
!execution_context &&
|
||||
node.type === 'LabeledStatement' &&
|
||||
node.label.name === '$'
|
||||
) {
|
||||
execution_context = node;
|
||||
}
|
||||
},
|
||||
leave(node) {
|
||||
if (map.has(node)) {
|
||||
scope = scope.parent;
|
||||
}
|
||||
if (execution_context === node) {
|
||||
execution_context = null;
|
||||
}
|
||||
if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') {
|
||||
const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument;
|
||||
// normally (`a = 1`, `b.c = 2`), there'll be a single name
|
||||
// (a or b). In destructuring cases (`[d, e] = [e, d]`) there
|
||||
// may be more, in which case we need to tack the extra ones
|
||||
// onto the initial function call
|
||||
const names = new Set(extract_names(/** @type {import('estree').Node} */ (assignee)));
|
||||
this.replace(invalidate(renderer, scope, node, names, execution_context === null));
|
||||
}
|
||||
}
|
||||
});
|
||||
component.rewrite_props(({ name, reassigned, export_name }) => {
|
||||
const value = `$${name}`;
|
||||
const i = renderer.context_lookup.get(`$${name}`).index;
|
||||
const insert =
|
||||
reassigned || export_name
|
||||
? b`${`$$subscribe_${name}`}()`
|
||||
: b`@component_subscribe($$self, ${name}, #value => $$invalidate(${i}, ${value} = #value))`;
|
||||
if (component.compile_options.dev) {
|
||||
return b`@validate_store(${name}, '${name}'); ${insert}`;
|
||||
}
|
||||
return insert;
|
||||
});
|
||||
}
|
||||
const args = [x`$$self`];
|
||||
const has_invalidate =
|
||||
props.length > 0 ||
|
||||
component.has_reactive_assignments ||
|
||||
component.slots.size > 0 ||
|
||||
capture_state ||
|
||||
inject_state;
|
||||
if (has_invalidate) {
|
||||
args.push(x`$$props`, x`$$invalidate`);
|
||||
} else if (component.compile_options.dev) {
|
||||
// $$props arg is still needed for unknown prop check
|
||||
args.push(x`$$props`);
|
||||
}
|
||||
// has_create_fragment is intentionally to be true in dev mode.
|
||||
const has_create_fragment = component.compile_options.dev || block.has_content();
|
||||
if (has_create_fragment) {
|
||||
body.push(b`
|
||||
function create_fragment(#ctx) {
|
||||
${block.get_contents()}
|
||||
}
|
||||
`);
|
||||
}
|
||||
body.push(b`
|
||||
${component.extract_javascript(component.ast.module)}
|
||||
|
||||
${component.fully_hoisted}
|
||||
`);
|
||||
const filtered_props = props.filter((prop) => {
|
||||
const variable = component.var_lookup.get(prop.name);
|
||||
if (variable.hoistable) return false;
|
||||
return prop.name[0] !== '$';
|
||||
});
|
||||
const reactive_stores = component.vars.filter(
|
||||
(variable) => variable.name[0] === '$' && variable.name[1] !== '$'
|
||||
);
|
||||
const instance_javascript = component.extract_javascript(component.ast.instance);
|
||||
const has_definition =
|
||||
component.compile_options.dev ||
|
||||
(instance_javascript && instance_javascript.length > 0) ||
|
||||
filtered_props.length > 0 ||
|
||||
uses_props ||
|
||||
component.partly_hoisted.length > 0 ||
|
||||
renderer.initial_context.length > 0 ||
|
||||
component.reactive_declarations.length > 0 ||
|
||||
capture_state ||
|
||||
inject_state;
|
||||
const definition = has_definition
|
||||
? component.alias('instance')
|
||||
: { type: 'Literal', value: null };
|
||||
const reactive_store_subscriptions = reactive_stores
|
||||
.filter((store) => {
|
||||
const variable = component.var_lookup.get(store.name.slice(1));
|
||||
return !variable || variable.hoistable;
|
||||
})
|
||||
.map(
|
||||
({ name }) => b`
|
||||
${component.compile_options.dev && b`@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
|
||||
@component_subscribe($$self, ${name.slice(1)}, $$value => $$invalidate(${
|
||||
renderer.context_lookup.get(name).index
|
||||
}, ${name} = $$value));
|
||||
`
|
||||
);
|
||||
const resubscribable_reactive_store_unsubscribers = reactive_stores
|
||||
.filter((store) => {
|
||||
const variable = component.var_lookup.get(store.name.slice(1));
|
||||
return variable && (variable.reassigned || variable.export_name);
|
||||
})
|
||||
.map(({ name }) => b`$$self.$$.on_destroy.push(() => ${`$$unsubscribe_${name.slice(1)}`}());`);
|
||||
if (has_definition) {
|
||||
/** @type {import('estree').Node | import('estree').Node[]} */
|
||||
const reactive_declarations = [];
|
||||
|
||||
/** @type {import('estree').Node[]} */
|
||||
const fixed_reactive_declarations = []; // not really 'reactive' but whatever
|
||||
component.reactive_declarations.forEach((d) => {
|
||||
const dependencies = Array.from(d.dependencies);
|
||||
const uses_rest_or_props = !!dependencies.find((n) => n === '$$props' || n === '$$restProps');
|
||||
const writable = dependencies.filter((n) => {
|
||||
const variable = component.var_lookup.get(n);
|
||||
return variable && (variable.export_name || variable.mutated || variable.reassigned);
|
||||
});
|
||||
const condition =
|
||||
!uses_rest_or_props && writable.length > 0 && renderer.dirty(writable, true);
|
||||
let statement = d.node; // TODO remove label (use d.node.body) if it's not referenced
|
||||
if (condition)
|
||||
statement = /** @type {import('estree').Statement} */ (
|
||||
b`if (${condition}) { ${statement} }`[0]
|
||||
);
|
||||
if (condition || uses_rest_or_props) {
|
||||
reactive_declarations.push(statement);
|
||||
} else {
|
||||
fixed_reactive_declarations.push(statement);
|
||||
}
|
||||
});
|
||||
const injected = Array.from(component.injected_reactive_declaration_vars).filter((name) => {
|
||||
const variable = component.var_lookup.get(name);
|
||||
return variable.injected && variable.name[0] !== '$';
|
||||
});
|
||||
const reactive_store_declarations = reactive_stores.map((variable) => {
|
||||
const $name = variable.name;
|
||||
const name = $name.slice(1);
|
||||
const store = component.var_lookup.get(name);
|
||||
if (store && (store.reassigned || store.export_name)) {
|
||||
const unsubscribe = `$$unsubscribe_${name}`;
|
||||
const subscribe = `$$subscribe_${name}`;
|
||||
const i = renderer.context_lookup.get($name).index;
|
||||
return b`let ${$name}, ${unsubscribe} = @noop, ${subscribe} = () => (${unsubscribe}(), ${unsubscribe} = @subscribe(${name}, $$value => $$invalidate(${i}, ${$name} = $$value)), ${name})`;
|
||||
}
|
||||
return b`let ${$name};`;
|
||||
});
|
||||
|
||||
/** @type {import('estree').Node[] | undefined} */
|
||||
let unknown_props_check;
|
||||
if (component.compile_options.dev && !(uses_props || uses_rest)) {
|
||||
unknown_props_check = b`
|
||||
const writable_props = [${writable_props.map((prop) => x`'${prop.export_name}'`)}];
|
||||
@_Object.keys($$props).forEach(key => {
|
||||
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') @_console.warn(\`<${
|
||||
component.tag
|
||||
}> was created with unknown prop '\${key}'\`);
|
||||
});
|
||||
`;
|
||||
}
|
||||
const return_value = {
|
||||
type: 'ArrayExpression',
|
||||
elements: renderer.initial_context.map(
|
||||
(member) =>
|
||||
/** @type {import('estree').Expression} */ ({
|
||||
type: 'Identifier',
|
||||
name: member.name
|
||||
})
|
||||
)
|
||||
};
|
||||
body.push(b`
|
||||
function ${definition}(${args}) {
|
||||
${injected.map((name) => b`let ${name};`)}
|
||||
|
||||
${rest}
|
||||
|
||||
${reactive_store_declarations}
|
||||
|
||||
${reactive_store_subscriptions}
|
||||
|
||||
${resubscribable_reactive_store_unsubscribers}
|
||||
|
||||
${
|
||||
component.slots.size || component.compile_options.dev || uses_slots
|
||||
? b`let { $$slots: #slots = {}, $$scope } = $$props;`
|
||||
: null
|
||||
}
|
||||
${
|
||||
component.compile_options.dev &&
|
||||
b`@validate_slots('${component.tag}', #slots, [${[...component.slots.keys()]
|
||||
.map((key) => `'${key}'`)
|
||||
.join(',')}]);`
|
||||
}
|
||||
${compute_slots}
|
||||
|
||||
${instance_javascript}
|
||||
|
||||
${missing_props_check}
|
||||
${unknown_props_check}
|
||||
|
||||
${
|
||||
renderer.binding_groups.size > 0 &&
|
||||
b`const $$binding_groups = [${[...renderer.binding_groups.keys()].map((_) => x`[]`)}];`
|
||||
}
|
||||
|
||||
${component.partly_hoisted}
|
||||
|
||||
${set && b`$$self.$$set = ${set};`}
|
||||
|
||||
${capture_state && b`$$self.$capture_state = ${capture_state};`}
|
||||
|
||||
${inject_state && b`$$self.$inject_state = ${inject_state};`}
|
||||
|
||||
${/* before reactive declarations */ props_inject}
|
||||
|
||||
${
|
||||
reactive_declarations.length > 0 &&
|
||||
b`
|
||||
$$self.$$.update = () => {
|
||||
${reactive_declarations}
|
||||
};
|
||||
`
|
||||
}
|
||||
|
||||
${fixed_reactive_declarations}
|
||||
|
||||
${uses_props && b`$$props = @exclude_internal_props($$props);`}
|
||||
|
||||
return ${return_value};
|
||||
}
|
||||
`);
|
||||
}
|
||||
const prop_indexes = /** @type {import('estree').ObjectExpression} */ (
|
||||
x`{
|
||||
${props
|
||||
.filter((v) => v.export_name && !v.module)
|
||||
.map((v) => p`${v.export_name}: ${renderer.context_lookup.get(v.name).index}`)}
|
||||
}`
|
||||
);
|
||||
let dirty;
|
||||
if (renderer.context_overflow) {
|
||||
dirty = x`[]`;
|
||||
for (let i = 0; i < renderer.context.length; i += 31) {
|
||||
/** @type {any} */ (dirty).elements.push(x`-1`);
|
||||
}
|
||||
}
|
||||
const superclass = {
|
||||
type: 'Identifier',
|
||||
name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
|
||||
};
|
||||
const optional_parameters = [];
|
||||
if (should_add_css) {
|
||||
optional_parameters.push(add_css);
|
||||
} else if (dirty) {
|
||||
optional_parameters.push(x`null`);
|
||||
}
|
||||
if (dirty) {
|
||||
optional_parameters.push(dirty);
|
||||
}
|
||||
const declaration = /** @type {import('estree').ClassDeclaration} */ (
|
||||
b`
|
||||
class ${name} extends ${superclass} {
|
||||
constructor(options) {
|
||||
super(${options.dev && 'options'});
|
||||
@init(this, options, ${definition}, ${
|
||||
has_create_fragment ? 'create_fragment' : 'null'
|
||||
}, ${not_equal}, ${prop_indexes}, ${optional_parameters});
|
||||
${
|
||||
options.dev &&
|
||||
b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`
|
||||
}
|
||||
}
|
||||
}
|
||||
`[0]
|
||||
);
|
||||
push_array(declaration.body.body, accessors);
|
||||
body.push(/** @type {any} */ (declaration));
|
||||
if (options.customElement) {
|
||||
const props_str = writable_props.reduce((def, prop) => {
|
||||
def[prop.export_name] =
|
||||
component.component_options.customElement?.props?.[prop.export_name] || {};
|
||||
if (prop.is_boolean && !def[prop.export_name].type) {
|
||||
def[prop.export_name].type = 'Boolean';
|
||||
}
|
||||
return def;
|
||||
}, {});
|
||||
const slots_str = [...component.slots.keys()].map((key) => `"${key}"`).join(',');
|
||||
const accessors_str = accessors
|
||||
.filter(
|
||||
(accessor) =>
|
||||
accessor.kind === 'get' &&
|
||||
!writable_props.some((prop) => prop.export_name === accessor.key.name)
|
||||
)
|
||||
.map((accessor) => `"${accessor.key.name}"`)
|
||||
.join(',');
|
||||
const use_shadow_dom =
|
||||
component.component_options.customElement?.shadow !== 'none' ? 'true' : 'false';
|
||||
|
||||
const create_ce = x`@create_custom_element(${name}, ${JSON.stringify(
|
||||
props_str
|
||||
)}, [${slots_str}], [${accessors_str}], ${use_shadow_dom}, ${
|
||||
component.component_options.customElement?.extend
|
||||
})`;
|
||||
|
||||
if (component.component_options.customElement?.tag) {
|
||||
body.push(
|
||||
b`@_customElements.define("${component.component_options.customElement.tag}", ${create_ce});`
|
||||
);
|
||||
} else {
|
||||
body.push(b`${create_ce}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.discloseVersion === true) {
|
||||
component.imports.unshift({
|
||||
type: 'ImportDeclaration',
|
||||
specifiers: [],
|
||||
source: {
|
||||
type: 'Literal',
|
||||
value: `${options.sveltePath ?? 'svelte'}/internal/disclose-version`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return { js: flatten(body), css };
|
||||
}
|
147
node_modules/svelte/src/compiler/compile/render_dom/invalidate.js
generated
vendored
Normal file
147
node_modules/svelte/src/compiler/compile/render_dom/invalidate.js
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
import { nodes_match } from '../../utils/nodes_match.js';
|
||||
import { x } from 'code-red';
|
||||
|
||||
/**
|
||||
* @param {import('./Renderer.js').default} renderer
|
||||
* @param {import('periscopic').Scope} scope
|
||||
* @param {import('estree').Node} node
|
||||
* @param {Set<string>} names
|
||||
* @param {boolean} main_execution_context
|
||||
* @returns {any}
|
||||
*/
|
||||
export function invalidate(renderer, scope, node, names, main_execution_context = false) {
|
||||
const { component } = renderer;
|
||||
const [head, ...tail] = /** @type {import('../../interfaces.js').Var[]} */ (
|
||||
Array.from(names)
|
||||
.filter((name) => {
|
||||
const owner = scope.find_owner(name);
|
||||
return !owner || owner === component.instance_scope;
|
||||
})
|
||||
.map((name) => component.var_lookup.get(name))
|
||||
.filter((variable) => {
|
||||
return (
|
||||
variable &&
|
||||
!variable.hoistable &&
|
||||
!variable.global &&
|
||||
!variable.module &&
|
||||
(variable.referenced ||
|
||||
variable.subscribable ||
|
||||
variable.is_reactive_dependency ||
|
||||
variable.export_name ||
|
||||
variable.name[0] === '$')
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {import('../../interfaces.js').Var} variable
|
||||
* @param {import('estree').Expression} [node]
|
||||
*/
|
||||
function get_invalidated(variable, node) {
|
||||
if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
|
||||
return node;
|
||||
}
|
||||
return renderer_invalidate(renderer, variable.name, undefined, main_execution_context);
|
||||
}
|
||||
if (!head) {
|
||||
return node;
|
||||
}
|
||||
component.has_reactive_assignments = true;
|
||||
if (
|
||||
node.type === 'AssignmentExpression' &&
|
||||
node.operator === '=' &&
|
||||
nodes_match(node.left, node.right, ['trailingComments', 'leadingComments']) &&
|
||||
tail.length === 0
|
||||
) {
|
||||
return get_invalidated(head, node);
|
||||
}
|
||||
const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
|
||||
const extra_args = tail.map((variable) => get_invalidated(variable)).filter(Boolean);
|
||||
if (is_store_value) {
|
||||
return x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`;
|
||||
}
|
||||
|
||||
let invalidate;
|
||||
if (!main_execution_context) {
|
||||
const pass_value =
|
||||
extra_args.length > 0 ||
|
||||
(node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
|
||||
(node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'));
|
||||
if (pass_value) {
|
||||
extra_args.unshift({
|
||||
type: 'Identifier',
|
||||
name: head.name
|
||||
});
|
||||
}
|
||||
invalidate = x`$$invalidate(${
|
||||
renderer.context_lookup.get(head.name).index
|
||||
}, ${node}, ${extra_args})`;
|
||||
} else {
|
||||
// skip `$$invalidate` if it is in the main execution context
|
||||
invalidate = extra_args.length ? [node, ...extra_args] : node;
|
||||
}
|
||||
if (head.subscribable && head.reassigned) {
|
||||
const subscribe = `$$subscribe_${head.name}`;
|
||||
invalidate = x`${subscribe}(${invalidate})`;
|
||||
}
|
||||
return invalidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./Renderer.js').default} renderer
|
||||
* @param {string} name
|
||||
* @param {any} [value]
|
||||
* @param {boolean} [main_execution_context]
|
||||
* @returns {import('estree').Node}
|
||||
*/
|
||||
export function renderer_invalidate(renderer, name, value, main_execution_context = false) {
|
||||
const variable = renderer.component.var_lookup.get(name);
|
||||
if (variable && variable.subscribable && (variable.reassigned || variable.export_name)) {
|
||||
if (main_execution_context) {
|
||||
return x`${`$$subscribe_${name}`}(${value || name})`;
|
||||
} else {
|
||||
const member = renderer.context_lookup.get(name);
|
||||
return x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
|
||||
}
|
||||
}
|
||||
if (name[0] === '$' && name[1] !== '$') {
|
||||
return x`${name.slice(1)}.set(${value || name})`;
|
||||
}
|
||||
if (
|
||||
variable &&
|
||||
(variable.module ||
|
||||
(!variable.referenced &&
|
||||
!variable.is_reactive_dependency &&
|
||||
!variable.export_name &&
|
||||
!name.startsWith('$$')))
|
||||
) {
|
||||
return value || name;
|
||||
}
|
||||
if (value) {
|
||||
if (main_execution_context) {
|
||||
return x`${value}`;
|
||||
} else {
|
||||
const member = renderer.context_lookup.get(name);
|
||||
return x`$$invalidate(${member.index}, ${value})`;
|
||||
}
|
||||
}
|
||||
if (main_execution_context) return;
|
||||
// if this is a reactive declaration, invalidate dependencies recursively
|
||||
const deps = new Set([name]);
|
||||
deps.forEach((name) => {
|
||||
const reactive_declarations = renderer.component.reactive_declarations.filter((x) =>
|
||||
x.assignees.has(name)
|
||||
);
|
||||
reactive_declarations.forEach((declaration) => {
|
||||
declaration.dependencies.forEach((name) => {
|
||||
deps.add(name);
|
||||
});
|
||||
});
|
||||
});
|
||||
// TODO ideally globals etc wouldn't be here in the first place
|
||||
const filtered = Array.from(deps).filter((n) => renderer.context_lookup.has(n));
|
||||
if (!filtered.length) return null;
|
||||
return filtered
|
||||
.map((n) => x`$$invalidate(${renderer.context_lookup.get(n).index}, ${n})`)
|
||||
.reduce((lhs, rhs) => x`${lhs}, ${rhs}`);
|
||||
}
|
307
node_modules/svelte/src/compiler/compile/render_dom/wrappers/AwaitBlock.js
generated
vendored
Normal file
307
node_modules/svelte/src/compiler/compile/render_dom/wrappers/AwaitBlock.js
generated
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import create_debugging_comment from './shared/create_debugging_comment.js';
|
||||
import { b, x } from 'code-red';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import ThenBlock from '../../nodes/ThenBlock.js';
|
||||
import CatchBlock from '../../nodes/CatchBlock.js';
|
||||
import { add_const_tags, add_const_tags_context } from './shared/add_const_tags.js';
|
||||
import Expression from '../../nodes/shared/Expression.js';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default> */
|
||||
class AwaitBlockBranch extends Wrapper {
|
||||
/** @typedef {'pending' | 'then' | 'catch'} Status */
|
||||
|
||||
/** @type {import('../Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_dynamic;
|
||||
|
||||
var = null;
|
||||
|
||||
/** @type {Status} */
|
||||
status;
|
||||
|
||||
/** @type {string} */
|
||||
value;
|
||||
|
||||
/** @type {import('estree').Literal} */
|
||||
value_index;
|
||||
|
||||
/** @type {import('../../nodes/shared/Context.js').Context[]} */
|
||||
value_contexts;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_destructured;
|
||||
|
||||
/**
|
||||
* @param {Status} status
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {AwaitBlockWrapper} parent
|
||||
* @param {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(status, renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
this.status = status;
|
||||
this.block = block.child({
|
||||
comment: create_debugging_comment(node, this.renderer.component),
|
||||
name: this.renderer.component.get_unique_name(`create_${status}_block`),
|
||||
type: status
|
||||
});
|
||||
this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']);
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.block,
|
||||
this.node.children,
|
||||
parent,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
this.is_dynamic = this.block.dependencies.size > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('estree').Node | null} node
|
||||
* @param {import('../../nodes/shared/Context.js').Context[]} contexts
|
||||
*/
|
||||
add_context(node, contexts) {
|
||||
if (!node) return;
|
||||
if (node.type === 'Identifier') {
|
||||
this.value = node.name;
|
||||
this.renderer.add_to_context(this.value, true);
|
||||
} else {
|
||||
contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
this.renderer.add_to_context(context.key.name, true);
|
||||
});
|
||||
this.value = this.block.parent.get_unique_name('value').name;
|
||||
this.value_contexts = contexts;
|
||||
this.renderer.add_to_context(this.value, true);
|
||||
this.is_destructured = true;
|
||||
}
|
||||
this.value_index = this.renderer.context_lookup.get(this.value).index;
|
||||
if (this.has_consts(this.node)) {
|
||||
add_const_tags_context(this.renderer, this.node.const_tags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../nodes/PendingBlock.js').default | import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default} node
|
||||
* @returns {node is import('../../nodes/ThenBlock.js').default | import('../../nodes/CatchBlock.js').default}
|
||||
*/
|
||||
has_consts(node) {
|
||||
return node instanceof ThenBlock || node instanceof CatchBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
this.fragment.render(block, parent_node, parent_nodes);
|
||||
if (this.is_destructured || (this.has_consts(this.node) && this.node.const_tags.length > 0)) {
|
||||
this.render_get_context();
|
||||
}
|
||||
}
|
||||
render_get_context() {
|
||||
const props = this.is_destructured
|
||||
? this.value_contexts.map((prop) => {
|
||||
if (prop.type === 'ComputedProperty') {
|
||||
const expression = new Expression(
|
||||
this.renderer.component,
|
||||
this.node,
|
||||
this.has_consts(this.node) ? this.node.scope : null,
|
||||
prop.key
|
||||
);
|
||||
return b`const ${prop.property_name} = ${expression.manipulate(this.block, '#ctx')};`;
|
||||
} else {
|
||||
/** @param {any} name */
|
||||
const to_ctx = (name) => this.renderer.reference(name);
|
||||
return b`#ctx[${
|
||||
this.block.renderer.context_lookup.get(prop.key.name).index
|
||||
}] = ${prop.default_modifier(prop.modifier(x`#ctx[${this.value_index}]`), to_ctx)};`;
|
||||
}
|
||||
})
|
||||
: null;
|
||||
const const_tags_props = this.has_consts(this.node)
|
||||
? add_const_tags(this.block, this.node.const_tags, '#ctx')
|
||||
: null;
|
||||
const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`);
|
||||
this.block.renderer.blocks.push(b`
|
||||
function ${get_context}(#ctx) {
|
||||
${props}
|
||||
${const_tags_props}
|
||||
}
|
||||
`);
|
||||
this.block.chunks.declarations.push(b`${get_context}(#ctx)`);
|
||||
if (this.block.has_update_method) {
|
||||
this.block.chunks.update.unshift(b`${get_context}(#ctx)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/AwaitBlock.js').default> */
|
||||
export default class AwaitBlockWrapper extends Wrapper {
|
||||
/** @type {AwaitBlockBranch} */
|
||||
pending;
|
||||
|
||||
/** @type {AwaitBlockBranch} */
|
||||
then;
|
||||
|
||||
/** @type {AwaitBlockBranch} */
|
||||
catch;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 'await_block' };
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/AwaitBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
block.add_dependencies(this.node.expression.dependencies);
|
||||
let is_dynamic = false;
|
||||
let has_intros = false;
|
||||
let has_outros = false;
|
||||
/** @type {const} */ (['pending', 'then', 'catch']).forEach((status) => {
|
||||
const child = this.node[status];
|
||||
const branch = new AwaitBlockBranch(
|
||||
status,
|
||||
renderer,
|
||||
block,
|
||||
this,
|
||||
child,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
renderer.blocks.push(branch.block);
|
||||
if (branch.is_dynamic) {
|
||||
is_dynamic = true;
|
||||
// TODO should blocks update their own parents?
|
||||
block.add_dependencies(branch.block.dependencies);
|
||||
}
|
||||
if (branch.block.has_intros) has_intros = true;
|
||||
if (branch.block.has_outros) has_outros = true;
|
||||
this[status] = branch;
|
||||
});
|
||||
['pending', 'then', 'catch'].forEach((status) => {
|
||||
this[status].block.has_update_method = is_dynamic;
|
||||
this[status].block.has_intro_method = has_intros;
|
||||
this[status].block.has_outro_method = has_outros;
|
||||
});
|
||||
if (has_outros) {
|
||||
block.add_outro();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
|
||||
const update_mount_node = this.get_update_mount_node(anchor);
|
||||
const snippet = this.node.expression.manipulate(block);
|
||||
const info = block.get_unique_name('info');
|
||||
const promise = block.get_unique_name('promise');
|
||||
block.add_variable(promise);
|
||||
block.maintain_context = true;
|
||||
|
||||
/** @type {any} */
|
||||
const info_props = x`{
|
||||
ctx: #ctx,
|
||||
current: null,
|
||||
token: null,
|
||||
hasCatch: ${this.catch.node.start !== null ? 'true' : 'false'},
|
||||
pending: ${this.pending.block.name},
|
||||
then: ${this.then.block.name},
|
||||
catch: ${this.catch.block.name},
|
||||
value: ${this.then.value_index},
|
||||
error: ${this.catch.value_index},
|
||||
blocks: ${this.pending.block.has_outro_method && x`[,,,]`}
|
||||
}`;
|
||||
block.chunks.init.push(b`
|
||||
let ${info} = ${info_props};
|
||||
`);
|
||||
block.chunks.init.push(b`
|
||||
@handle_promise(${promise} = ${snippet}, ${info});
|
||||
`);
|
||||
block.chunks.create.push(b`
|
||||
${info}.block.c();
|
||||
`);
|
||||
if (parent_nodes && this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`
|
||||
${info}.block.l(${parent_nodes});
|
||||
`);
|
||||
}
|
||||
const initial_mount_node = parent_node || '#target';
|
||||
const anchor_node = parent_node ? 'null' : '#anchor';
|
||||
const has_transitions =
|
||||
this.pending.block.has_intro_method || this.pending.block.has_outro_method;
|
||||
block.chunks.mount.push(b`
|
||||
${info}.block.m(${initial_mount_node}, ${info}.anchor = ${anchor_node});
|
||||
${info}.mount = () => ${update_mount_node};
|
||||
${info}.anchor = ${anchor};
|
||||
`);
|
||||
if (has_transitions) {
|
||||
block.chunks.intro.push(b`@transition_in(${info}.block);`);
|
||||
}
|
||||
const dependencies = this.node.expression.dynamic_dependencies();
|
||||
const update_await_block_branch = b`@update_await_block_branch(${info}, #ctx, #dirty)`;
|
||||
if (dependencies.length > 0) {
|
||||
const condition = x`
|
||||
${block.renderer.dirty(dependencies)} &&
|
||||
${promise} !== (${promise} = ${snippet}) &&
|
||||
@handle_promise(${promise}, ${info})`;
|
||||
block.chunks.update.push(b`${info}.ctx = #ctx;`);
|
||||
if (this.pending.block.has_update_method) {
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
|
||||
} else {
|
||||
${update_await_block_branch}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(b`
|
||||
${condition}
|
||||
`);
|
||||
}
|
||||
} else {
|
||||
if (this.pending.block.has_update_method) {
|
||||
block.chunks.update.push(b`
|
||||
${update_await_block_branch}
|
||||
`);
|
||||
}
|
||||
}
|
||||
if (this.pending.block.has_outro_method) {
|
||||
block.chunks.outro.push(b`
|
||||
for (let #i = 0; #i < 3; #i += 1) {
|
||||
const block = ${info}.blocks[#i];
|
||||
@transition_out(block);
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.destroy.push(b`
|
||||
${info}.block.d(${parent_node ? null : 'detaching'});
|
||||
${info}.token = null;
|
||||
${info} = null;
|
||||
`);
|
||||
[this.pending, this.then, this.catch].forEach((branch) => {
|
||||
branch.render(branch.block, null, /** @type {import('estree').Identifier} */ (x`#nodes`));
|
||||
});
|
||||
}
|
||||
}
|
32
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Body.js
generated
vendored
Normal file
32
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Body.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import { x } from 'code-red';
|
||||
import EventHandler from './Element/EventHandler.js';
|
||||
import add_event_handlers from './shared/add_event_handlers.js';
|
||||
import add_actions from './shared/add_actions.js';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Body.js').default> */
|
||||
export default class BodyWrapper extends Wrapper {
|
||||
/** @type {import('./Element/EventHandler.js').default[]} */
|
||||
handlers;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Body.js').default} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
this.handlers = this.node.handlers.map((handler) => new EventHandler(handler, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, _parent_node, _parent_nodes) {
|
||||
add_event_handlers(block, x`@_document.body`, this.handlers);
|
||||
add_actions(block, x`@_document.body`, this.node.actions);
|
||||
}
|
||||
}
|
43
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Comment.js
generated
vendored
Normal file
43
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Comment.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import { x } from 'code-red';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Comment.js').default> */
|
||||
export default class CommentWrapper extends Wrapper {
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Comment.js').default} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
this.var = /** @type {import('estree').Identifier} */ (x`c`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
if (!this.renderer.options.preserveComments) return;
|
||||
const string_literal = {
|
||||
type: 'Literal',
|
||||
value: this.node.data,
|
||||
loc: {
|
||||
start: this.renderer.locate(this.node.start),
|
||||
end: this.renderer.locate(this.node.end)
|
||||
}
|
||||
};
|
||||
block.add_element(
|
||||
this.var,
|
||||
x`@comment(${string_literal})`,
|
||||
parent_nodes && x`@claim_comment(${parent_nodes}, ${string_literal})`,
|
||||
parent_node
|
||||
);
|
||||
}
|
||||
text() {
|
||||
if (!this.renderer.options.preserveComments) return '';
|
||||
return `<!--${this.node.data}-->`;
|
||||
}
|
||||
}
|
81
node_modules/svelte/src/compiler/compile/render_dom/wrappers/DebugTag.js
generated
vendored
Normal file
81
node_modules/svelte/src/compiler/compile/render_dom/wrappers/DebugTag.js
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import add_to_set from '../../utils/add_to_set.js';
|
||||
import { b, p } from 'code-red';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/DebugTag.js').default> */
|
||||
export default class DebugTagWrapper extends Wrapper {
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/DebugTag.js').default} node
|
||||
* @param {boolean} _strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} _next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, _parent_node, _parent_nodes) {
|
||||
const { renderer } = this;
|
||||
const { component } = renderer;
|
||||
if (!renderer.options.dev) return;
|
||||
const { var_lookup } = component;
|
||||
const start = component.locate(this.node.start + 1);
|
||||
const end = { line: start.line, column: start.column + 6 };
|
||||
const loc = { start, end };
|
||||
|
||||
/** @type {import('estree').DebuggerStatement} */
|
||||
const debug = {
|
||||
type: 'DebuggerStatement',
|
||||
loc
|
||||
};
|
||||
if (this.node.expressions.length === 0) {
|
||||
// Debug all
|
||||
block.chunks.create.push(debug);
|
||||
block.chunks.update.push(debug);
|
||||
} else {
|
||||
/** @type {import('estree').Identifier} */
|
||||
const log = {
|
||||
type: 'Identifier',
|
||||
name: 'log',
|
||||
loc
|
||||
};
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const dependencies = new Set();
|
||||
this.node.expressions.forEach((expression) => {
|
||||
add_to_set(dependencies, expression.dependencies);
|
||||
});
|
||||
const contextual_identifiers = this.node.expressions
|
||||
.filter((e) => {
|
||||
const variable = var_lookup.get(/** @type {import('estree').Identifier} */ (e.node).name);
|
||||
return !(variable && variable.hoistable);
|
||||
})
|
||||
.map((e) => /** @type {import('estree').Identifier} */ (e.node).name);
|
||||
const logged_identifiers = this.node.expressions.map(
|
||||
(e) => p`${/** @type {import('estree').Identifier} */ (e.node).name}`
|
||||
);
|
||||
const debug_statements = b`
|
||||
${contextual_identifiers.map((name) => b`const ${name} = ${renderer.reference(name)};`)}
|
||||
@_console.${log}({ ${logged_identifiers} });
|
||||
debugger;`;
|
||||
if (dependencies.size) {
|
||||
const condition = renderer.dirty(Array.from(dependencies));
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${debug_statements}
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.create.push(b`{
|
||||
${debug_statements}
|
||||
}`);
|
||||
}
|
||||
}
|
||||
}
|
86
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Document.js
generated
vendored
Normal file
86
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Document.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import { b, x } from 'code-red';
|
||||
import EventHandler from './Element/EventHandler.js';
|
||||
import add_event_handlers from './shared/add_event_handlers.js';
|
||||
import add_actions from './shared/add_actions.js';
|
||||
|
||||
const associated_events = {
|
||||
fullscreenElement: ['fullscreenchange'],
|
||||
visibilityState: ['visibilitychange']
|
||||
};
|
||||
const readonly = new Set(['fullscreenElement', 'visibilityState']);
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Document.js').default> */
|
||||
export default class DocumentWrapper extends Wrapper {
|
||||
/** @type {import('./Element/EventHandler.js').default[]} */
|
||||
handlers;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Document.js').default} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
this.handlers = this.node.handlers.map((handler) => new EventHandler(handler, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, _parent_node, _parent_nodes) {
|
||||
const { renderer } = this;
|
||||
const { component } = renderer;
|
||||
|
||||
/** @type {Record<string, Array<{ name: string; value: string }>>} */
|
||||
const events = {};
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
const bindings = {};
|
||||
add_event_handlers(block, x`@_document`, this.handlers);
|
||||
add_actions(block, x`@_document`, this.node.actions);
|
||||
this.node.bindings.forEach((binding) => {
|
||||
// TODO: what if it's a MemberExpression?
|
||||
const binding_name = /** @type {import('estree').Identifier} */ (binding.expression.node)
|
||||
.name;
|
||||
// in dev mode, throw if read-only values are written to
|
||||
if (readonly.has(binding.name)) {
|
||||
renderer.readonly.add(binding_name);
|
||||
}
|
||||
bindings[binding.name] = binding_name;
|
||||
const binding_events = associated_events[binding.name];
|
||||
const property = binding.name;
|
||||
binding_events.forEach((associated_event) => {
|
||||
if (!events[associated_event]) events[associated_event] = [];
|
||||
events[associated_event].push({
|
||||
name: binding_name,
|
||||
value: property
|
||||
});
|
||||
});
|
||||
});
|
||||
Object.keys(events).forEach((event) => {
|
||||
const id = block.get_unique_name(`ondocument${event}`);
|
||||
const props = events[event];
|
||||
renderer.add_to_context(id.name);
|
||||
const fn = renderer.reference(id.name);
|
||||
props.forEach((prop) => {
|
||||
renderer.meta_bindings.push(b`this._state.${prop.name} = @_document.${prop.value};`);
|
||||
});
|
||||
block.event_listeners.push(x`
|
||||
@listen(@_document, "${event}", ${fn})
|
||||
`);
|
||||
component.partly_hoisted.push(b`
|
||||
function ${id}() {
|
||||
${props.map((prop) => renderer.invalidate(prop.name, x`${prop.name} = @_document.${prop.value}`))}
|
||||
}
|
||||
`);
|
||||
block.chunks.init.push(b`
|
||||
@add_render_callback(${fn});
|
||||
`);
|
||||
component.has_reactive_assignments = true;
|
||||
});
|
||||
}
|
||||
}
|
649
node_modules/svelte/src/compiler/compile/render_dom/wrappers/EachBlock.js
generated
vendored
Normal file
649
node_modules/svelte/src/compiler/compile/render_dom/wrappers/EachBlock.js
generated
vendored
Normal file
@ -0,0 +1,649 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import create_debugging_comment from './shared/create_debugging_comment.js';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import { b, x } from 'code-red';
|
||||
import get_object from '../../utils/get_object.js';
|
||||
import { add_const_tags, add_const_tags_context } from './shared/add_const_tags.js';
|
||||
import Expression from '../../nodes/shared/Expression.js';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/ElseBlock.js').default> */
|
||||
export class ElseBlockWrapper extends Wrapper {
|
||||
/** @type {import('../Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_dynamic;
|
||||
|
||||
var = null;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/ElseBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
add_const_tags_context(renderer, this.node.const_tags);
|
||||
this.block = block.child({
|
||||
comment: create_debugging_comment(node, this.renderer.component),
|
||||
name: this.renderer.component.get_unique_name('create_else_block'),
|
||||
type: 'else'
|
||||
});
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.block,
|
||||
this.node.children,
|
||||
parent,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
this.is_dynamic = this.block.dependencies.size > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/EachBlock.js').default> */
|
||||
export default class EachBlockWrapper extends Wrapper {
|
||||
/** @type {import('../Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {ElseBlockWrapper} */
|
||||
else;
|
||||
/**
|
||||
* @type {{
|
||||
* create_each_block: import('estree').Identifier;
|
||||
* each_block_value: import('estree').Identifier;
|
||||
* get_each_context: import('estree').Identifier;
|
||||
* iterations: import('estree').Identifier;
|
||||
* fixed_length: number;
|
||||
* data_length: import('estree').Node | number;
|
||||
* view_length: import('estree').Node | number;
|
||||
* }}
|
||||
*/
|
||||
vars;
|
||||
|
||||
/** @type {Array<import('estree').Node | import('estree').Node[]>} */
|
||||
context_props;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
index_name;
|
||||
|
||||
/** @type {Array<import('estree').Node | import('estree').Node[]>} */
|
||||
updates = [];
|
||||
|
||||
/** @type {Set<string>} */
|
||||
dependencies;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 'each' };
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/EachBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
const { dependencies } = node.expression;
|
||||
block.add_dependencies(dependencies);
|
||||
this.node.contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
renderer.add_to_context(context.key.name, true);
|
||||
});
|
||||
add_const_tags_context(renderer, this.node.const_tags);
|
||||
this.block = block.child({
|
||||
comment: create_debugging_comment(this.node, this.renderer.component),
|
||||
name: renderer.component.get_unique_name('create_each_block'),
|
||||
type: 'each',
|
||||
// @ts-ignore todo: probably error
|
||||
key: /** @type {string} */ (node.key),
|
||||
bindings: new Map(block.bindings)
|
||||
});
|
||||
// TODO this seems messy
|
||||
this.block.has_animation = this.node.has_animation;
|
||||
this.index_name = this.node.index
|
||||
? { 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,
|
||||
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
|
||||
};
|
||||
const object = get_object(node.expression.node);
|
||||
const store =
|
||||
object.type === 'Identifier' && object.name[0] === '$' ? object.name.slice(1) : null;
|
||||
node.contexts.forEach((prop) => {
|
||||
if (prop.type !== 'DestructuredVariable') return;
|
||||
this.block.bindings.set(prop.key.name, {
|
||||
object: this.vars.each_block_value,
|
||||
property: this.index_name,
|
||||
modifier: prop.modifier,
|
||||
snippet: prop.modifier(
|
||||
/** @type {import('estree').Node} */ (
|
||||
x`${this.vars.each_block_value}[${this.index_name}]`
|
||||
)
|
||||
),
|
||||
store
|
||||
});
|
||||
});
|
||||
if (this.node.index) {
|
||||
this.block.get_unique_name(this.node.index); // this prevents name collisions (#1254)
|
||||
}
|
||||
renderer.blocks.push(this.block);
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.block,
|
||||
node.children,
|
||||
this,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
if (this.node.else) {
|
||||
this.else = new ElseBlockWrapper(
|
||||
renderer,
|
||||
block,
|
||||
this,
|
||||
this.node.else,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
renderer.blocks.push(this.else.block);
|
||||
if (this.else.is_dynamic) {
|
||||
this.block.add_dependencies(this.else.block.dependencies);
|
||||
}
|
||||
}
|
||||
block.add_dependencies(this.block.dependencies);
|
||||
if (this.block.has_outros || (this.else && this.else.block.has_outros)) {
|
||||
block.add_outro();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
if (this.fragment.nodes.length === 0) return;
|
||||
const { renderer } = this;
|
||||
const { component } = renderer;
|
||||
const needs_anchor = this.next
|
||||
? !this.next.is_dom_node()
|
||||
: !parent_node || !this.parent.is_dom_node();
|
||||
const snippet = x`@ensure_array_like(${this.node.expression.manipulate(block)})`;
|
||||
block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`);
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
const initial_anchor_node = {
|
||||
type: 'Identifier',
|
||||
name: parent_node ? 'null' : '#anchor'
|
||||
};
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
const initial_mount_node = parent_node || { type: 'Identifier', name: '#target' };
|
||||
const update_anchor_node = needs_anchor
|
||||
? block.get_unique_name(`${this.var.name}_anchor`)
|
||||
: (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
const update_mount_node = this.get_update_mount_node(
|
||||
/** @type {import('estree').Identifier} */ (update_anchor_node)
|
||||
);
|
||||
const args = {
|
||||
block,
|
||||
parent_node,
|
||||
parent_nodes,
|
||||
snippet,
|
||||
initial_anchor_node,
|
||||
initial_mount_node,
|
||||
update_anchor_node,
|
||||
update_mount_node
|
||||
};
|
||||
const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only
|
||||
this.node.expression.dynamic_dependencies().forEach((dependency) => {
|
||||
all_dependencies.add(dependency);
|
||||
});
|
||||
if (this.node.key) {
|
||||
this.node.key.dynamic_dependencies().forEach((dependency) => {
|
||||
all_dependencies.add(dependency);
|
||||
});
|
||||
}
|
||||
this.dependencies = all_dependencies;
|
||||
if (this.node.key) {
|
||||
this.render_keyed(args);
|
||||
} else {
|
||||
this.render_unkeyed(args);
|
||||
}
|
||||
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]);
|
||||
}
|
||||
`);
|
||||
}
|
||||
if (needs_anchor) {
|
||||
block.add_element(
|
||||
/** @type {import('estree').Identifier} */ (update_anchor_node),
|
||||
x`@empty()`,
|
||||
parent_nodes && x`@empty()`,
|
||||
parent_node
|
||||
);
|
||||
}
|
||||
if (this.else) {
|
||||
let else_ctx = x`#ctx`;
|
||||
if (this.else.node.const_tags.length > 0) {
|
||||
const get_ctx_name = this.renderer.component.get_unique_name('get_else_ctx');
|
||||
this.renderer.blocks.push(b`
|
||||
function ${get_ctx_name}(#ctx) {
|
||||
const child_ctx = #ctx.slice();
|
||||
${add_const_tags(block, this.else.node.const_tags, 'child_ctx')}
|
||||
return child_ctx;
|
||||
}
|
||||
`);
|
||||
else_ctx = x`${get_ctx_name}(#ctx)`;
|
||||
}
|
||||
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}) {
|
||||
${each_block_else} = ${this.else.block.name}(${else_ctx});
|
||||
}
|
||||
`);
|
||||
block.chunks.create.push(b`
|
||||
if (${each_block_else}) {
|
||||
${each_block_else}.c();
|
||||
}
|
||||
`);
|
||||
if (this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`
|
||||
if (${each_block_else}) {
|
||||
${each_block_else}.l(${parent_nodes});
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.mount.push(b`
|
||||
if (${each_block_else}) {
|
||||
${each_block_else}.m(${initial_mount_node}, ${initial_anchor_node});
|
||||
}
|
||||
`);
|
||||
const has_transitions = !!(
|
||||
this.else.block.has_intro_method || this.else.block.has_outro_method
|
||||
);
|
||||
const destroy_block_else = this.else.block.has_outro_method
|
||||
? b`
|
||||
@group_outros();
|
||||
@transition_out(${each_block_else}, 1, 1, () => {
|
||||
${each_block_else} = null;
|
||||
});
|
||||
@check_outros();`
|
||||
: b`
|
||||
${each_block_else}.d(1);
|
||||
${each_block_else} = null;`;
|
||||
if (this.else.block.has_update_method) {
|
||||
this.updates.push(b`
|
||||
if (!${this.vars.data_length} && ${each_block_else}) {
|
||||
${each_block_else}.p(${else_ctx}, #dirty);
|
||||
} else if (!${this.vars.data_length}) {
|
||||
${each_block_else} = ${this.else.block.name}(${else_ctx});
|
||||
${each_block_else}.c();
|
||||
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
|
||||
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
|
||||
} else if (${each_block_else}) {
|
||||
${destroy_block_else};
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
this.updates.push(b`
|
||||
if (${this.vars.data_length}) {
|
||||
if (${each_block_else}) {
|
||||
${destroy_block_else};
|
||||
}
|
||||
} else if (!${each_block_else}) {
|
||||
${each_block_else} = ${this.else.block.name}(${else_ctx});
|
||||
${each_block_else}.c();
|
||||
${has_transitions && b`@transition_in(${each_block_else}, 1);`}
|
||||
${each_block_else}.m(${update_mount_node}, ${update_anchor_node});
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.destroy.push(b`
|
||||
if (${each_block_else}) ${each_block_else}.d(${parent_node ? '' : 'detaching'});
|
||||
`);
|
||||
}
|
||||
if (this.updates.length) {
|
||||
block.chunks.update.push(b`
|
||||
if (${block.renderer.dirty(Array.from(all_dependencies))}) {
|
||||
${this.updates}
|
||||
}
|
||||
`);
|
||||
}
|
||||
this.fragment.render(this.block, null, /** @type {import('estree').Identifier} */ (x`#nodes`));
|
||||
if (this.else) {
|
||||
this.else.fragment.render(
|
||||
this.else.block,
|
||||
null,
|
||||
/** @type {import('estree').Identifier} */ (x`#nodes`)
|
||||
);
|
||||
}
|
||||
this.context_props = this.node.contexts.map((prop) => {
|
||||
if (prop.type === 'DestructuredVariable') {
|
||||
/** @param {string} name */
|
||||
const to_ctx = (name) =>
|
||||
renderer.context_lookup.has(name)
|
||||
? x`child_ctx[${renderer.context_lookup.get(name).index}]`
|
||||
: /** @type {import('estree').Node} */ ({ type: 'Identifier', name });
|
||||
return b`child_ctx[${
|
||||
renderer.context_lookup.get(prop.key.name).index
|
||||
}] = ${prop.default_modifier(prop.modifier(x`list[i]`), to_ctx)};`;
|
||||
} else {
|
||||
const expression = new Expression(
|
||||
this.renderer.component,
|
||||
this.node,
|
||||
this.node.scope,
|
||||
prop.key
|
||||
);
|
||||
return b`const ${prop.property_name} = ${expression.manipulate(block, 'child_ctx')};`;
|
||||
}
|
||||
});
|
||||
if (this.node.has_binding)
|
||||
this.context_props.push(
|
||||
b`child_ctx[${renderer.context_lookup.get(this.vars.each_block_value.name).index}] = list;`
|
||||
);
|
||||
if (this.node.has_binding || this.node.has_index_binding || this.node.index)
|
||||
this.context_props.push(
|
||||
b`child_ctx[${renderer.context_lookup.get(this.index_name.name).index}] = i;`
|
||||
);
|
||||
// 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();
|
||||
${this.context_props}
|
||||
${add_const_tags(this.block, this.node.const_tags, 'child_ctx')}
|
||||
return child_ctx;
|
||||
}
|
||||
`);
|
||||
}
|
||||
/**
|
||||
* @param {{
|
||||
* block: import('../Block.js').default;
|
||||
* parent_node: import('estree').Identifier;
|
||||
* parent_nodes: import('estree').Identifier;
|
||||
* snippet: import('estree').Node;
|
||||
* initial_anchor_node: import('estree').Identifier;
|
||||
* initial_mount_node: import('estree').Identifier;
|
||||
* update_anchor_node: import('estree').Identifier;
|
||||
* update_mount_node: import('estree').Identifier;
|
||||
* }} params
|
||||
*/
|
||||
render_keyed({
|
||||
block,
|
||||
parent_node,
|
||||
parent_nodes,
|
||||
snippet,
|
||||
initial_anchor_node,
|
||||
initial_mount_node,
|
||||
update_anchor_node,
|
||||
update_mount_node
|
||||
}) {
|
||||
const { create_each_block, iterations, data_length, view_length } = this.vars;
|
||||
const get_key = block.get_unique_name('get_key');
|
||||
const lookup = block.get_unique_name(`${this.var.name}_lookup`);
|
||||
block.add_variable(iterations, 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)};
|
||||
|
||||
${
|
||||
this.renderer.options.dev &&
|
||||
b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`
|
||||
}
|
||||
for (let #i = 0; #i < ${data_length}; #i += 1) {
|
||||
let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i);
|
||||
let key = ${get_key}(child_ctx);
|
||||
${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx));
|
||||
}
|
||||
`);
|
||||
block.chunks.create.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
${iterations}[#i].c();
|
||||
}
|
||||
`);
|
||||
if (parent_nodes && this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
${iterations}[#i].l(${parent_nodes});
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.mount.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
if (${iterations}[#i]) {
|
||||
${iterations}[#i].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';
|
||||
if (this.dependencies.size) {
|
||||
this.block.maintain_context = true;
|
||||
this.updates.push(b`
|
||||
${this.vars.each_block_value} = ${snippet};
|
||||
|
||||
${this.block.has_outros && b`@group_outros();`}
|
||||
${
|
||||
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, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${
|
||||
this.vars.each_block_value
|
||||
}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${
|
||||
this.vars.get_each_context
|
||||
});
|
||||
${
|
||||
this.node.has_animation &&
|
||||
b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`
|
||||
}
|
||||
${this.block.has_outros && b`@check_outros();`}
|
||||
`);
|
||||
}
|
||||
if (this.block.has_outros) {
|
||||
block.chunks.outro.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
@transition_out(${iterations}[#i]);
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.destroy.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
${iterations}[#i].d(${parent_node ? null : 'detaching'});
|
||||
}
|
||||
`);
|
||||
}
|
||||
/**
|
||||
* @param {{
|
||||
* block: import('../Block.js').default;
|
||||
* parent_nodes: import('estree').Identifier;
|
||||
* snippet: import('estree').Node;
|
||||
* initial_anchor_node: import('estree').Identifier;
|
||||
* initial_mount_node: import('estree').Identifier;
|
||||
* update_anchor_node: import('estree').Identifier;
|
||||
* update_mount_node: import('estree').Identifier;
|
||||
* }} params
|
||||
*/
|
||||
render_unkeyed({
|
||||
block,
|
||||
parent_nodes,
|
||||
snippet,
|
||||
initial_anchor_node,
|
||||
initial_mount_node,
|
||||
update_anchor_node,
|
||||
update_mount_node
|
||||
}) {
|
||||
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();
|
||||
}
|
||||
`);
|
||||
if (parent_nodes && this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
${iterations}[#i].l(${parent_nodes});
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.mount.push(b`
|
||||
for (let #i = 0; #i < ${view_length}; #i += 1) {
|
||||
if (${iterations}[#i]) {
|
||||
${iterations}[#i].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 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';
|
||||
|
||||
/** @type {import('estree').Node[]} */
|
||||
let remove_old_blocks;
|
||||
if (this.block.has_outros) {
|
||||
const out = block.get_unique_name('out');
|
||||
block.chunks.init.push(b`
|
||||
const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => {
|
||||
${iterations}[i] = null;
|
||||
});
|
||||
`);
|
||||
remove_old_blocks = b`
|
||||
@group_outros();
|
||||
for (#i = ${data_length}; #i < ${view_length}; #i += 1) {
|
||||
${out}(#i);
|
||||
}
|
||||
@check_outros();
|
||||
`;
|
||||
} else {
|
||||
remove_old_blocks = b`
|
||||
for (${this.block.has_update_method ? null : x`#i = ${data_length}`}; #i < ${
|
||||
this.block.has_update_method ? view_length : '#old_length'
|
||||
}; #i += 1) {
|
||||
${iterations}[#i].d(1);
|
||||
}
|
||||
${!fixed_length && b`${view_length} = ${data_length};`}
|
||||
`;
|
||||
}
|
||||
// We declare `i` as block scoped here, as the `remove_old_blocks` code
|
||||
// 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};
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
${remove_old_blocks}
|
||||
`;
|
||||
this.updates.push(update);
|
||||
}
|
||||
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]);
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.destroy.push(b`@destroy_each(${iterations}, detaching);`);
|
||||
}
|
||||
}
|
434
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/Attribute.js
generated
vendored
Normal file
434
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/Attribute.js
generated
vendored
Normal file
@ -0,0 +1,434 @@
|
||||
import fix_attribute_casing from './fix_attribute_casing.js';
|
||||
import { string_literal } from '../../../utils/stringify.js';
|
||||
import { b, x } from 'code-red';
|
||||
import handle_select_value_binding from './handle_select_value_binding.js';
|
||||
import { namespaces } from '../../../../utils/namespaces.js';
|
||||
import { boolean_attributes } from '../../../../../shared/boolean_attributes.js';
|
||||
import { regex_double_quotes } from '../../../../utils/patterns.js';
|
||||
|
||||
const non_textlike_input_types = new Set([
|
||||
'button',
|
||||
'checkbox',
|
||||
'color',
|
||||
'date',
|
||||
'datetime-local',
|
||||
'file',
|
||||
'hidden',
|
||||
'image',
|
||||
'radio',
|
||||
'range',
|
||||
'reset',
|
||||
'submit'
|
||||
]);
|
||||
|
||||
export class BaseAttributeWrapper {
|
||||
/** @type {import('../../../nodes/Attribute.js').default} */
|
||||
node;
|
||||
|
||||
/** @type {import('./index.js').default} */
|
||||
parent;
|
||||
|
||||
/**
|
||||
* @param {import('./index.js').default} parent
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('../../../nodes/Attribute.js').default} node
|
||||
*/
|
||||
constructor(parent, block, node) {
|
||||
this.node = node;
|
||||
this.parent = parent;
|
||||
if (node.dependencies.size > 0) {
|
||||
block.add_dependencies(node.dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('../../Block.js').default} _block */
|
||||
render(_block) {}
|
||||
}
|
||||
const regex_minus_sign = /-/;
|
||||
const regex_invalid_variable_identifier_characters = /[^a-zA-Z_$]/g;
|
||||
|
||||
/** @extends BaseAttributeWrapper */
|
||||
export default class AttributeWrapper extends BaseAttributeWrapper {
|
||||
/** @type {any} */
|
||||
metadata;
|
||||
|
||||
/** @type {string} */
|
||||
name;
|
||||
|
||||
/** @type {string} */
|
||||
property_name;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_indirectly_bound_value;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_src;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_srcset;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_select_value_attribute;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_input_value;
|
||||
|
||||
/** @type {boolean} */
|
||||
should_cache;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
last;
|
||||
constructor(parent, block, node) {
|
||||
super(parent, block, node);
|
||||
if (node.dependencies.size > 0) {
|
||||
// special case — <option value={foo}> — see below
|
||||
if (this.parent.node.name === 'option' && node.name === 'value') {
|
||||
let select = this.parent;
|
||||
while (select && (select.node.type !== 'Element' || select.node.name !== 'select')) {
|
||||
// @ts-ignore todo: doublecheck this, but looks to be correct
|
||||
select = select.parent;
|
||||
}
|
||||
if (select && select.select_binding_dependencies) {
|
||||
select.select_binding_dependencies.forEach((prop) => {
|
||||
this.node.dependencies.forEach((dependency) => {
|
||||
if (this.node.scope.is_top_level(dependency)) {
|
||||
this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
if (node.name === 'value') {
|
||||
handle_select_value_binding(this, node.dependencies);
|
||||
this.parent.has_dynamic_value = true;
|
||||
}
|
||||
}
|
||||
if (this.parent.node.namespace == namespaces.foreign || this.parent.node.name.includes('-')) {
|
||||
// leave attribute case alone for elements in the "foreign" namespace and for custom elements
|
||||
this.name = this.node.name;
|
||||
this.metadata = this.get_metadata();
|
||||
this.is_indirectly_bound_value = false;
|
||||
this.property_name = null;
|
||||
this.is_select_value_attribute = false;
|
||||
this.is_input_value = false;
|
||||
} else {
|
||||
this.name = fix_attribute_casing(this.node.name);
|
||||
this.metadata = this.get_metadata();
|
||||
this.is_indirectly_bound_value = is_indirectly_bound_value(this);
|
||||
this.property_name = this.is_indirectly_bound_value
|
||||
? '__value'
|
||||
: this.metadata && this.metadata.property_name;
|
||||
this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
|
||||
this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
|
||||
}
|
||||
// TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
|
||||
this.is_src =
|
||||
this.name === 'src' &&
|
||||
(!this.parent.node.namespace || this.parent.node.namespace === namespaces.html);
|
||||
this.is_srcset =
|
||||
this.name === 'srcset' &&
|
||||
(!this.parent.node.namespace || this.parent.node.namespace === namespaces.html);
|
||||
this.should_cache = should_cache(this);
|
||||
}
|
||||
|
||||
/** @param {import('../../Block.js').default} block */
|
||||
render(block) {
|
||||
const element = this.parent;
|
||||
const { name, property_name, should_cache, is_indirectly_bound_value } = this;
|
||||
// xlink is a special case... we could maybe extend this to generic
|
||||
// namespaced attributes but I'm not sure that's applicable in
|
||||
// HTML5?
|
||||
const method = regex_minus_sign.test(element.node.name)
|
||||
? '@set_custom_element_data'
|
||||
: name.slice(0, 6) === 'xlink:'
|
||||
? '@xlink_attr'
|
||||
: '@attr';
|
||||
const is_legacy_input_type =
|
||||
element.renderer.component.compile_options.legacy &&
|
||||
name === 'type' &&
|
||||
this.parent.node.name === 'input';
|
||||
const dependencies = this.get_dependencies();
|
||||
const value = this.get_value(block);
|
||||
|
||||
/** @type {import('estree').Node[]} */
|
||||
let updater;
|
||||
const init = this.get_init(block, value);
|
||||
if (is_legacy_input_type) {
|
||||
block.chunks.hydrate.push(b`@set_input_type(${element.var}, ${init});`);
|
||||
updater = b`@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
|
||||
} else if (this.is_select_value_attribute) {
|
||||
// annoying special case
|
||||
const is_multiple_select = element.node.get_static_attribute_value('multiple');
|
||||
if (is_multiple_select) {
|
||||
updater = b`@select_options(${element.var}, ${value});`;
|
||||
} else {
|
||||
updater = b`@select_option(${element.var}, ${value});`;
|
||||
}
|
||||
block.chunks.mount.push(b`
|
||||
${updater}
|
||||
`);
|
||||
} else if (this.is_src) {
|
||||
block.chunks.hydrate.push(
|
||||
b`if (!@src_url_equal(${element.var}.src, ${init})) ${method}(${element.var}, "${name}", ${this.last});`
|
||||
);
|
||||
updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
|
||||
} else if (this.is_srcset) {
|
||||
block.chunks.hydrate.push(
|
||||
b`if (!@srcset_url_equal(${element.var}, ${init})) ${method}(${element.var}, "${name}", ${this.last});`
|
||||
);
|
||||
updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
|
||||
} else if (property_name) {
|
||||
block.chunks.hydrate.push(b`${element.var}.${property_name} = ${init};`);
|
||||
updater = block.renderer.options.dev
|
||||
? b`@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
|
||||
: b`${element.var}.${property_name} = ${should_cache ? this.last : value};`;
|
||||
} else {
|
||||
block.chunks.hydrate.push(b`${method}(${element.var}, "${name}", ${init});`);
|
||||
updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
|
||||
}
|
||||
if (is_indirectly_bound_value) {
|
||||
const update_value = b`@set_input_value(${element.var}, ${element.var}.__value);`;
|
||||
block.chunks.hydrate.push(update_value);
|
||||
updater = b`
|
||||
${updater}
|
||||
${update_value};
|
||||
`;
|
||||
}
|
||||
if (this.node.name === 'value' && dependencies.length > 0) {
|
||||
if (this.parent.bindings.some((binding) => binding.node.name === 'group')) {
|
||||
this.parent.dynamic_value_condition = block.get_unique_name('value_has_changed');
|
||||
block.add_variable(this.parent.dynamic_value_condition, x`false`);
|
||||
updater = b`
|
||||
${updater}
|
||||
${this.parent.dynamic_value_condition} = true;
|
||||
`;
|
||||
}
|
||||
}
|
||||
if (dependencies.length > 0) {
|
||||
const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${updater}
|
||||
}`);
|
||||
}
|
||||
// special case – autofocus. has to be handled in a bit of a weird way
|
||||
if (name === 'autofocus') {
|
||||
block.autofocus = {
|
||||
element_var: element.var,
|
||||
condition_expression: this.node.is_true ? undefined : value
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {any} value
|
||||
*/
|
||||
get_init(block, value) {
|
||||
this.last =
|
||||
this.should_cache &&
|
||||
block.get_unique_name(
|
||||
`${this.parent.var.name}_${this.name.replace(
|
||||
regex_invalid_variable_identifier_characters,
|
||||
'_'
|
||||
)}_value`
|
||||
);
|
||||
if (this.should_cache) block.add_variable(this.last);
|
||||
return this.should_cache ? x`${this.last} = ${value}` : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Node} dependency_condition
|
||||
*/
|
||||
get_dom_update_conditions(block, dependency_condition) {
|
||||
const { property_name, should_cache, last } = this;
|
||||
const element = this.parent;
|
||||
const value = this.get_value(block);
|
||||
let condition = dependency_condition;
|
||||
if (should_cache) {
|
||||
condition = this.is_src
|
||||
? x`${condition} && (!@src_url_equal(${element.var}.src, (${last} = ${value})))`
|
||||
: x`${condition} && (${last} !== (${last} = ${value}))`;
|
||||
}
|
||||
if (this.is_input_value) {
|
||||
const type = element.node.get_static_attribute_value('type');
|
||||
if (type !== true && !non_textlike_input_types.has(type)) {
|
||||
condition = x`${condition} && ${element.var}.${property_name} !== ${
|
||||
should_cache ? last : value
|
||||
}`;
|
||||
}
|
||||
}
|
||||
if (block.has_outros) {
|
||||
condition = x`!#current || ${condition}`;
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
get_dependencies() {
|
||||
const node_dependencies = this.node.get_dependencies();
|
||||
const dependencies = new Set(node_dependencies);
|
||||
node_dependencies.forEach((prop) => {
|
||||
const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
|
||||
if (indirect_dependencies) {
|
||||
indirect_dependencies.forEach((indirect_dependency) => {
|
||||
dependencies.add(indirect_dependency);
|
||||
});
|
||||
}
|
||||
});
|
||||
return Array.from(dependencies);
|
||||
}
|
||||
get_metadata() {
|
||||
if (this.parent.node.namespace) return null;
|
||||
const metadata = attribute_lookup[this.name];
|
||||
if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name))
|
||||
return null;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/** @param {import('../../Block.js').default} block */
|
||||
get_value(block) {
|
||||
if (this.node.is_true) {
|
||||
if (this.metadata && boolean_attributes.has(this.metadata.property_name.toLowerCase())) {
|
||||
return x`true`;
|
||||
}
|
||||
return x`""`;
|
||||
}
|
||||
if (this.node.chunks.length === 0) return x`""`;
|
||||
// TODO some of this code is repeated in Tag.ts — would be good to
|
||||
// DRY it out if that's possible without introducing crazy indirection
|
||||
if (this.node.chunks.length === 1) {
|
||||
return this.node.chunks[0].type === 'Text'
|
||||
? string_literal(
|
||||
/** @type {import('../../../nodes/Text.js').default} */ (this.node.chunks[0]).data
|
||||
)
|
||||
: /** @type {import('../../../nodes/shared/Expression.js').default} */ (
|
||||
this.node.chunks[0]
|
||||
).manipulate(block);
|
||||
}
|
||||
let value =
|
||||
this.node.name === 'class'
|
||||
? this.get_class_name_text(block)
|
||||
: this.render_chunks(block).reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
|
||||
// '{foo} {bar}' — treat as string concatenation
|
||||
if (this.node.chunks[0].type !== 'Text') {
|
||||
value = x`"" + ${value}`;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/** @param {import('../../Block.js').default} block */
|
||||
get_class_name_text(block) {
|
||||
const scoped_css = this.node.chunks.some(
|
||||
(/** @type {import('../../../nodes/Text.js').default} */ chunk) => chunk.synthetic
|
||||
);
|
||||
const rendered = this.render_chunks(block);
|
||||
if (scoped_css && rendered.length === 2) {
|
||||
// we have a situation like class={possiblyUndefined}
|
||||
rendered[0] = x`@null_to_empty(${rendered[0]})`;
|
||||
}
|
||||
return rendered.reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
|
||||
}
|
||||
|
||||
/** @param {import('../../Block.js').default} block */
|
||||
render_chunks(block) {
|
||||
return this.node.chunks.map((chunk) => {
|
||||
if (chunk.type === 'Text') {
|
||||
return string_literal(chunk.data);
|
||||
}
|
||||
return chunk.manipulate(block);
|
||||
});
|
||||
}
|
||||
stringify() {
|
||||
if (this.node.is_true) return '';
|
||||
const value = this.node.chunks;
|
||||
if (value.length === 0) return '=""';
|
||||
return `="${value
|
||||
.map((chunk) => {
|
||||
return chunk.type === 'Text'
|
||||
? chunk.data.replace(regex_double_quotes, '\\"')
|
||||
: `\${${chunk.manipulate()}}`;
|
||||
})
|
||||
.join('')}"`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @type {{
|
||||
* [key in import('../../../../../shared/boolean_attributes.js').BooleanAttributes]: { property_name?: string; applies_to?: string[] } } &
|
||||
* { [key in string]: { property_name?: string; applies_to?: string[] }; }
|
||||
* }
|
||||
*/
|
||||
const attribute_lookup = {
|
||||
allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
|
||||
allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
|
||||
async: { applies_to: ['script'] },
|
||||
autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
|
||||
autoplay: { applies_to: ['audio', 'video'] },
|
||||
checked: { applies_to: ['input'] },
|
||||
controls: { applies_to: ['audio', 'video'] },
|
||||
default: { applies_to: ['track'] },
|
||||
defer: { applies_to: ['script'] },
|
||||
disabled: {
|
||||
applies_to: [
|
||||
'button',
|
||||
'fieldset',
|
||||
'input',
|
||||
'keygen',
|
||||
'optgroup',
|
||||
'option',
|
||||
'select',
|
||||
'textarea'
|
||||
]
|
||||
},
|
||||
formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
|
||||
hidden: {},
|
||||
indeterminate: { applies_to: ['input'] },
|
||||
inert: {},
|
||||
ismap: { property_name: 'isMap', applies_to: ['img'] },
|
||||
loop: { applies_to: ['audio', 'bgsound', 'video'] },
|
||||
multiple: { applies_to: ['input', 'select'] },
|
||||
muted: { applies_to: ['audio', 'video'] },
|
||||
nomodule: { property_name: 'noModule', applies_to: ['script'] },
|
||||
novalidate: { property_name: 'noValidate', applies_to: ['form'] },
|
||||
open: { applies_to: ['details', 'dialog'] },
|
||||
playsinline: { property_name: 'playsInline', applies_to: ['video'] },
|
||||
readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
|
||||
required: { applies_to: ['input', 'select', 'textarea'] },
|
||||
reversed: { applies_to: ['ol'] },
|
||||
selected: { applies_to: ['option'] },
|
||||
value: {
|
||||
applies_to: [
|
||||
'button',
|
||||
'option',
|
||||
'input',
|
||||
'li',
|
||||
'meter',
|
||||
'progress',
|
||||
'param',
|
||||
'select',
|
||||
'textarea'
|
||||
]
|
||||
}
|
||||
};
|
||||
Object.keys(attribute_lookup).forEach((name) => {
|
||||
const metadata = attribute_lookup[name];
|
||||
if (!metadata.property_name) metadata.property_name = name;
|
||||
});
|
||||
|
||||
/** @param {AttributeWrapper} attribute */
|
||||
function should_cache(attribute) {
|
||||
return attribute.is_src || attribute.is_srcset || attribute.node.should_cache();
|
||||
}
|
||||
const regex_contains_checked_or_group = /checked|group/;
|
||||
|
||||
/** @param {AttributeWrapper} attribute */
|
||||
function is_indirectly_bound_value(attribute) {
|
||||
const element = attribute.parent;
|
||||
return (
|
||||
attribute.name === 'value' &&
|
||||
(element.node.name === 'option' || // TODO check it's actually bound
|
||||
(element.node.name === 'input' &&
|
||||
element.node.bindings.some((binding) =>
|
||||
regex_contains_checked_or_group.test(binding.name)
|
||||
)))
|
||||
);
|
||||
}
|
460
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/Binding.js
generated
vendored
Normal file
460
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/Binding.js
generated
vendored
Normal file
@ -0,0 +1,460 @@
|
||||
import { b, x } from 'code-red';
|
||||
import get_object from '../../../utils/get_object.js';
|
||||
import replace_object from '../../../utils/replace_object.js';
|
||||
import flatten_reference from '../../../utils/flatten_reference.js';
|
||||
import add_to_set from '../../../utils/add_to_set.js';
|
||||
import mark_each_block_bindings from '../shared/mark_each_block_bindings.js';
|
||||
import handle_select_value_binding from './handle_select_value_binding.js';
|
||||
import { regex_box_size } from '../../../../utils/patterns.js';
|
||||
/** */
|
||||
export default class BindingWrapper {
|
||||
/** @type {import('../../../nodes/Binding.js').default} */
|
||||
node = undefined;
|
||||
|
||||
/** @type {import('./index.js').default | import('../InlineComponent/index.js').default} */
|
||||
parent = undefined;
|
||||
|
||||
/** @type {string} */
|
||||
object = undefined;
|
||||
/**
|
||||
* @type {{
|
||||
* uses_context: boolean;
|
||||
* mutation: import('estree').Node | import('estree').Node[];
|
||||
* contextual_dependencies: Set<string>;
|
||||
* lhs?: import('estree').Node;
|
||||
* }}
|
||||
*/
|
||||
handler = undefined;
|
||||
|
||||
/** @type {import('estree').Node} */
|
||||
snippet = undefined;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_readonly = undefined;
|
||||
|
||||
/** @type {boolean} */
|
||||
needs_lock = undefined;
|
||||
|
||||
/** @type {import('../../Renderer.js').BindingGroup} */
|
||||
binding_group = undefined;
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('../../../nodes/Binding.js').default} node
|
||||
* @param {import('./index.js').default | import('../InlineComponent/index.js').default} parent
|
||||
*/
|
||||
constructor(block, node, parent) {
|
||||
this.node = node;
|
||||
this.parent = parent;
|
||||
const { dependencies } = this.node.expression;
|
||||
block.add_dependencies(dependencies);
|
||||
// TODO does this also apply to e.g. `<input type='checkbox' bind:group='foo'>`?
|
||||
handle_select_value_binding(this, dependencies);
|
||||
if (node.is_contextual) {
|
||||
mark_each_block_bindings(this.parent, this.node);
|
||||
}
|
||||
this.object = get_object(this.node.expression.node).name;
|
||||
if (this.node.name === 'group') {
|
||||
this.binding_group = get_binding_group(parent.renderer, this, block);
|
||||
}
|
||||
// view to model
|
||||
this.handler = get_event_handler(
|
||||
this,
|
||||
parent.renderer,
|
||||
block,
|
||||
this.object,
|
||||
this.node.raw_expression
|
||||
);
|
||||
this.snippet = this.node.expression.manipulate(block);
|
||||
this.is_readonly = this.node.is_readonly;
|
||||
this.needs_lock = this.node.name === 'currentTime'; // TODO others?
|
||||
}
|
||||
get_dependencies() {
|
||||
const dependencies = new Set(this.node.expression.dependencies);
|
||||
this.node.expression.dependencies.forEach((prop) => {
|
||||
const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
|
||||
if (indirect_dependencies) {
|
||||
indirect_dependencies.forEach((indirect_dependency) => {
|
||||
dependencies.add(indirect_dependency);
|
||||
});
|
||||
}
|
||||
});
|
||||
if (this.binding_group) {
|
||||
this.binding_group.list_dependencies.forEach((dep) => dependencies.add(dep));
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
get_update_dependencies() {
|
||||
const object = this.object;
|
||||
const dependencies = new Set();
|
||||
if (this.node.expression.template_scope.names.has(object)) {
|
||||
this.node.expression.template_scope.dependencies_for_name
|
||||
.get(object)
|
||||
.forEach((name) => dependencies.add(name));
|
||||
} else {
|
||||
dependencies.add(object);
|
||||
}
|
||||
const result = new Set(dependencies);
|
||||
dependencies.forEach((dependency) => {
|
||||
const indirect_dependencies =
|
||||
this.parent.renderer.component.indirect_dependencies.get(dependency);
|
||||
if (indirect_dependencies) {
|
||||
indirect_dependencies.forEach((indirect_dependency) => {
|
||||
result.add(indirect_dependency);
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
is_readonly_media_attribute() {
|
||||
return this.node.is_readonly_media_attribute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Identifier} lock
|
||||
*/
|
||||
render(block, lock) {
|
||||
if (this.is_readonly) return;
|
||||
const { parent } = this;
|
||||
|
||||
/** @type {any[]} */
|
||||
const update_conditions = this.needs_lock ? [x`!${lock}`] : [];
|
||||
|
||||
/** @type {any[]} */
|
||||
const mount_conditions = [];
|
||||
|
||||
/** @type {any} */
|
||||
let update_or_condition = null;
|
||||
const dependency_array = Array.from(this.get_dependencies());
|
||||
if (dependency_array.length > 0) {
|
||||
update_conditions.push(block.renderer.dirty(dependency_array));
|
||||
}
|
||||
if (parent.node.name === 'input') {
|
||||
const type = parent.node.get_static_attribute_value('type');
|
||||
if (
|
||||
type === null ||
|
||||
type === '' ||
|
||||
type === 'text' ||
|
||||
type === 'email' ||
|
||||
type === 'password' ||
|
||||
type === 'search' ||
|
||||
type === 'url'
|
||||
) {
|
||||
update_conditions.push(x`${parent.var}.${this.node.name} !== ${this.snippet}`);
|
||||
} else if (type === 'number') {
|
||||
update_conditions.push(x`@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
|
||||
}
|
||||
}
|
||||
// model to view
|
||||
let update_dom = get_dom_updater(parent, this, false);
|
||||
let mount_dom = get_dom_updater(parent, this, true);
|
||||
// special cases
|
||||
switch (this.node.name) {
|
||||
case 'group': {
|
||||
block.renderer.add_to_context('$$binding_groups');
|
||||
this.binding_group.add_element(block, this.parent.var);
|
||||
if (/** @type {import('./index.js').default} */ (this.parent).has_dynamic_value) {
|
||||
update_or_condition = /** @type {import('./index.js').default} */ (this.parent)
|
||||
.dynamic_value_condition;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'textContent':
|
||||
update_conditions.push(x`${this.snippet} !== ${parent.var}.textContent`);
|
||||
mount_conditions.push(x`${this.snippet} !== void 0`);
|
||||
break;
|
||||
case 'innerText':
|
||||
update_conditions.push(x`${this.snippet} !== ${parent.var}.innerText`);
|
||||
mount_conditions.push(x`${this.snippet} !== void 0`);
|
||||
break;
|
||||
case 'innerHTML':
|
||||
update_conditions.push(x`${this.snippet} !== ${parent.var}.innerHTML`);
|
||||
mount_conditions.push(x`${this.snippet} !== void 0`);
|
||||
break;
|
||||
case 'currentTime':
|
||||
update_conditions.push(x`!@_isNaN(${this.snippet})`);
|
||||
mount_dom = null;
|
||||
break;
|
||||
case 'playbackRate':
|
||||
case 'volume':
|
||||
update_conditions.push(x`!@_isNaN(${this.snippet})`);
|
||||
mount_conditions.push(x`!@_isNaN(${this.snippet})`);
|
||||
break;
|
||||
case 'paused': {
|
||||
// this is necessary to prevent audio restarting by itself
|
||||
const last = block.get_unique_name(`${parent.var.name}_is_paused`);
|
||||
block.add_variable(last, x`true`);
|
||||
update_conditions.push(x`${last} !== (${last} = ${this.snippet})`);
|
||||
update_dom = b`${parent.var}[${last} ? "pause" : "play"]();`;
|
||||
mount_dom = null;
|
||||
break;
|
||||
}
|
||||
case 'value':
|
||||
if (parent.node.get_static_attribute_value('type') === 'file') {
|
||||
update_dom = null;
|
||||
mount_dom = null;
|
||||
}
|
||||
}
|
||||
if (update_dom) {
|
||||
if (update_conditions.length > 0) {
|
||||
let condition = update_conditions.reduce((lhs, rhs) => x`${lhs} && ${rhs}`);
|
||||
if (update_or_condition) condition = x`${update_or_condition} || (${condition})`;
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${update_dom}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(update_dom);
|
||||
}
|
||||
}
|
||||
if (mount_dom) {
|
||||
if (mount_conditions.length > 0) {
|
||||
const condition = mount_conditions.reduce((lhs, rhs) => x`${lhs} && ${rhs}`);
|
||||
block.chunks.mount.push(b`
|
||||
if (${condition}) {
|
||||
${mount_dom}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.mount.push(mount_dom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./index.js').default | import('../InlineComponent/index.js').default} element
|
||||
* @param {BindingWrapper} binding
|
||||
* @param {boolean} mounting
|
||||
*/
|
||||
function get_dom_updater(element, binding, mounting) {
|
||||
const { node } = element;
|
||||
if (binding.is_readonly_media_attribute()) {
|
||||
return null;
|
||||
}
|
||||
if (binding.node.name === 'this') {
|
||||
return null;
|
||||
}
|
||||
if (node.name === 'select') {
|
||||
return node.get_static_attribute_value('multiple') === true
|
||||
? b`@select_options(${element.var}, ${binding.snippet})`
|
||||
: mounting
|
||||
? b`@select_option(${element.var}, ${binding.snippet}, true)`
|
||||
: b`@select_option(${element.var}, ${binding.snippet})`;
|
||||
}
|
||||
if (binding.node.name === 'group') {
|
||||
const type = node.get_static_attribute_value('type');
|
||||
const condition =
|
||||
type === 'checkbox'
|
||||
? x`~(${binding.snippet} || []).indexOf(${element.var}.__value)`
|
||||
: x`${element.var}.__value === ${binding.snippet}`;
|
||||
return b`${element.var}.checked = ${condition};`;
|
||||
}
|
||||
if (binding.node.name === 'value') {
|
||||
return b`@set_input_value(${element.var}, ${binding.snippet});`;
|
||||
}
|
||||
return b`${element.var}.${binding.node.name} = ${binding.snippet};`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Renderer.js').default} renderer
|
||||
* @param {BindingWrapper} binding
|
||||
* @param {import('../../Block.js').default} block
|
||||
*/
|
||||
function get_binding_group(renderer, binding, block) {
|
||||
const value = binding.node;
|
||||
const { parts } = flatten_reference(value.raw_expression);
|
||||
let keypath = parts.join('.');
|
||||
const contexts = [];
|
||||
const contextual_dependencies = new Set();
|
||||
const { template_scope } = value.expression;
|
||||
|
||||
/** @param {string} dep */
|
||||
const add_contextual_dependency = (dep) => {
|
||||
contextual_dependencies.add(dep);
|
||||
const owner = template_scope.get_owner(dep);
|
||||
if (owner.type === 'EachBlock') {
|
||||
for (const dep of owner.expression.contextual_dependencies) {
|
||||
add_contextual_dependency(dep);
|
||||
}
|
||||
}
|
||||
};
|
||||
for (const dep of value.expression.contextual_dependencies) {
|
||||
add_contextual_dependency(dep);
|
||||
}
|
||||
for (const dep of contextual_dependencies) {
|
||||
const context = block.bindings.get(dep);
|
||||
let key;
|
||||
let name;
|
||||
if (context) {
|
||||
key = context.object.name;
|
||||
name = context.property.name;
|
||||
} else {
|
||||
key = dep;
|
||||
name = dep;
|
||||
}
|
||||
keypath = `${key}@${keypath}`;
|
||||
contexts.push(name);
|
||||
}
|
||||
// create a global binding_group across blocks
|
||||
if (!renderer.binding_groups.has(keypath)) {
|
||||
const index = renderer.binding_groups.size;
|
||||
// the bind:group depends on the list in the {#each} block as well
|
||||
// as reordering (removing and adding back to the DOM) may affect the value
|
||||
const list_dependencies = new Set();
|
||||
let parent = value.parent;
|
||||
while (parent) {
|
||||
if (parent.type === 'EachBlock') {
|
||||
for (const dep of parent.expression.dynamic_dependencies()) {
|
||||
list_dependencies.add(dep);
|
||||
}
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
/**
|
||||
* When using bind:group with logic blocks, the inputs with bind:group may be scattered across different blocks.
|
||||
* This therefore keeps track of all the <input> elements that have the same bind:group within the same block.
|
||||
*/
|
||||
const elements = new Map();
|
||||
contexts.forEach((context) => {
|
||||
renderer.add_to_context(context, true);
|
||||
});
|
||||
renderer.binding_groups.set(keypath, {
|
||||
binding_group: () => {
|
||||
let obj = x`$$binding_groups[${index}]`;
|
||||
if (contexts.length > 0) {
|
||||
contexts.forEach((secondary_index) => {
|
||||
obj = x`${obj}[${secondary_index}]`;
|
||||
});
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
contexts,
|
||||
list_dependencies,
|
||||
keypath,
|
||||
add_element(block, element) {
|
||||
if (!elements.has(block)) {
|
||||
elements.set(block, []);
|
||||
}
|
||||
elements.get(block).push(element);
|
||||
},
|
||||
render(block) {
|
||||
const local_name = block.get_unique_name('binding_group');
|
||||
const binding_group = block.renderer.reference('$$binding_groups');
|
||||
block.add_variable(local_name);
|
||||
if (contexts.length > 0) {
|
||||
const indexes = {
|
||||
type: 'ArrayExpression',
|
||||
elements: contexts.map((name) => block.renderer.reference(name))
|
||||
};
|
||||
block.chunks.init.push(
|
||||
b`${local_name} = @init_binding_group_dynamic(${binding_group}[${index}], ${indexes})`
|
||||
);
|
||||
block.chunks.update.push(
|
||||
b`if (${block.renderer.dirty(
|
||||
Array.from(list_dependencies)
|
||||
)}) ${local_name}.u(${indexes})`
|
||||
);
|
||||
} else {
|
||||
block.chunks.init.push(
|
||||
b`${local_name} = @init_binding_group(${binding_group}[${index}])`
|
||||
);
|
||||
}
|
||||
block.chunks.hydrate.push(b`${local_name}.p(${elements.get(block)})`);
|
||||
block.chunks.destroy.push(b`${local_name}.r()`);
|
||||
}
|
||||
});
|
||||
}
|
||||
// register the binding_group for the block
|
||||
const binding_group = renderer.binding_groups.get(keypath);
|
||||
block.binding_groups.add(binding_group);
|
||||
return binding_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BindingWrapper} binding
|
||||
* @param {import('../../Renderer.js').default} renderer
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {string} name
|
||||
* @param {import('estree').Node} lhs
|
||||
* @returns {{ uses_context: boolean; mutation: import('estree').Node | import('estree').Node[]; contextual_dependencies: Set<string>; lhs?: import('estree').Node; }}
|
||||
*/
|
||||
function get_event_handler(binding, renderer, block, name, lhs) {
|
||||
const contextual_dependencies = new Set(binding.node.expression.contextual_dependencies);
|
||||
const context = block.bindings.get(name);
|
||||
|
||||
/** @type {import('estree').Node[] | undefined} */
|
||||
let set_store;
|
||||
if (context) {
|
||||
const { object, property, store, snippet } = context;
|
||||
lhs = replace_object(lhs, snippet);
|
||||
contextual_dependencies.add(object.name);
|
||||
contextual_dependencies.add(property.name);
|
||||
contextual_dependencies.delete(name);
|
||||
if (store) {
|
||||
set_store = b`${store}.set(${`$${store}`});`;
|
||||
}
|
||||
} else {
|
||||
const object = get_object(lhs);
|
||||
if (object.name[0] === '$') {
|
||||
const store = object.name.slice(1);
|
||||
set_store = b`${store}.set(${object.name});`;
|
||||
}
|
||||
}
|
||||
const value = get_value_from_dom(renderer, binding.parent, binding, contextual_dependencies);
|
||||
const mutation = b`
|
||||
${lhs} = ${value};
|
||||
${set_store}
|
||||
`;
|
||||
return {
|
||||
uses_context: binding.node.is_contextual || binding.node.expression.uses_context,
|
||||
mutation,
|
||||
contextual_dependencies,
|
||||
lhs
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Renderer.js').default} _renderer
|
||||
* @param {import('./index.js').default | import('../InlineComponent/index.js').default} element
|
||||
* @param {BindingWrapper} binding
|
||||
* @param {Set<string>} contextual_dependencies
|
||||
*/
|
||||
function get_value_from_dom(_renderer, element, binding, contextual_dependencies) {
|
||||
const { node } = element;
|
||||
const { name } = binding.node;
|
||||
if (name === 'this') {
|
||||
return x`$$value`;
|
||||
}
|
||||
// <div bind:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize>
|
||||
if (regex_box_size.test(name)) {
|
||||
return x`@ResizeObserverSingleton.entries.get(this)?.${name}`;
|
||||
}
|
||||
// <select bind:value='selected>
|
||||
if (node.name === 'select') {
|
||||
return node.get_static_attribute_value('multiple') === true
|
||||
? x`@select_multiple_value(this)`
|
||||
: x`@select_value(this)`;
|
||||
}
|
||||
const type = node.get_static_attribute_value('type');
|
||||
// <input type='checkbox' bind:group='foo'>
|
||||
if (name === 'group') {
|
||||
if (type === 'checkbox') {
|
||||
const { binding_group, contexts } = binding.binding_group;
|
||||
add_to_set(contextual_dependencies, contexts);
|
||||
return x`@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
|
||||
}
|
||||
return x`this.__value`;
|
||||
}
|
||||
// <input type='range|number' bind:value>
|
||||
if (type === 'range' || type === 'number') {
|
||||
return x`@to_number(this.${name})`;
|
||||
}
|
||||
if (name === 'buffered' || name === 'seekable' || name === 'played') {
|
||||
return x`@time_ranges_to_array(this.${name})`;
|
||||
}
|
||||
// everything else
|
||||
return x`this.${name}`;
|
||||
}
|
76
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/EventHandler.js
generated
vendored
Normal file
76
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/EventHandler.js
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
import { b, x, p } from 'code-red';
|
||||
|
||||
const TRUE = x`true`;
|
||||
const FALSE = x`false`;
|
||||
|
||||
export default class EventHandlerWrapper {
|
||||
/** @type {import('../../../nodes/EventHandler.js').default} */
|
||||
node;
|
||||
|
||||
/** @type {import('../shared/Wrapper.js').default} */
|
||||
parent;
|
||||
|
||||
/**
|
||||
* @param {import('../../../nodes/EventHandler.js').default} node
|
||||
* @param {import('../shared/Wrapper.js').default} parent
|
||||
*/
|
||||
constructor(node, parent) {
|
||||
this.node = node;
|
||||
this.parent = parent;
|
||||
if (!node.expression) {
|
||||
this.parent.renderer.add_to_context(node.handler_name.name);
|
||||
this.parent.renderer.component.partly_hoisted.push(b`
|
||||
function ${node.handler_name.name}(event) {
|
||||
@bubble.call(this, $$self, event);
|
||||
}
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {import('../../Block.js').default} block */
|
||||
get_snippet(block) {
|
||||
const snippet = this.node.expression
|
||||
? this.node.expression.manipulate(block)
|
||||
: block.renderer.reference(this.node.handler_name);
|
||||
if (this.node.reassigned) {
|
||||
block.maintain_context = true;
|
||||
return x`function () { if (@is_function(${snippet})) ${snippet}.apply(this, arguments); }`;
|
||||
}
|
||||
return snippet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {string | import('estree').Expression} target
|
||||
*/
|
||||
render(block, target) {
|
||||
let snippet = this.get_snippet(block);
|
||||
if (this.node.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`;
|
||||
if (this.node.modifiers.has('stopPropagation')) snippet = x`@stop_propagation(${snippet})`;
|
||||
if (this.node.modifiers.has('stopImmediatePropagation'))
|
||||
snippet = x`@stop_immediate_propagation(${snippet})`;
|
||||
if (this.node.modifiers.has('self')) snippet = x`@self(${snippet})`;
|
||||
if (this.node.modifiers.has('trusted')) snippet = x`@trusted(${snippet})`;
|
||||
const args = [];
|
||||
const opts = ['nonpassive', 'passive', 'once', 'capture'].filter((mod) =>
|
||||
this.node.modifiers.has(mod)
|
||||
);
|
||||
if (opts.length) {
|
||||
if (opts.length === 1 && opts[0] === 'capture') {
|
||||
args.push(TRUE);
|
||||
} else {
|
||||
args.push(
|
||||
x`{ ${opts.map((opt) => (opt === 'nonpassive' ? p`passive: false` : p`${opt}: true`))} }`
|
||||
);
|
||||
}
|
||||
} else if (block.renderer.options.dev) {
|
||||
args.push(FALSE);
|
||||
}
|
||||
if (block.renderer.options.dev) {
|
||||
args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
|
||||
args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
|
||||
args.push(this.node.modifiers.has('stopImmediatePropagation') ? TRUE : FALSE);
|
||||
}
|
||||
block.event_listeners.push(x`@listen(${target}, "${this.node.name}", ${snippet}, ${args})`);
|
||||
}
|
||||
}
|
3
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/SpreadAttribute.js
generated
vendored
Normal file
3
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/SpreadAttribute.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { BaseAttributeWrapper } from './Attribute.js';
|
||||
|
||||
export default class SpreadAttributeWrapper extends BaseAttributeWrapper {}
|
162
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/StyleAttribute.js
generated
vendored
Normal file
162
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/StyleAttribute.js
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
import { b, x } from 'code-red';
|
||||
import AttributeWrapper from './Attribute.js';
|
||||
import { string_literal } from '../../../utils/stringify.js';
|
||||
import add_to_set from '../../../utils/add_to_set.js';
|
||||
|
||||
/** @extends AttributeWrapper */
|
||||
export default class StyleAttributeWrapper extends AttributeWrapper {
|
||||
/** @param {import('../../Block.js').default} block */
|
||||
render(block) {
|
||||
const style_props = optimize_style(this.node.chunks);
|
||||
if (!style_props) return super.render(block);
|
||||
style_props.forEach((prop) => {
|
||||
let value;
|
||||
if (is_dynamic(prop.value)) {
|
||||
const prop_dependencies = new Set();
|
||||
value = prop.value
|
||||
.map((chunk) => {
|
||||
if (chunk.type === 'Text') {
|
||||
return string_literal(chunk.data);
|
||||
} else {
|
||||
add_to_set(prop_dependencies, chunk.dynamic_dependencies());
|
||||
return chunk.manipulate(block);
|
||||
}
|
||||
})
|
||||
.reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
|
||||
// TODO is this necessary? style.setProperty always treats value as string, no?
|
||||
// if (prop.value.length === 1 || prop.value[0].type !== 'Text') {
|
||||
// value = x`"" + ${value}`;
|
||||
// }
|
||||
if (prop_dependencies.size) {
|
||||
let condition = block.renderer.dirty(Array.from(prop_dependencies));
|
||||
if (block.has_outros) {
|
||||
condition = x`!#current || ${condition}`;
|
||||
}
|
||||
const update = b`
|
||||
if (${condition}) {
|
||||
@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});
|
||||
}`;
|
||||
block.chunks.update.push(update);
|
||||
}
|
||||
} else {
|
||||
value = string_literal(
|
||||
/** @type {import('../../../nodes/Text.js').default} */ (prop.value[0]).data
|
||||
);
|
||||
}
|
||||
block.chunks.hydrate.push(
|
||||
b`@set_style(${this.parent.var}, "${prop.key}", ${value}, ${prop.important ? 1 : null});`
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
const regex_style_prop_key = /^\s*([\w-]+):\s*/;
|
||||
|
||||
/** @param {Array<import('../../../nodes/Text.js').default | import('../../../nodes/shared/Expression.js').default>} value */
|
||||
function optimize_style(value) {
|
||||
/** @type {Array<{ key: string; value: Array<import('../../../nodes/Text.js').default | import('../../../nodes/shared/Expression.js').default>; important: boolean; }>} */
|
||||
const props = [];
|
||||
let chunks = value.slice();
|
||||
while (chunks.length) {
|
||||
const chunk = chunks[0];
|
||||
if (chunk.type !== 'Text') return null;
|
||||
const key_match = regex_style_prop_key.exec(chunk.data);
|
||||
if (!key_match) return null;
|
||||
const key = key_match[1];
|
||||
const offset = key_match.index + key_match[0].length;
|
||||
const remaining_data = chunk.data.slice(offset);
|
||||
if (remaining_data) {
|
||||
chunks[0] = /** @type {import('../../../nodes/Text.js').default} */ ({
|
||||
start: chunk.start + offset,
|
||||
end: chunk.end,
|
||||
type: 'Text',
|
||||
data: remaining_data
|
||||
});
|
||||
} else {
|
||||
chunks.shift();
|
||||
}
|
||||
const result = get_style_value(chunks);
|
||||
props.push({ key, value: result.value, important: result.important });
|
||||
chunks = result.chunks;
|
||||
}
|
||||
return props;
|
||||
}
|
||||
const regex_important_flag = /\s*!important\s*$/;
|
||||
const regex_semicolon_or_whitespace = /[;\s]/;
|
||||
|
||||
/** @param {Array<import('../../../nodes/Text.js').default | import('../../../nodes/shared/Expression.js').default>} chunks */
|
||||
function get_style_value(chunks) {
|
||||
/** @type {Array<import('../../../nodes/Text.js').default | import('../../../nodes/shared/Expression.js').default>} */
|
||||
const value = [];
|
||||
let in_url = false;
|
||||
let quote_mark = null;
|
||||
let escaped = false;
|
||||
let closed = false;
|
||||
while (chunks.length && !closed) {
|
||||
const chunk = chunks.shift();
|
||||
if (chunk.type === 'Text') {
|
||||
let c = 0;
|
||||
while (c < chunk.data.length) {
|
||||
const char = chunk.data[c];
|
||||
if (escaped) {
|
||||
escaped = false;
|
||||
} else if (char === '\\') {
|
||||
escaped = true;
|
||||
} else if (char === quote_mark) {
|
||||
quote_mark = null;
|
||||
} else if (char === '"' || char === "'") {
|
||||
quote_mark = char;
|
||||
} else if (char === ')' && in_url) {
|
||||
in_url = false;
|
||||
} else if (char === 'u' && chunk.data.slice(c, c + 4) === 'url(') {
|
||||
in_url = true;
|
||||
} else if (char === ';' && !in_url && !quote_mark) {
|
||||
closed = true;
|
||||
break;
|
||||
}
|
||||
c += 1;
|
||||
}
|
||||
if (c > 0) {
|
||||
value.push(
|
||||
/** @type {import('../../../nodes/Text.js').default} */ ({
|
||||
type: 'Text',
|
||||
start: chunk.start,
|
||||
end: chunk.start + c,
|
||||
data: chunk.data.slice(0, c)
|
||||
})
|
||||
);
|
||||
}
|
||||
while (regex_semicolon_or_whitespace.test(chunk.data[c])) c += 1;
|
||||
const remaining_data = chunk.data.slice(c);
|
||||
if (remaining_data) {
|
||||
chunks.unshift(
|
||||
/** @type {import('../../../nodes/Text.js').default} */ ({
|
||||
start: chunk.start + c,
|
||||
end: chunk.end,
|
||||
type: 'Text',
|
||||
data: remaining_data
|
||||
})
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value.push(chunk);
|
||||
}
|
||||
}
|
||||
let important = false;
|
||||
const last_chunk = value[value.length - 1];
|
||||
if (last_chunk && last_chunk.type === 'Text' && regex_important_flag.test(last_chunk.data)) {
|
||||
important = true;
|
||||
last_chunk.data = last_chunk.data.replace(regex_important_flag, '');
|
||||
if (!last_chunk.data) value.pop();
|
||||
}
|
||||
return {
|
||||
chunks,
|
||||
value,
|
||||
important
|
||||
};
|
||||
}
|
||||
|
||||
/** @param {Array<import('../../../nodes/Text.js').default | import('../../../nodes/shared/Expression.js').default>} value */
|
||||
function is_dynamic(value) {
|
||||
return value.length > 1 || value[0].type !== 'Text';
|
||||
}
|
18
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/fix_attribute_casing.js
generated
vendored
Normal file
18
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/fix_attribute_casing.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
const svg_attributes =
|
||||
'accent-height accumulate additive alignment-baseline allowReorder alphabetic amplitude arabic-form ascent attributeName attributeType autoReverse azimuth baseFrequency baseline-shift baseProfile bbox begin bias by calcMode cap-height class clip clipPathUnits clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominant-baseline dur dx dy edgeMode elevation enable-background end exponent externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format from fr fx fy g1 g2 glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits hanging height href horiz-adv-x horiz-origin-x id ideographic image-rendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lang lengthAdjust letter-spacing lighting-color limitingConeAngle local marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask maskContentUnits maskUnits mathematical max media method min mode name numOctaves offset onabort onactivate onbegin onclick onend onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onrepeat onresize onscroll onunload opacity operator order orient orientation origin overflow overline-position overline-thickness panose-1 paint-order pathLength patternContentUnits patternTransform patternUnits pointer-events points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shape-rendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness string stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale systemLanguage tabindex tableValues target targetX targetY text-anchor text-decoration text-rendering textLength to transform type u1 u2 underline-position underline-thickness unicode unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical values version vert-adv-y vert-origin-x vert-origin-y viewBox viewTarget visibility width widths word-spacing writing-mode x x-height x1 x2 xChannelSelector xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y y1 y2 yChannelSelector z zoomAndPan'.split(
|
||||
' '
|
||||
);
|
||||
|
||||
const svg_attribute_lookup = new Map();
|
||||
|
||||
svg_attributes.forEach((name) => {
|
||||
svg_attribute_lookup.set(name.toLowerCase(), name);
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
export default function fix_attribute_casing(name) {
|
||||
name = name.toLowerCase();
|
||||
return svg_attribute_lookup.get(name) || name;
|
||||
}
|
13
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/handle_select_value_binding.js
generated
vendored
Normal file
13
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/handle_select_value_binding.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @param {import('./Attribute.js').default | import('./Binding.js').default} attr
|
||||
* @param {Set<string>} dependencies
|
||||
*/
|
||||
export default function handle_select_value_binding(attr, dependencies) {
|
||||
const { parent } = attr;
|
||||
if (parent.node.name === 'select') {
|
||||
/** @type {import('./index.js').default} */ (parent).select_binding_dependencies = dependencies;
|
||||
dependencies.forEach((prop) => {
|
||||
parent.renderer.component.indirect_dependencies.set(prop, new Set());
|
||||
});
|
||||
}
|
||||
}
|
1386
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js
generated
vendored
Normal file
1386
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
164
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Fragment.js
generated
vendored
Normal file
164
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Fragment.js
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
import AwaitBlock from './AwaitBlock.js';
|
||||
import Body from './Body.js';
|
||||
import DebugTag from './DebugTag.js';
|
||||
import Document from './Document.js';
|
||||
import EachBlock from './EachBlock.js';
|
||||
import Element from './Element/index.js';
|
||||
import Head from './Head.js';
|
||||
import IfBlock from './IfBlock.js';
|
||||
import KeyBlock from './KeyBlock.js';
|
||||
import InlineComponent from './InlineComponent/index.js';
|
||||
import MustacheTag from './MustacheTag.js';
|
||||
import RawMustacheTag from './RawMustacheTag.js';
|
||||
import Slot from './Slot.js';
|
||||
import SlotTemplate from './SlotTemplate.js';
|
||||
import Text from './Text.js';
|
||||
import Comment from './Comment.js';
|
||||
import Title from './Title.js';
|
||||
import Window from './Window.js';
|
||||
import { trim_start, trim_end } from '../../../utils/trim.js';
|
||||
import { link } from '../../../utils/link.js';
|
||||
import { regex_starts_with_whitespace } from '../../../utils/patterns.js';
|
||||
|
||||
const wrappers = {
|
||||
AwaitBlock,
|
||||
Body,
|
||||
Comment,
|
||||
DebugTag,
|
||||
Document,
|
||||
EachBlock,
|
||||
Element,
|
||||
Head,
|
||||
IfBlock,
|
||||
InlineComponent,
|
||||
KeyBlock,
|
||||
MustacheTag,
|
||||
Options: null,
|
||||
RawMustacheTag,
|
||||
Slot,
|
||||
SlotTemplate,
|
||||
Text,
|
||||
Title,
|
||||
Window
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('../../nodes/interfaces.js').INode} child
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function trimmable_at(child, next_sibling) {
|
||||
// Whitespace is trimmable if one of the following is true:
|
||||
// The child and its sibling share a common nearest each block (not at an each block boundary)
|
||||
// The next sibling's previous node is an each block
|
||||
return (
|
||||
next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/) ||
|
||||
next_sibling.node.prev.type === 'EachBlock'
|
||||
);
|
||||
}
|
||||
|
||||
export default class FragmentWrapper {
|
||||
/** @type {import('./shared/Wrapper.js').default[]} */
|
||||
nodes;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('../../nodes/interfaces.js').INode[]} nodes
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, nodes, parent, strip_whitespace, next_sibling) {
|
||||
this.nodes = [];
|
||||
|
||||
/** @type {import('./shared/Wrapper.js').default} */
|
||||
let last_child;
|
||||
|
||||
/** @type {import('./Window.js').default | undefined} */
|
||||
let window_wrapper;
|
||||
let i = nodes.length;
|
||||
while (i--) {
|
||||
const child = nodes[i];
|
||||
if (!child.type) {
|
||||
throw new Error('missing type');
|
||||
}
|
||||
if (!(child.type in wrappers)) {
|
||||
throw new Error(`TODO implement ${child.type}`);
|
||||
}
|
||||
// special case — this is an easy way to remove whitespace surrounding
|
||||
// <svelte:window/>. lil hacky but it works
|
||||
if (child.type === 'Window') {
|
||||
window_wrapper = new Window(renderer, block, parent, child);
|
||||
continue;
|
||||
}
|
||||
if (child.type === 'Text') {
|
||||
let { data } = child;
|
||||
// We want to remove trailing whitespace inside an element/component/block,
|
||||
// *unless* there is no whitespace between this node and its next sibling
|
||||
if (this.nodes.length === 0) {
|
||||
const should_trim = next_sibling
|
||||
? next_sibling.node.type === 'Text' &&
|
||||
regex_starts_with_whitespace.test(next_sibling.node.data) &&
|
||||
trimmable_at(child, next_sibling)
|
||||
: !child.has_ancestor('EachBlock');
|
||||
if (should_trim && !child.keep_space()) {
|
||||
data = trim_end(data);
|
||||
if (!data) continue;
|
||||
}
|
||||
}
|
||||
// glue text nodes (which could e.g. be separated by comments) together
|
||||
if (last_child && last_child.node.type === 'Text') {
|
||||
/** @type {import('./Text.js').default} */ (last_child).data =
|
||||
data + /** @type {import('./Text.js').default} */ (last_child).data;
|
||||
continue;
|
||||
}
|
||||
const wrapper = new Text(renderer, block, parent, child, data);
|
||||
if (wrapper.skip) continue;
|
||||
this.nodes.unshift(wrapper);
|
||||
link(last_child, (last_child = wrapper));
|
||||
} else {
|
||||
const Wrapper = wrappers[child.type];
|
||||
if (!Wrapper || (child.type === 'Comment' && !renderer.options.preserveComments)) continue;
|
||||
const wrapper = new Wrapper(
|
||||
renderer,
|
||||
block,
|
||||
parent,
|
||||
child,
|
||||
strip_whitespace,
|
||||
last_child || next_sibling
|
||||
);
|
||||
this.nodes.unshift(wrapper);
|
||||
link(last_child, (last_child = wrapper));
|
||||
}
|
||||
}
|
||||
if (strip_whitespace) {
|
||||
const first = /** @type {import('./Text.js').default} */ (this.nodes[0]);
|
||||
if (first && first.node.type === 'Text' && !first.node.keep_space()) {
|
||||
first.data = trim_start(first.data);
|
||||
if (!first.data) {
|
||||
first.var = null;
|
||||
this.nodes.shift();
|
||||
if (this.nodes[0]) {
|
||||
this.nodes[0].prev = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (window_wrapper) {
|
||||
this.nodes.unshift(window_wrapper);
|
||||
link(last_child, window_wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
for (let i = 0; i < this.nodes.length; i += 1) {
|
||||
this.nodes[i].render(block, parent_node, parent_nodes);
|
||||
}
|
||||
}
|
||||
}
|
53
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Head.js
generated
vendored
Normal file
53
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Head.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import { x, b } from 'code-red';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Head.js').default> */
|
||||
export default class HeadWrapper extends Wrapper {
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Head.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
block,
|
||||
node.children,
|
||||
this,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, _parent_node, _parent_nodes) {
|
||||
/** @type {import('estree').Identifier} */
|
||||
let nodes;
|
||||
if (this.renderer.options.hydratable && this.fragment.nodes.length) {
|
||||
nodes = block.get_unique_name('head_nodes');
|
||||
block.chunks.claim.push(
|
||||
b`const ${nodes} = @head_selector('${this.node.id}', @_document.head);`
|
||||
);
|
||||
}
|
||||
this.fragment.render(
|
||||
block,
|
||||
/** @type {unknown} */ /** @type {import('estree').Identifier} */ (x`@_document.head`),
|
||||
nodes
|
||||
);
|
||||
if (nodes && this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`${nodes}.forEach(@detach);`);
|
||||
}
|
||||
}
|
||||
}
|
691
node_modules/svelte/src/compiler/compile/render_dom/wrappers/IfBlock.js
generated
vendored
Normal file
691
node_modules/svelte/src/compiler/compile/render_dom/wrappers/IfBlock.js
generated
vendored
Normal file
@ -0,0 +1,691 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import create_debugging_comment from './shared/create_debugging_comment.js';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import { b, x } from 'code-red';
|
||||
import { walk } from 'estree-walker';
|
||||
import { is_head } from './shared/is_head.js';
|
||||
import { push_array } from '../../../utils/push_array.js';
|
||||
import { add_const_tags, add_const_tags_context } from './shared/add_const_tags.js';
|
||||
|
||||
/** @param {import('../../nodes/ElseBlock.js').default} node */
|
||||
function is_else_if(node) {
|
||||
return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
|
||||
}
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/IfBlock.js').default | import('../../nodes/ElseBlock.js').default> */
|
||||
class IfBlockBranch extends Wrapper {
|
||||
/** @type {import('../Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {string[]} */
|
||||
dependencies;
|
||||
|
||||
/** @type {any} */
|
||||
condition;
|
||||
|
||||
/** @type {import('estree').Node} */
|
||||
snippet;
|
||||
|
||||
/** @type {boolean} */
|
||||
is_dynamic;
|
||||
|
||||
/** */
|
||||
var = null;
|
||||
|
||||
/** @type {import('estree').Node | undefined} */
|
||||
get_ctx_name;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {IfBlockWrapper} parent
|
||||
* @param {import('../../nodes/IfBlock.js').default | import('../../nodes/ElseBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
const { expression } = /** @type {import('../../nodes/IfBlock.js').default} */ (node);
|
||||
const is_else = !expression;
|
||||
if (expression) {
|
||||
this.dependencies = expression.dynamic_dependencies();
|
||||
// TODO is this the right rule? or should any non-reference count?
|
||||
// const should_cache = !is_reference(expression.node, null) && dependencies.length > 0;
|
||||
let should_cache = false;
|
||||
walk(expression.node, {
|
||||
enter(node) {
|
||||
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
||||
should_cache = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (should_cache) {
|
||||
this.condition = block.get_unique_name('show_if');
|
||||
this.snippet = /** @type {import('estree').Node} */ (expression.manipulate(block));
|
||||
} else {
|
||||
this.condition = expression.manipulate(block);
|
||||
}
|
||||
}
|
||||
add_const_tags_context(renderer, this.node.const_tags);
|
||||
this.block = block.child({
|
||||
comment: create_debugging_comment(node, parent.renderer.component),
|
||||
name: parent.renderer.component.get_unique_name(
|
||||
is_else ? 'create_else_block' : 'create_if_block'
|
||||
),
|
||||
type: /** @type {import('../../nodes/IfBlock.js').default} */ (node).expression
|
||||
? 'if'
|
||||
: 'else'
|
||||
});
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.block,
|
||||
node.children,
|
||||
parent,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
this.is_dynamic = this.block.dependencies.size > 0;
|
||||
if (node.const_tags.length > 0) {
|
||||
this.get_ctx_name = parent.renderer.component.get_unique_name(
|
||||
is_else ? 'get_else_ctx' : 'get_if_ctx'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/IfBlock.js').default> */
|
||||
export default class IfBlockWrapper extends Wrapper {
|
||||
/** @typedef {'detaching' | null} DetachingOrNull */
|
||||
|
||||
/** @type {IfBlockBranch[]} */
|
||||
branches;
|
||||
/** */
|
||||
needs_update = false;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 'if_block' };
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/IfBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
this.branches = [];
|
||||
|
||||
/** @type {import('../Block.js').default[]} */
|
||||
const blocks = [];
|
||||
let is_dynamic = false;
|
||||
let has_intros = false;
|
||||
let has_outros = false;
|
||||
|
||||
/** @param {import('../../nodes/IfBlock.js').default} node */
|
||||
const create_branches = (node) => {
|
||||
const branch = new IfBlockBranch(renderer, block, this, node, strip_whitespace, next_sibling);
|
||||
this.branches.push(branch);
|
||||
blocks.push(branch.block);
|
||||
block.add_dependencies(node.expression.dependencies);
|
||||
if (branch.block.dependencies.size > 0) {
|
||||
// the condition, or its contents, is dynamic
|
||||
is_dynamic = true;
|
||||
block.add_dependencies(branch.block.dependencies);
|
||||
}
|
||||
if (branch.dependencies && branch.dependencies.length > 0) {
|
||||
// the condition itself is dynamic
|
||||
this.needs_update = true;
|
||||
}
|
||||
if (branch.block.has_intros) has_intros = true;
|
||||
if (branch.block.has_outros) has_outros = true;
|
||||
if (is_else_if(node.else)) {
|
||||
create_branches(
|
||||
/** @type {import('../../nodes/IfBlock.js').default} */ (node.else.children[0])
|
||||
);
|
||||
} else if (node.else) {
|
||||
const branch = new IfBlockBranch(
|
||||
renderer,
|
||||
block,
|
||||
this,
|
||||
node.else,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
this.branches.push(branch);
|
||||
blocks.push(branch.block);
|
||||
if (branch.block.dependencies.size > 0) {
|
||||
is_dynamic = true;
|
||||
block.add_dependencies(branch.block.dependencies);
|
||||
}
|
||||
if (branch.block.has_intros) has_intros = true;
|
||||
if (branch.block.has_outros) has_outros = true;
|
||||
}
|
||||
};
|
||||
create_branches(this.node);
|
||||
blocks.forEach((block) => {
|
||||
block.has_update_method = is_dynamic;
|
||||
block.has_intro_method = has_intros;
|
||||
block.has_outro_method = has_outros;
|
||||
});
|
||||
push_array(renderer.blocks, blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
const name = this.var;
|
||||
const needs_anchor = this.next
|
||||
? !this.next.is_dom_node()
|
||||
: !parent_node || !this.parent.is_dom_node();
|
||||
const anchor = needs_anchor
|
||||
? block.get_unique_name(`${this.var.name}_anchor`)
|
||||
: (this.next && this.next.var) || 'null';
|
||||
const has_else = !this.branches[this.branches.length - 1].condition;
|
||||
const if_exists_condition = has_else ? null : name;
|
||||
const dynamic = this.branches[0].block.has_update_method; // can use [0] as proxy for all, since they necessarily have the same value
|
||||
const has_intros = this.branches[0].block.has_intro_method;
|
||||
const has_outros = this.branches[0].block.has_outro_method;
|
||||
const has_transitions = has_intros || has_outros;
|
||||
this.branches.forEach((branch) => {
|
||||
if (branch.get_ctx_name) {
|
||||
this.renderer.blocks.push(b`
|
||||
function ${branch.get_ctx_name}(#ctx) {
|
||||
const child_ctx = #ctx.slice();
|
||||
${add_const_tags(block, branch.node.const_tags, 'child_ctx')}
|
||||
return child_ctx;
|
||||
}
|
||||
`);
|
||||
}
|
||||
});
|
||||
const vars = { name, anchor, if_exists_condition, has_else, has_transitions };
|
||||
|
||||
/** @type {DetachingOrNull} */
|
||||
const detaching = parent_node && !is_head(parent_node) ? null : 'detaching';
|
||||
if (this.node.else) {
|
||||
this.branches.forEach((branch) => {
|
||||
if (branch.snippet) block.add_variable(branch.condition);
|
||||
});
|
||||
if (has_outros) {
|
||||
this.render_compound_with_outros(
|
||||
block,
|
||||
parent_node,
|
||||
parent_nodes,
|
||||
dynamic,
|
||||
vars,
|
||||
detaching
|
||||
);
|
||||
block.chunks.outro.push(b`@transition_out(${name});`);
|
||||
} else {
|
||||
this.render_compound(block, parent_node, parent_nodes, dynamic, vars, detaching);
|
||||
}
|
||||
} else {
|
||||
this.render_simple(block, parent_node, parent_nodes, dynamic, vars, detaching);
|
||||
if (has_outros) {
|
||||
block.chunks.outro.push(b`@transition_out(${name});`);
|
||||
}
|
||||
}
|
||||
if (if_exists_condition) {
|
||||
block.chunks.create.push(b`if (${if_exists_condition}) ${name}.c();`);
|
||||
} else {
|
||||
block.chunks.create.push(b`${name}.c();`);
|
||||
}
|
||||
if (parent_nodes && this.renderer.options.hydratable) {
|
||||
if (if_exists_condition) {
|
||||
block.chunks.claim.push(b`if (${if_exists_condition}) ${name}.l(${parent_nodes});`);
|
||||
} else {
|
||||
block.chunks.claim.push(b`${name}.l(${parent_nodes});`);
|
||||
}
|
||||
}
|
||||
if (has_intros || has_outros) {
|
||||
block.chunks.intro.push(b`@transition_in(${name});`);
|
||||
}
|
||||
if (needs_anchor) {
|
||||
block.add_element(
|
||||
/** @type {import('estree').Identifier} */ (anchor),
|
||||
x`@empty()`,
|
||||
parent_nodes && x`@empty()`,
|
||||
parent_node
|
||||
);
|
||||
}
|
||||
this.branches.forEach((branch) => {
|
||||
branch.fragment.render(
|
||||
branch.block,
|
||||
null,
|
||||
/** @type {unknown} */ /** @type {import('estree').Identifier} */ (x`#nodes`)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
* @param {boolean} dynamic
|
||||
* @param {any} opts
|
||||
* @param {DetachingOrNull} detaching
|
||||
*/
|
||||
render_compound(
|
||||
block,
|
||||
parent_node,
|
||||
_parent_nodes,
|
||||
dynamic,
|
||||
{ name, anchor, has_else, if_exists_condition, has_transitions },
|
||||
detaching
|
||||
) {
|
||||
const select_block_type = this.renderer.component.get_unique_name('select_block_type');
|
||||
const current_block_type = block.get_unique_name('current_block_type');
|
||||
const need_select_block_ctx = this.branches.some((branch) => branch.get_ctx_name);
|
||||
const select_block_ctx = need_select_block_ctx
|
||||
? block.get_unique_name('select_block_ctx')
|
||||
: null;
|
||||
const if_ctx = select_block_ctx ? x`${select_block_ctx}(#ctx, ${current_block_type})` : x`#ctx`;
|
||||
const get_block = has_else
|
||||
? x`${current_block_type}(${if_ctx})`
|
||||
: x`${current_block_type} && ${current_block_type}(${if_ctx})`;
|
||||
if (this.needs_update) {
|
||||
block.chunks.init.push(b`
|
||||
function ${select_block_type}(#ctx, #dirty) {
|
||||
${this.branches.map(({ dependencies, condition, snippet }) => {
|
||||
return b`${
|
||||
snippet && dependencies.length > 0
|
||||
? b`if (${block.renderer.dirty(dependencies)}) ${condition} = null;`
|
||||
: null
|
||||
}`;
|
||||
})}
|
||||
${this.branches.map(({ condition, snippet, block }) =>
|
||||
condition
|
||||
? b`
|
||||
${snippet && b`if (${condition} == null) ${condition} = !!${snippet}`}
|
||||
if (${condition}) return ${block.name};`
|
||||
: b`return ${block.name};`
|
||||
)}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.init.push(b`
|
||||
function ${select_block_type}(#ctx, #dirty) {
|
||||
${this.branches.map(({ condition, snippet, block }) =>
|
||||
condition
|
||||
? b`if (${snippet || condition}) return ${block.name};`
|
||||
: b`return ${block.name};`
|
||||
)}
|
||||
}
|
||||
`);
|
||||
}
|
||||
if (need_select_block_ctx) {
|
||||
// if all branches needs create a context
|
||||
if (this.branches.every((branch) => branch.get_ctx_name)) {
|
||||
block.chunks.init.push(b`
|
||||
function ${select_block_ctx}(#ctx, #type) {
|
||||
${this.branches
|
||||
.map(({ condition, get_ctx_name, block }) => {
|
||||
return condition
|
||||
? b`if (#type === ${block.name}) return ${get_ctx_name}(#ctx);`
|
||||
: b`return ${get_ctx_name}(#ctx);`;
|
||||
})
|
||||
.filter(Boolean)}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
// when not all branches need to create a new context,
|
||||
// this code is simpler
|
||||
block.chunks.init.push(b`
|
||||
function ${select_block_ctx}(#ctx, #type) {
|
||||
${this.branches
|
||||
.map(({ get_ctx_name, block }) => {
|
||||
return get_ctx_name
|
||||
? b`if (#type === ${block.name}) return ${get_ctx_name}(#ctx);`
|
||||
: null;
|
||||
})
|
||||
.filter(Boolean)}
|
||||
return #ctx;
|
||||
}
|
||||
`);
|
||||
}
|
||||
}
|
||||
block.chunks.init.push(b`
|
||||
let ${current_block_type} = ${select_block_type}(#ctx, ${this.renderer.get_initial_dirty()});
|
||||
let ${name} = ${get_block};
|
||||
`);
|
||||
const initial_mount_node = parent_node || '#target';
|
||||
const anchor_node = parent_node ? 'null' : '#anchor';
|
||||
if (if_exists_condition) {
|
||||
block.chunks.mount.push(
|
||||
b`if (${if_exists_condition}) ${name}.m(${initial_mount_node}, ${anchor_node});`
|
||||
);
|
||||
} else {
|
||||
block.chunks.mount.push(b`${name}.m(${initial_mount_node}, ${anchor_node});`);
|
||||
}
|
||||
if (this.needs_update) {
|
||||
const update_mount_node = this.get_update_mount_node(anchor);
|
||||
const change_block = b`
|
||||
${if_exists_condition ? b`if (${if_exists_condition}) ${name}.d(1)` : b`${name}.d(1)`};
|
||||
${name} = ${get_block};
|
||||
if (${name}) {
|
||||
${name}.c();
|
||||
${has_transitions && b`@transition_in(${name}, 1);`}
|
||||
${name}.m(${update_mount_node}, ${anchor});
|
||||
}
|
||||
`;
|
||||
if (dynamic) {
|
||||
block.chunks.update.push(b`
|
||||
if (${current_block_type} === (${current_block_type} = ${select_block_type}(#ctx, #dirty)) && ${name}) {
|
||||
${name}.p(${if_ctx}, #dirty);
|
||||
} else {
|
||||
${change_block}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(b`
|
||||
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(#ctx, #dirty))) {
|
||||
${change_block}
|
||||
}
|
||||
`);
|
||||
}
|
||||
} else if (dynamic) {
|
||||
if (if_exists_condition) {
|
||||
block.chunks.update.push(b`if (${if_exists_condition}) ${name}.p(${if_ctx}, #dirty);`);
|
||||
} else {
|
||||
block.chunks.update.push(b`${name}.p(${if_ctx}, #dirty);`);
|
||||
}
|
||||
}
|
||||
if (if_exists_condition) {
|
||||
block.chunks.destroy.push(b`
|
||||
if (${if_exists_condition}) {
|
||||
${name}.d(${detaching});
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.destroy.push(b`
|
||||
${name}.d(${detaching});
|
||||
`);
|
||||
}
|
||||
}
|
||||
// if any of the siblings have outros, we need to keep references to the blocks
|
||||
// (TODO does this only apply to bidi transitions?)
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
* @param {boolean} dynamic
|
||||
* @param {any} opts
|
||||
* @param {DetachingOrNull} detaching
|
||||
*/
|
||||
render_compound_with_outros(
|
||||
block,
|
||||
parent_node,
|
||||
_parent_nodes,
|
||||
dynamic,
|
||||
{ name, anchor, has_else, has_transitions, if_exists_condition },
|
||||
detaching
|
||||
) {
|
||||
const select_block_type = this.renderer.component.get_unique_name('select_block_type');
|
||||
const current_block_type_index = block.get_unique_name('current_block_type_index');
|
||||
const previous_block_index = block.get_unique_name('previous_block_index');
|
||||
const if_block_creators = block.get_unique_name('if_block_creators');
|
||||
const if_blocks = block.get_unique_name('if_blocks');
|
||||
const need_select_block_ctx = this.branches.some((branch) => branch.get_ctx_name);
|
||||
const select_block_ctx = need_select_block_ctx
|
||||
? block.get_unique_name('select_block_ctx')
|
||||
: null;
|
||||
const if_ctx = select_block_ctx
|
||||
? x`${select_block_ctx}(#ctx, ${current_block_type_index})`
|
||||
: x`#ctx`;
|
||||
const if_current_block_type_index = has_else
|
||||
? (nodes) => nodes
|
||||
: (nodes) => b`if (~${current_block_type_index}) { ${nodes} }`;
|
||||
block.add_variable(current_block_type_index);
|
||||
block.add_variable(name);
|
||||
block.chunks.init.push(b`
|
||||
const ${if_block_creators} = [
|
||||
${this.branches.map((branch) => branch.block.name)}
|
||||
];
|
||||
|
||||
const ${if_blocks} = [];
|
||||
|
||||
${
|
||||
this.needs_update
|
||||
? b`
|
||||
function ${select_block_type}(#ctx, #dirty) {
|
||||
${this.branches.map(({ dependencies, condition, snippet }) => {
|
||||
return b`${
|
||||
snippet && dependencies.length > 0
|
||||
? b`if (${block.renderer.dirty(dependencies)}) ${condition} = null;`
|
||||
: null
|
||||
}`;
|
||||
})}
|
||||
${this.branches.map(({ condition, snippet }, i) =>
|
||||
condition
|
||||
? b`
|
||||
${snippet && b`if (${condition} == null) ${condition} = !!${snippet}`}
|
||||
if (${condition}) return ${i};`
|
||||
: b`return ${i};`
|
||||
)}
|
||||
${!has_else && b`return -1;`}
|
||||
}
|
||||
`
|
||||
: b`
|
||||
function ${select_block_type}(#ctx, #dirty) {
|
||||
${this.branches.map(({ condition, snippet }, i) =>
|
||||
condition ? b`if (${snippet || condition}) return ${i};` : b`return ${i};`
|
||||
)}
|
||||
${!has_else && b`return -1;`}
|
||||
}
|
||||
`
|
||||
}
|
||||
`);
|
||||
if (need_select_block_ctx) {
|
||||
// if all branches needs create a context
|
||||
if (this.branches.every((branch) => branch.get_ctx_name)) {
|
||||
block.chunks.init.push(b`
|
||||
function ${select_block_ctx}(#ctx, #index) {
|
||||
${this.branches
|
||||
.map(({ condition, get_ctx_name }, i) => {
|
||||
return condition
|
||||
? b`if (#index === ${i}) return ${get_ctx_name}(#ctx);`
|
||||
: b`return ${get_ctx_name}(#ctx);`;
|
||||
})
|
||||
.filter(Boolean)}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
// when not all branches need to create a new context,
|
||||
// this code is simpler
|
||||
block.chunks.init.push(b`
|
||||
function ${select_block_ctx}(#ctx, #index) {
|
||||
${this.branches
|
||||
.map(({ get_ctx_name }, i) => {
|
||||
return get_ctx_name ? b`if (#index === ${i}) return ${get_ctx_name}(#ctx);` : null;
|
||||
})
|
||||
.filter(Boolean)}
|
||||
return #ctx;
|
||||
}
|
||||
`);
|
||||
}
|
||||
}
|
||||
if (has_else) {
|
||||
block.chunks.init.push(b`
|
||||
${current_block_type_index} = ${select_block_type}(#ctx, ${this.renderer.get_initial_dirty()});
|
||||
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](${if_ctx});
|
||||
`);
|
||||
} else {
|
||||
block.chunks.init.push(b`
|
||||
if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.renderer.get_initial_dirty()}))) {
|
||||
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](${if_ctx});
|
||||
}
|
||||
`);
|
||||
}
|
||||
const initial_mount_node = parent_node || '#target';
|
||||
const anchor_node = parent_node ? 'null' : '#anchor';
|
||||
block.chunks.mount.push(
|
||||
if_current_block_type_index(
|
||||
b`${if_blocks}[${current_block_type_index}].m(${initial_mount_node}, ${anchor_node});`
|
||||
)
|
||||
);
|
||||
if (this.needs_update) {
|
||||
const update_mount_node = this.get_update_mount_node(anchor);
|
||||
const destroy_old_block = b`
|
||||
@group_outros();
|
||||
@transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => {
|
||||
${if_blocks}[${previous_block_index}] = null;
|
||||
});
|
||||
@check_outros();
|
||||
`;
|
||||
const create_new_block = b`
|
||||
${name} = ${if_blocks}[${current_block_type_index}];
|
||||
if (!${name}) {
|
||||
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](${if_ctx});
|
||||
${name}.c();
|
||||
} else {
|
||||
${dynamic && b`${name}.p(${if_ctx}, #dirty);`}
|
||||
}
|
||||
${has_transitions && b`@transition_in(${name}, 1);`}
|
||||
${name}.m(${update_mount_node}, ${anchor});
|
||||
`;
|
||||
const change_block = has_else
|
||||
? b`
|
||||
${destroy_old_block}
|
||||
|
||||
${create_new_block}
|
||||
`
|
||||
: b`
|
||||
if (${name}) {
|
||||
${destroy_old_block}
|
||||
}
|
||||
|
||||
if (~${current_block_type_index}) {
|
||||
${create_new_block}
|
||||
} else {
|
||||
${name} = null;
|
||||
}
|
||||
`;
|
||||
block.chunks.update.push(b`
|
||||
let ${previous_block_index} = ${current_block_type_index};
|
||||
${current_block_type_index} = ${select_block_type}(#ctx, #dirty);
|
||||
`);
|
||||
if (dynamic) {
|
||||
block.chunks.update.push(b`
|
||||
if (${current_block_type_index} === ${previous_block_index}) {
|
||||
${if_current_block_type_index(b`${if_blocks}[${current_block_type_index}].p(${if_ctx}, #dirty);`)}
|
||||
} else {
|
||||
${change_block}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(b`
|
||||
if (${current_block_type_index} !== ${previous_block_index}) {
|
||||
${change_block}
|
||||
}
|
||||
`);
|
||||
}
|
||||
} else if (dynamic) {
|
||||
if (if_exists_condition) {
|
||||
block.chunks.update.push(b`if (${if_exists_condition}) ${name}.p(${if_ctx}, #dirty);`);
|
||||
} else {
|
||||
block.chunks.update.push(b`${name}.p(${if_ctx}, #dirty);`);
|
||||
}
|
||||
}
|
||||
block.chunks.destroy.push(
|
||||
if_current_block_type_index(b`${if_blocks}[${current_block_type_index}].d(${detaching});`)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
* @param {boolean} dynamic
|
||||
* @param {any} opts
|
||||
* @param {DetachingOrNull} detaching
|
||||
*/
|
||||
render_simple(
|
||||
block,
|
||||
parent_node,
|
||||
_parent_nodes,
|
||||
dynamic,
|
||||
{ name, anchor, if_exists_condition, has_transitions },
|
||||
detaching
|
||||
) {
|
||||
const branch = this.branches[0];
|
||||
const if_ctx = branch.get_ctx_name ? x`${branch.get_ctx_name}(#ctx)` : x`#ctx`;
|
||||
if (branch.snippet) block.add_variable(branch.condition, branch.snippet);
|
||||
block.chunks.init.push(b`
|
||||
let ${name} = ${branch.condition} && ${branch.block.name}(${if_ctx});
|
||||
`);
|
||||
const initial_mount_node = parent_node || '#target';
|
||||
const anchor_node = parent_node ? 'null' : '#anchor';
|
||||
block.chunks.mount.push(b`if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});`);
|
||||
if (branch.dependencies.length > 0) {
|
||||
const update_mount_node = this.get_update_mount_node(anchor);
|
||||
const enter = b`
|
||||
if (${name}) {
|
||||
${dynamic && b`${name}.p(${if_ctx}, #dirty);`}
|
||||
${
|
||||
has_transitions &&
|
||||
b`if (${block.renderer.dirty(branch.dependencies)}) {
|
||||
@transition_in(${name}, 1);
|
||||
}`
|
||||
}
|
||||
} else {
|
||||
${name} = ${branch.block.name}(${if_ctx});
|
||||
${name}.c();
|
||||
${has_transitions && b`@transition_in(${name}, 1);`}
|
||||
${name}.m(${update_mount_node}, ${anchor});
|
||||
}
|
||||
`;
|
||||
if (branch.snippet) {
|
||||
block.chunks.update.push(
|
||||
b`if (${block.renderer.dirty(branch.dependencies)}) ${branch.condition} = ${
|
||||
branch.snippet
|
||||
}`
|
||||
);
|
||||
}
|
||||
// no `p()` here — we don't want to update outroing nodes,
|
||||
// as that will typically result in glitching
|
||||
if (branch.block.has_outro_method) {
|
||||
block.chunks.update.push(b`
|
||||
if (${branch.condition}) {
|
||||
${enter}
|
||||
} else if (${name}) {
|
||||
@group_outros();
|
||||
@transition_out(${name}, 1, 1, () => {
|
||||
${name} = null;
|
||||
});
|
||||
@check_outros();
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(b`
|
||||
if (${branch.condition}) {
|
||||
${enter}
|
||||
} else if (${name}) {
|
||||
${name}.d(1);
|
||||
${name} = null;
|
||||
}
|
||||
`);
|
||||
}
|
||||
} else if (dynamic) {
|
||||
block.chunks.update.push(b`
|
||||
if (${branch.condition}) ${name}.p(${if_ctx}, #dirty);
|
||||
`);
|
||||
}
|
||||
if (if_exists_condition) {
|
||||
block.chunks.destroy.push(b`
|
||||
if (${if_exists_condition}) ${name}.d(${detaching});
|
||||
`);
|
||||
} else {
|
||||
block.chunks.destroy.push(b`
|
||||
${name}.d(${detaching});
|
||||
`);
|
||||
}
|
||||
}
|
||||
}
|
666
node_modules/svelte/src/compiler/compile/render_dom/wrappers/InlineComponent/index.js
generated
vendored
Normal file
666
node_modules/svelte/src/compiler/compile/render_dom/wrappers/InlineComponent/index.js
generated
vendored
Normal file
@ -0,0 +1,666 @@
|
||||
import { b, p, x } from 'code-red';
|
||||
import { extract_ignores_above_node } from '../../../../utils/extract_svelte_ignore.js';
|
||||
import { sanitize } from '../../../../utils/names.js';
|
||||
import { namespaces } from '../../../../utils/namespaces.js';
|
||||
import compiler_warnings from '../../../compiler_warnings.js';
|
||||
import add_to_set from '../../../utils/add_to_set.js';
|
||||
import { string_to_member_expression } from '../../../utils/string_to_member_expression.js';
|
||||
import BindingWrapper from '../Element/Binding.js';
|
||||
import EventHandler from '../Element/EventHandler.js';
|
||||
import SlotTemplateWrapper from '../SlotTemplate.js';
|
||||
import Wrapper from '../shared/Wrapper.js';
|
||||
import bind_this from '../shared/bind_this.js';
|
||||
import is_dynamic from '../shared/is_dynamic.js';
|
||||
import { is_head } from '../shared/is_head.js';
|
||||
import mark_each_block_bindings from '../shared/mark_each_block_bindings.js';
|
||||
|
||||
const regex_invalid_variable_identifier_characters = /[^a-zA-Z_$]/g;
|
||||
|
||||
/** @extends Wrapper<import('../../../nodes/InlineComponent.js').default> */
|
||||
export default class InlineComponentWrapper extends Wrapper {
|
||||
/**
|
||||
* @typedef {{
|
||||
* block: import('../../Block.js').default;
|
||||
* scope: import('../../../nodes/shared/TemplateScope.js').default;
|
||||
* get_context?: import('estree').Node;
|
||||
* get_changes?: import('estree').Node;
|
||||
* }} SlotDefinition
|
||||
*/
|
||||
|
||||
/** @type {Map<string, SlotDefinition>} */
|
||||
slots = new Map();
|
||||
|
||||
/** @type {import('../Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {Array<Wrapper | import('../Fragment.js').default>} */
|
||||
children = [];
|
||||
|
||||
/**
|
||||
* @param {import('../../Renderer.js').default} renderer
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('../shared/Wrapper.js').default} parent
|
||||
* @param {import('../../../nodes/InlineComponent.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('../shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
if (this.node.expression) {
|
||||
block.add_dependencies(this.node.expression.dependencies);
|
||||
}
|
||||
this.node.attributes.forEach((attr) => {
|
||||
block.add_dependencies(attr.dependencies);
|
||||
});
|
||||
this.node.bindings.forEach((binding) => {
|
||||
if (binding.is_contextual) {
|
||||
mark_each_block_bindings(this, binding);
|
||||
}
|
||||
block.add_dependencies(binding.expression.dependencies);
|
||||
});
|
||||
this.node.handlers.forEach((handler) => {
|
||||
if (handler.expression) {
|
||||
block.add_dependencies(handler.expression.dependencies);
|
||||
}
|
||||
});
|
||||
this.node.css_custom_properties.forEach((attr) => {
|
||||
block.add_dependencies(attr.dependencies);
|
||||
});
|
||||
this.var = {
|
||||
type: /** @type {const} */ ('Identifier'),
|
||||
name: (this.node.name === 'svelte:self'
|
||||
? renderer.component.name.name
|
||||
: this.node.name === 'svelte:component'
|
||||
? 'switch_instance'
|
||||
: sanitize(this.node.name)
|
||||
).toLowerCase()
|
||||
};
|
||||
if (this.node.children.length) {
|
||||
this.children = this.node.children.map(
|
||||
(child) =>
|
||||
new SlotTemplateWrapper(
|
||||
renderer,
|
||||
block,
|
||||
this,
|
||||
/** @type {import('../../../nodes/SlotTemplate.js').default} */ (child),
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
)
|
||||
);
|
||||
}
|
||||
block.add_outro();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {SlotDefinition} slot_definition
|
||||
*/
|
||||
set_slot(name, slot_definition) {
|
||||
if (this.slots.has(name)) {
|
||||
if (name === 'default') {
|
||||
throw new Error('Found elements without slot attribute when using slot="default"');
|
||||
}
|
||||
throw new Error(`Duplicate slot name "${name}" in <${this.node.name}>`);
|
||||
}
|
||||
this.slots.set(name, slot_definition);
|
||||
}
|
||||
warn_if_reactive() {
|
||||
let { name } = this.node;
|
||||
const top = name.split('.')[0]; // <T.foo/> etc. should check for T instead of "T.foo"
|
||||
const variable = this.renderer.component.var_lookup.get(top);
|
||||
if (!variable) {
|
||||
return;
|
||||
}
|
||||
const ignores = extract_ignores_above_node(this.node);
|
||||
this.renderer.component.push_ignores(ignores);
|
||||
if (
|
||||
variable.reassigned ||
|
||||
variable.export_name || // or a prop
|
||||
variable.mutated
|
||||
) {
|
||||
this.renderer.component.warn(this.node, compiler_warnings.reactive_component(name));
|
||||
}
|
||||
this.renderer.component.pop_ignores();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
this.warn_if_reactive();
|
||||
const { renderer } = this;
|
||||
const { component } = renderer;
|
||||
const name = this.var;
|
||||
block.add_variable(name);
|
||||
const component_opts = /** @type {import('estree').ObjectExpression} */ (x`{}`);
|
||||
|
||||
/** @type {Array<import('estree').Node | import('estree').Node[]>} */
|
||||
const statements = [];
|
||||
|
||||
/** @type {Array<import('estree').Node | import('estree').Node[]>} */
|
||||
const updates = [];
|
||||
this.children.forEach((child) => {
|
||||
this.renderer.add_to_context('$$scope', true);
|
||||
child.render(block, null, /** @type {import('estree').Identifier} */ (x`#nodes`));
|
||||
});
|
||||
|
||||
/** @type {import('estree').Identifier | undefined} */
|
||||
let props;
|
||||
const name_changes = block.get_unique_name(`${name.name}_changes`);
|
||||
const uses_spread = !!this.node.attributes.find((a) => a.is_spread);
|
||||
// removing empty slot
|
||||
for (const slot of this.slots.keys()) {
|
||||
if (!this.slots.get(slot).block.has_content()) {
|
||||
this.renderer.remove_block(this.slots.get(slot).block);
|
||||
this.slots.delete(slot);
|
||||
}
|
||||
}
|
||||
const has_css_custom_properties = this.node.css_custom_properties.length > 0;
|
||||
const is_svg_namespace = this.node.namespace === namespaces.svg;
|
||||
const css_custom_properties_wrapper_element = is_svg_namespace ? 'g' : 'div';
|
||||
const css_custom_properties_wrapper = has_css_custom_properties
|
||||
? block.get_unique_name(css_custom_properties_wrapper_element)
|
||||
: null;
|
||||
if (has_css_custom_properties) {
|
||||
block.add_variable(css_custom_properties_wrapper);
|
||||
}
|
||||
const initial_props =
|
||||
this.slots.size > 0
|
||||
? [
|
||||
p`$$slots: {
|
||||
${Array.from(this.slots).map(([name, slot]) => {
|
||||
return p`${name}: [${slot.block.name}, ${slot.get_context || null}, ${
|
||||
slot.get_changes || null
|
||||
}]`;
|
||||
})}
|
||||
}`,
|
||||
p`$$scope: {
|
||||
ctx: #ctx
|
||||
}`
|
||||
]
|
||||
: [];
|
||||
const attribute_object = uses_spread
|
||||
? x`{ ${initial_props} }`
|
||||
: x`{
|
||||
${this.node.attributes.map((attr) => p`${attr.name}: ${attr.get_value(block)}`)},
|
||||
${initial_props}
|
||||
}`;
|
||||
if (this.node.attributes.length || this.node.bindings.length || initial_props.length) {
|
||||
if (!uses_spread && this.node.bindings.length === 0) {
|
||||
component_opts.properties.push(p`props: ${attribute_object}`);
|
||||
} else {
|
||||
props = block.get_unique_name(`${name.name}_props`);
|
||||
component_opts.properties.push(p`props: ${props}`);
|
||||
}
|
||||
}
|
||||
if (component.compile_options.dev) {
|
||||
// TODO this is a terrible hack, but without it the component
|
||||
// will complain that options.target is missing. This would
|
||||
// work better if components had separate public and private
|
||||
// APIs
|
||||
component_opts.properties.push(p`$$inline: true`);
|
||||
}
|
||||
const fragment_dependencies = new Set(this.slots.size ? ['$$scope'] : []);
|
||||
this.slots.forEach((slot) => {
|
||||
slot.block.dependencies.forEach((name) => {
|
||||
const is_let = slot.scope.is_let(name);
|
||||
const variable = renderer.component.var_lookup.get(name);
|
||||
if (is_let || is_dynamic(variable)) fragment_dependencies.add(name);
|
||||
});
|
||||
});
|
||||
const dynamic_attributes = this.node.attributes.filter((a) => a.get_dependencies().length > 0);
|
||||
if (
|
||||
!uses_spread &&
|
||||
(dynamic_attributes.length > 0 ||
|
||||
this.node.bindings.length > 0 ||
|
||||
fragment_dependencies.size > 0)
|
||||
) {
|
||||
updates.push(b`const ${name_changes} = {};`);
|
||||
}
|
||||
if (this.node.attributes.length) {
|
||||
if (uses_spread) {
|
||||
const levels = block.get_unique_name(`${this.var.name}_spread_levels`);
|
||||
const initial_props = [];
|
||||
const changes = [];
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const all_dependencies = new Set();
|
||||
this.node.attributes.forEach((attr) => {
|
||||
add_to_set(all_dependencies, attr.dependencies);
|
||||
});
|
||||
this.node.attributes.forEach((attr, i) => {
|
||||
const { name, dependencies } = attr;
|
||||
const condition =
|
||||
dependencies.size > 0 && dependencies.size !== all_dependencies.size
|
||||
? renderer.dirty(Array.from(dependencies))
|
||||
: null;
|
||||
const unchanged = dependencies.size === 0;
|
||||
|
||||
/** @type {import('estree').Node | ReturnType<typeof x>} */
|
||||
let change_object;
|
||||
if (attr.is_spread) {
|
||||
const value = attr.expression.manipulate(block);
|
||||
initial_props.push(value);
|
||||
let value_object = value;
|
||||
if (attr.expression.node.type !== 'ObjectExpression') {
|
||||
value_object = x`@get_spread_object(${value})`;
|
||||
}
|
||||
change_object = value_object;
|
||||
} else {
|
||||
const obj = x`{ ${name}: ${attr.get_value(block)} }`;
|
||||
initial_props.push(obj);
|
||||
change_object = obj;
|
||||
}
|
||||
changes.push(
|
||||
unchanged
|
||||
? x`${levels}[${i}]`
|
||||
: condition
|
||||
? x`${condition} && ${change_object}`
|
||||
: change_object
|
||||
);
|
||||
});
|
||||
block.chunks.init.push(b`
|
||||
const ${levels} = [
|
||||
${initial_props}
|
||||
];
|
||||
`);
|
||||
statements.push(b`
|
||||
for (let #i = 0; #i < ${levels}.length; #i += 1) {
|
||||
${props} = @assign(${props}, ${levels}[#i]);
|
||||
}
|
||||
`);
|
||||
if (all_dependencies.size) {
|
||||
const condition = renderer.dirty(Array.from(all_dependencies));
|
||||
if (this.node.name === 'svelte:component') {
|
||||
// statements will become switch_props function body
|
||||
// rewrite last statement, add props update logic
|
||||
statements[statements.length - 1] = b`
|
||||
if (#dirty !== undefined && ${condition}) {
|
||||
${props} = @get_spread_update(${levels}, [
|
||||
${changes}
|
||||
]);
|
||||
} else {
|
||||
for (let #i = 0; #i < ${levels}.length; #i += 1) {
|
||||
${props} = @assign(${props}, ${levels}[#i]);
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
updates.push(b`
|
||||
const ${name_changes} = ${condition} ? @get_spread_update(${levels}, [
|
||||
${changes}
|
||||
]) : {}
|
||||
`);
|
||||
} else {
|
||||
updates.push(b`
|
||||
const ${name_changes} = {};
|
||||
`);
|
||||
}
|
||||
} else {
|
||||
dynamic_attributes.forEach((attribute) => {
|
||||
const dependencies = attribute.get_dependencies();
|
||||
if (dependencies.length > 0) {
|
||||
const condition = renderer.dirty(dependencies);
|
||||
updates.push(b`
|
||||
if (${condition}) ${name_changes}.${attribute.name} = ${attribute.get_value(block)};
|
||||
`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (fragment_dependencies.size > 0) {
|
||||
updates.push(b`
|
||||
if (${renderer.dirty(Array.from(fragment_dependencies))}) {
|
||||
${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
|
||||
}`);
|
||||
}
|
||||
const munged_bindings = this.node.bindings.map((binding) => {
|
||||
component.has_reactive_assignments = true;
|
||||
if (binding.name === 'this') {
|
||||
return bind_this(component, block, new BindingWrapper(block, binding, this), this.var);
|
||||
}
|
||||
const id = component.get_unique_name(`${this.var.name}_${binding.name}_binding`);
|
||||
renderer.add_to_context(id.name);
|
||||
const callee = renderer.reference(id);
|
||||
const updating = block.get_unique_name(`updating_${binding.name}`);
|
||||
block.add_variable(updating);
|
||||
const snippet = binding.expression.manipulate(block);
|
||||
statements.push(b`
|
||||
if (${snippet} !== void 0) {
|
||||
${props}.${binding.name} = ${snippet};
|
||||
}`);
|
||||
updates.push(b`
|
||||
if (!${updating} && ${renderer.dirty(Array.from(binding.expression.dependencies))}) {
|
||||
${updating} = true;
|
||||
${name_changes}.${binding.name} = ${snippet};
|
||||
@add_flush_callback(() => ${updating} = false);
|
||||
}
|
||||
`);
|
||||
const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
|
||||
const dependencies = Array.from(binding.expression.dependencies);
|
||||
let lhs = binding.raw_expression;
|
||||
if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
|
||||
// bind:x={y} — we can't just do `y = x`, we need to
|
||||
// to `array[index] = x;
|
||||
const { name } = binding.expression.node;
|
||||
const { object, property, snippet } = block.bindings.get(name);
|
||||
lhs = snippet;
|
||||
contextual_dependencies.push(object.name, property.name);
|
||||
}
|
||||
|
||||
/** @type {import('estree').Identifier[]} */
|
||||
const params = [/** @type {import('estree').Identifier} */ (x`#value`)];
|
||||
const args = [x`#value`];
|
||||
if (contextual_dependencies.length > 0) {
|
||||
contextual_dependencies.forEach((name) => {
|
||||
params.push({
|
||||
type: 'Identifier',
|
||||
name
|
||||
});
|
||||
renderer.add_to_context(name, true);
|
||||
args.push(renderer.reference(name));
|
||||
});
|
||||
block.maintain_context = true; // TODO put this somewhere more logical
|
||||
}
|
||||
block.chunks.init.push(b`
|
||||
function ${id}(#value) {
|
||||
${callee}(${args});
|
||||
}
|
||||
`);
|
||||
let invalidate_binding = b`
|
||||
${lhs} = #value;
|
||||
${renderer.invalidate(dependencies[0])};
|
||||
`;
|
||||
if (binding.expression.node.type === 'MemberExpression') {
|
||||
invalidate_binding = b`
|
||||
if ($$self.$$.not_equal(${lhs}, #value)) {
|
||||
${invalidate_binding}
|
||||
}
|
||||
`;
|
||||
}
|
||||
const body = b`
|
||||
function ${id}(${params}) {
|
||||
${invalidate_binding}
|
||||
}
|
||||
`;
|
||||
component.partly_hoisted.push(body);
|
||||
return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
|
||||
});
|
||||
const munged_handlers = this.node.handlers.map((handler) => {
|
||||
const event_handler = new EventHandler(handler, this);
|
||||
let snippet = event_handler.get_snippet(block);
|
||||
if (handler.modifiers.has('once')) snippet = x`@once(${snippet})`;
|
||||
return b`${name}.$on("${handler.name}", ${snippet});`;
|
||||
});
|
||||
const mount_target = has_css_custom_properties
|
||||
? css_custom_properties_wrapper
|
||||
: parent_node || '#target';
|
||||
const mount_anchor = has_css_custom_properties ? 'null' : parent_node ? 'null' : '#anchor';
|
||||
const to_claim = parent_nodes && this.renderer.options.hydratable;
|
||||
let claim_nodes = parent_nodes;
|
||||
if (this.node.name === 'svelte:component') {
|
||||
const switch_value = block.get_unique_name('switch_value');
|
||||
const switch_props = block.get_unique_name('switch_props');
|
||||
const snippet = this.node.expression.manipulate(block);
|
||||
const dependencies = this.node.expression.dynamic_dependencies();
|
||||
if (has_css_custom_properties) {
|
||||
this.set_css_custom_properties(
|
||||
block,
|
||||
css_custom_properties_wrapper,
|
||||
css_custom_properties_wrapper_element,
|
||||
is_svg_namespace
|
||||
);
|
||||
}
|
||||
block.chunks.init.push(b`
|
||||
var ${switch_value} = ${snippet};
|
||||
|
||||
function ${switch_props}(#ctx, #dirty) {
|
||||
${
|
||||
(this.node.attributes.length > 0 || this.node.bindings.length > 0) &&
|
||||
b`
|
||||
${props && b`let ${props} = ${attribute_object};`}`
|
||||
}
|
||||
${statements}
|
||||
return ${component_opts};
|
||||
}
|
||||
|
||||
if (${switch_value}) {
|
||||
${name} = @construct_svelte_component(${switch_value}, ${switch_props}(#ctx));
|
||||
|
||||
${munged_bindings}
|
||||
${munged_handlers}
|
||||
}
|
||||
`);
|
||||
block.chunks.create.push(b`if (${name}) @create_component(${name}.$$.fragment);`);
|
||||
if (css_custom_properties_wrapper)
|
||||
this.create_css_custom_properties_wrapper_mount_chunk(
|
||||
block,
|
||||
parent_node,
|
||||
css_custom_properties_wrapper
|
||||
);
|
||||
block.chunks.mount.push(
|
||||
b`if (${name}) @mount_component(${name}, ${mount_target}, ${mount_anchor});`
|
||||
);
|
||||
if (to_claim) {
|
||||
if (css_custom_properties_wrapper)
|
||||
claim_nodes = this.create_css_custom_properties_wrapper_claim_chunk(
|
||||
block,
|
||||
claim_nodes,
|
||||
css_custom_properties_wrapper,
|
||||
css_custom_properties_wrapper_element,
|
||||
is_svg_namespace
|
||||
);
|
||||
block.chunks.claim.push(
|
||||
b`if (${name}) @claim_component(${name}.$$.fragment, ${claim_nodes});`
|
||||
);
|
||||
}
|
||||
const tmp_anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
|
||||
const anchor = has_css_custom_properties ? 'null' : tmp_anchor;
|
||||
const update_mount_node = has_css_custom_properties
|
||||
? css_custom_properties_wrapper
|
||||
: this.get_update_mount_node(tmp_anchor);
|
||||
const update_insert =
|
||||
css_custom_properties_wrapper &&
|
||||
(tmp_anchor.name !== 'null'
|
||||
? b`@insert(${tmp_anchor}.parentNode, ${css_custom_properties_wrapper}, ${tmp_anchor});`
|
||||
: b`@insert(${parent_node}, ${css_custom_properties_wrapper}, ${tmp_anchor});`);
|
||||
let update_condition = x`${switch_value} !== (${switch_value} = ${snippet})`;
|
||||
if (dependencies.length > 0) {
|
||||
update_condition = x`${block.renderer.dirty(dependencies)} && ${update_condition}`;
|
||||
}
|
||||
block.chunks.update.push(b`
|
||||
if (${update_condition}) {
|
||||
if (${name}) {
|
||||
@group_outros();
|
||||
const old_component = ${name};
|
||||
@transition_out(old_component.$$.fragment, 1, 0, () => {
|
||||
@destroy_component(old_component, 1);
|
||||
${has_css_custom_properties ? b`@detach(${update_mount_node})` : null}
|
||||
});
|
||||
@check_outros();
|
||||
}
|
||||
|
||||
if (${switch_value}) {
|
||||
${update_insert}
|
||||
${name} = @construct_svelte_component(${switch_value}, ${switch_props}(#ctx, #dirty));
|
||||
|
||||
${munged_bindings}
|
||||
${munged_handlers}
|
||||
|
||||
@create_component(${name}.$$.fragment);
|
||||
@transition_in(${name}.$$.fragment, 1);
|
||||
@mount_component(${name}, ${update_mount_node}, ${anchor});
|
||||
} else {
|
||||
${name} = null;
|
||||
}
|
||||
} else if (${switch_value}) {
|
||||
${updates}
|
||||
${updates.length > 0 && b`${name}.$set(${name_changes});`}
|
||||
}
|
||||
`);
|
||||
block.chunks.intro.push(b`
|
||||
if (${name}) @transition_in(${name}.$$.fragment, #local);
|
||||
`);
|
||||
block.chunks.outro.push(b`if (${name}) @transition_out(${name}.$$.fragment, #local);`);
|
||||
block.chunks.destroy.push(
|
||||
b`if (${name}) @destroy_component(${name}, ${parent_node ? null : 'detaching'});`
|
||||
);
|
||||
} else {
|
||||
const expression =
|
||||
this.node.name === 'svelte:self'
|
||||
? component.name
|
||||
: this.renderer.reference(string_to_member_expression(this.node.name));
|
||||
block.chunks.init.push(b`
|
||||
${
|
||||
(this.node.attributes.length > 0 || this.node.bindings.length > 0) &&
|
||||
b`
|
||||
${props && b`let ${props} = ${attribute_object};`}`
|
||||
}
|
||||
${statements}
|
||||
${name} = new ${expression}(${component_opts});
|
||||
|
||||
${munged_bindings}
|
||||
${munged_handlers}
|
||||
`);
|
||||
if (has_css_custom_properties) {
|
||||
this.set_css_custom_properties(
|
||||
block,
|
||||
css_custom_properties_wrapper,
|
||||
css_custom_properties_wrapper_element,
|
||||
is_svg_namespace
|
||||
);
|
||||
}
|
||||
block.chunks.create.push(b`@create_component(${name}.$$.fragment);`);
|
||||
if (css_custom_properties_wrapper)
|
||||
this.create_css_custom_properties_wrapper_mount_chunk(
|
||||
block,
|
||||
parent_node,
|
||||
css_custom_properties_wrapper
|
||||
);
|
||||
block.chunks.mount.push(b`@mount_component(${name}, ${mount_target}, ${mount_anchor});`);
|
||||
if (to_claim) {
|
||||
if (css_custom_properties_wrapper)
|
||||
claim_nodes = this.create_css_custom_properties_wrapper_claim_chunk(
|
||||
block,
|
||||
claim_nodes,
|
||||
css_custom_properties_wrapper,
|
||||
css_custom_properties_wrapper_element,
|
||||
is_svg_namespace
|
||||
);
|
||||
block.chunks.claim.push(b`@claim_component(${name}.$$.fragment, ${claim_nodes});`);
|
||||
}
|
||||
block.chunks.intro.push(b`
|
||||
@transition_in(${name}.$$.fragment, #local);
|
||||
`);
|
||||
if (updates.length) {
|
||||
block.chunks.update.push(b`
|
||||
${updates}
|
||||
${name}.$set(${name_changes});
|
||||
`);
|
||||
}
|
||||
block.chunks.destroy.push(b`
|
||||
@destroy_component(${name}, ${parent_node ? null : 'detaching'});
|
||||
`);
|
||||
block.chunks.outro.push(b`@transition_out(${name}.$$.fragment, #local);`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier | null} css_custom_properties_wrapper
|
||||
*/
|
||||
create_css_custom_properties_wrapper_mount_chunk(
|
||||
block,
|
||||
parent_node,
|
||||
css_custom_properties_wrapper
|
||||
) {
|
||||
if (parent_node) {
|
||||
block.chunks.mount.push(b`@append(${parent_node}, ${css_custom_properties_wrapper})`);
|
||||
if (is_head(parent_node)) {
|
||||
block.chunks.destroy.push(b`@detach(${css_custom_properties_wrapper});`);
|
||||
}
|
||||
} else {
|
||||
block.chunks.mount.push(b`@insert(#target, ${css_custom_properties_wrapper}, #anchor);`);
|
||||
// TODO we eventually need to consider what happens to elements
|
||||
// that belong to the same outgroup as an outroing element...
|
||||
block.chunks.destroy.push(
|
||||
b`if (detaching && ${this.var}) @detach(${css_custom_properties_wrapper});`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
* @param {import('estree').Identifier | null} css_custom_properties_wrapper
|
||||
* @param {string} css_custom_properties_wrapper_element
|
||||
* @param {boolean} is_svg_namespace
|
||||
*/
|
||||
create_css_custom_properties_wrapper_claim_chunk(
|
||||
block,
|
||||
parent_nodes,
|
||||
css_custom_properties_wrapper,
|
||||
css_custom_properties_wrapper_element,
|
||||
is_svg_namespace
|
||||
) {
|
||||
const nodes = block.get_unique_name(`${css_custom_properties_wrapper.name}_nodes`);
|
||||
const claim_element = is_svg_namespace ? x`@claim_svg_element` : x`@claim_element`;
|
||||
block.chunks.claim.push(b`
|
||||
${css_custom_properties_wrapper} = ${claim_element}(${parent_nodes}, "${css_custom_properties_wrapper_element.toUpperCase()}", { style: true })
|
||||
var ${nodes} = @children(${css_custom_properties_wrapper});
|
||||
`);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Identifier} css_custom_properties_wrapper
|
||||
* @param {string} css_custom_properties_wrapper_element
|
||||
* @param {boolean} is_svg_namespace
|
||||
*/
|
||||
set_css_custom_properties(
|
||||
block,
|
||||
css_custom_properties_wrapper,
|
||||
css_custom_properties_wrapper_element,
|
||||
is_svg_namespace
|
||||
) {
|
||||
const element = is_svg_namespace ? x`@svg_element` : x`@element`;
|
||||
block.chunks.create.push(
|
||||
b`${css_custom_properties_wrapper} = ${element}("${css_custom_properties_wrapper_element}");`
|
||||
);
|
||||
if (!is_svg_namespace)
|
||||
block.chunks.hydrate.push(
|
||||
b`@set_style(${css_custom_properties_wrapper}, "display", "contents");`
|
||||
);
|
||||
this.node.css_custom_properties.forEach((attr) => {
|
||||
const dependencies = attr.get_dependencies();
|
||||
const should_cache = attr.should_cache();
|
||||
const last =
|
||||
should_cache &&
|
||||
block.get_unique_name(
|
||||
`${attr.name.replace(regex_invalid_variable_identifier_characters, '_')}_last`
|
||||
);
|
||||
if (should_cache) block.add_variable(last);
|
||||
const value = attr.get_value(block);
|
||||
const init = should_cache ? x`${last} = ${value}` : value;
|
||||
block.chunks.hydrate.push(
|
||||
b`@set_style(${css_custom_properties_wrapper}, "${attr.name}", ${init});`
|
||||
);
|
||||
if (dependencies.length > 0) {
|
||||
let condition = block.renderer.dirty(dependencies);
|
||||
if (should_cache) condition = x`${condition} && (${last} !== (${last} = ${value}))`;
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
@set_style(${css_custom_properties_wrapper}, "${attr.name}", ${should_cache ? last : value});
|
||||
}
|
||||
`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
142
node_modules/svelte/src/compiler/compile/render_dom/wrappers/KeyBlock.js
generated
vendored
Normal file
142
node_modules/svelte/src/compiler/compile/render_dom/wrappers/KeyBlock.js
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import create_debugging_comment from './shared/create_debugging_comment.js';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import { b, x } from 'code-red';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/KeyBlock.js').default> */
|
||||
export default class KeyBlockWrapper extends Wrapper {
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {import('../Block.js').default} */
|
||||
block;
|
||||
|
||||
/** @type {string[]} */
|
||||
dependencies;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 'key_block' };
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/KeyBlock.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
this.dependencies = node.expression.dynamic_dependencies();
|
||||
if (this.dependencies.length) {
|
||||
block = block.child({
|
||||
comment: create_debugging_comment(node, renderer.component),
|
||||
name: renderer.component.get_unique_name('create_key_block'),
|
||||
type: 'key'
|
||||
});
|
||||
block.add_dependencies(node.expression.dependencies);
|
||||
renderer.blocks.push(block);
|
||||
}
|
||||
this.block = block;
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.block,
|
||||
node.children,
|
||||
this,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
if (this.dependencies.length === 0) {
|
||||
this.render_static_key(block, parent_node, parent_nodes);
|
||||
} else {
|
||||
this.render_dynamic_key(block, parent_node, parent_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} _block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render_static_key(_block, parent_node, parent_nodes) {
|
||||
this.fragment.render(this.block, parent_node, parent_nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render_dynamic_key(block, parent_node, parent_nodes) {
|
||||
this.fragment.render(
|
||||
this.block,
|
||||
null,
|
||||
/** @type {unknown} */ /** @type {import('estree').Identifier} */ (x`#nodes`)
|
||||
);
|
||||
const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method);
|
||||
const dynamic = this.block.has_update_method;
|
||||
const previous_key = block.get_unique_name('previous_key');
|
||||
const snippet = this.node.expression.manipulate(block);
|
||||
block.add_variable(previous_key, snippet);
|
||||
const not_equal = this.renderer.component.component_options.immutable
|
||||
? x`@not_equal`
|
||||
: x`@safe_not_equal`;
|
||||
const condition = x`${this.renderer.dirty(
|
||||
this.dependencies
|
||||
)} && ${not_equal}(${previous_key}, ${previous_key} = ${snippet})`;
|
||||
block.chunks.init.push(b`
|
||||
let ${this.var} = ${this.block.name}(#ctx);
|
||||
`);
|
||||
block.chunks.create.push(b`${this.var}.c();`);
|
||||
if (this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`${this.var}.l(${parent_nodes});`);
|
||||
}
|
||||
block.chunks.mount.push(
|
||||
b`${this.var}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});`
|
||||
);
|
||||
const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
|
||||
const body = b`
|
||||
${
|
||||
has_transitions
|
||||
? b`
|
||||
@group_outros();
|
||||
@transition_out(${this.var}, 1, 1, @noop);
|
||||
@check_outros();
|
||||
`
|
||||
: b`${this.var}.d(1);`
|
||||
}
|
||||
${this.var} = ${this.block.name}(#ctx);
|
||||
${this.var}.c();
|
||||
${has_transitions && b`@transition_in(${this.var}, 1)`}
|
||||
${this.var}.m(${this.get_update_mount_node(anchor)}, ${anchor});
|
||||
`;
|
||||
if (dynamic) {
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${body}
|
||||
} else {
|
||||
${this.var}.p(#ctx, #dirty);
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${body}
|
||||
}
|
||||
`);
|
||||
}
|
||||
if (has_transitions) {
|
||||
block.chunks.intro.push(b`@transition_in(${this.var})`);
|
||||
block.chunks.outro.push(b`@transition_out(${this.var})`);
|
||||
}
|
||||
block.chunks.destroy.push(b`${this.var}.d(detaching)`);
|
||||
}
|
||||
}
|
66
node_modules/svelte/src/compiler/compile/render_dom/wrappers/MustacheTag.js
generated
vendored
Normal file
66
node_modules/svelte/src/compiler/compile/render_dom/wrappers/MustacheTag.js
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
import Tag from './shared/Tag.js';
|
||||
import { x } from 'code-red';
|
||||
import ElementWrapper from './Element/index.js';
|
||||
|
||||
/** @extends Tag */
|
||||
export default class MustacheTagWrapper extends Tag {
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 't' };
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/MustacheTag.js').default | import('../../nodes/RawMustacheTag.js').default} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
* @param {Record<string, unknown> | undefined} data
|
||||
*/
|
||||
render(block, parent_node, parent_nodes, data) {
|
||||
const contenteditable_attributes =
|
||||
this.parent instanceof ElementWrapper &&
|
||||
this.parent.attributes.filter((a) => a.node.name === 'contenteditable');
|
||||
const spread_attributes =
|
||||
this.parent instanceof ElementWrapper &&
|
||||
this.parent.attributes.filter((a) => a.node.is_spread);
|
||||
|
||||
/** @type {import('estree').Expression | true | undefined} */
|
||||
let contenteditable_attr_value = undefined;
|
||||
if (contenteditable_attributes.length > 0) {
|
||||
const attribute = /** @type {import('./Element/Attribute.js').default} */ (
|
||||
contenteditable_attributes[0]
|
||||
);
|
||||
if ([true, 'true', ''].includes(attribute.node.get_static_value())) {
|
||||
contenteditable_attr_value = true;
|
||||
} else {
|
||||
contenteditable_attr_value = x`${attribute.get_value(block)}`;
|
||||
}
|
||||
} else if (spread_attributes.length > 0 && data.element_data_name) {
|
||||
contenteditable_attr_value = x`${data.element_data_name}['contenteditable']`;
|
||||
}
|
||||
const { init } = this.rename_this_method(block, (value) => {
|
||||
if (contenteditable_attr_value) {
|
||||
if (contenteditable_attr_value === true) {
|
||||
return x`@set_data_contenteditable(${this.var}, ${value})`;
|
||||
} else {
|
||||
return x`@set_data_maybe_contenteditable(${this.var}, ${value}, ${contenteditable_attr_value})`;
|
||||
}
|
||||
} else {
|
||||
return x`@set_data(${this.var}, ${value})`;
|
||||
}
|
||||
});
|
||||
block.add_element(
|
||||
this.var,
|
||||
x`@text(${init})`,
|
||||
parent_nodes && x`@claim_text(${parent_nodes}, ${init})`,
|
||||
parent_node
|
||||
);
|
||||
}
|
||||
}
|
65
node_modules/svelte/src/compiler/compile/render_dom/wrappers/RawMustacheTag.js
generated
vendored
Normal file
65
node_modules/svelte/src/compiler/compile/render_dom/wrappers/RawMustacheTag.js
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
import { namespaces } from '../../../utils/namespaces.js';
|
||||
import { b, x } from 'code-red';
|
||||
import Tag from './shared/Tag.js';
|
||||
import { is_head } from './shared/is_head.js';
|
||||
|
||||
/** @extends Tag */
|
||||
export default class RawMustacheTagWrapper extends Tag {
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 'raw' };
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/MustacheTag.js').default | import('../../nodes/RawMustacheTag.js').default} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, parent_node, _parent_nodes) {
|
||||
const in_head = is_head(parent_node);
|
||||
const can_use_innerhtml = !in_head && parent_node && !this.prev && !this.next;
|
||||
if (can_use_innerhtml && !this.renderer.options.hydratable) {
|
||||
/** @param {import('estree').Node} content */
|
||||
const insert = (content) => b`${parent_node}.innerHTML = ${content};`[0];
|
||||
const { init } = this.rename_this_method(block, (content) => insert(content));
|
||||
block.chunks.mount.push(insert(init));
|
||||
} else {
|
||||
const needs_anchor =
|
||||
in_head ||
|
||||
(this.next ? !this.next.is_dom_node() : !this.parent || !this.parent.is_dom_node());
|
||||
const html_tag = block.get_unique_name('html_tag');
|
||||
const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
|
||||
block.add_variable(html_tag);
|
||||
const { init } = this.rename_this_method(block, (content) => x`${html_tag}.p(${content})`);
|
||||
const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
|
||||
const parent_element = /** @type {import('../../nodes/Element.js').default} */ (
|
||||
this.node.find_nearest(/^Element/)
|
||||
);
|
||||
const is_svg = parent_element && parent_element.namespace === namespaces.svg;
|
||||
block.chunks.create.push(b`${html_tag} = new @HtmlTag(${is_svg ? 'true' : 'false'});`);
|
||||
if (this.renderer.options.hydratable) {
|
||||
block.chunks.claim.push(
|
||||
b`${html_tag} = @claim_html_tag(${_parent_nodes}, ${is_svg ? 'true' : 'false'});`
|
||||
);
|
||||
}
|
||||
block.chunks.hydrate.push(b`${html_tag}.a = ${update_anchor};`);
|
||||
block.chunks.mount.push(
|
||||
b`${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`
|
||||
);
|
||||
if (needs_anchor) {
|
||||
block.add_element(html_anchor, x`@empty()`, x`@empty()`, parent_node);
|
||||
}
|
||||
if (!parent_node || in_head) {
|
||||
block.chunks.destroy.push(b`if (detaching) ${html_tag}.d();`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
243
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Slot.js
generated
vendored
Normal file
243
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Slot.js
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import { b, p, x } from 'code-red';
|
||||
import { sanitize } from '../../../utils/names.js';
|
||||
import add_to_set from '../../utils/add_to_set.js';
|
||||
import get_slot_data from '../../utils/get_slot_data.js';
|
||||
import { is_reserved_keyword } from '../../utils/reserved_keywords.js';
|
||||
import is_dynamic from './shared/is_dynamic.js';
|
||||
import create_debugging_comment from './shared/create_debugging_comment.js';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Slot.js').default> */
|
||||
export default class SlotWrapper extends Wrapper {
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {import('../Block.js').default | null} */
|
||||
fallback = null;
|
||||
|
||||
/** @type {import('../Block.js').default} */
|
||||
slot_block;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var = { type: 'Identifier', name: 'slot' };
|
||||
|
||||
/** @type {Set<string>} */
|
||||
dependencies = new Set(['$$scope']);
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Slot.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
if (this.node.children.length) {
|
||||
this.fallback = block.child({
|
||||
comment: create_debugging_comment(this.node.children[0], this.renderer.component),
|
||||
name: this.renderer.component.get_unique_name('fallback_block'),
|
||||
type: 'fallback'
|
||||
});
|
||||
renderer.blocks.push(this.fallback);
|
||||
}
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.fallback,
|
||||
node.children,
|
||||
this,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
this.node.values.forEach((attribute) => {
|
||||
add_to_set(this.dependencies, attribute.dependencies);
|
||||
});
|
||||
block.add_dependencies(this.dependencies);
|
||||
// we have to do this, just in case
|
||||
block.add_intro();
|
||||
block.add_outro();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
const { renderer } = this;
|
||||
const { slot_name } = this.node;
|
||||
if (this.slot_block) {
|
||||
block = this.slot_block;
|
||||
}
|
||||
|
||||
/** @type {import('estree').Identifier | 'null'} */
|
||||
let get_slot_changes_fn;
|
||||
|
||||
/** @type {import('estree').Identifier | undefined} */
|
||||
let get_slot_spread_changes_fn;
|
||||
|
||||
/** @type {import('estree').Identifier | 'null'} */
|
||||
let get_slot_context_fn;
|
||||
if (this.node.values.size > 0) {
|
||||
get_slot_changes_fn = renderer.component.get_unique_name(
|
||||
`get_${sanitize(slot_name)}_slot_changes`
|
||||
);
|
||||
get_slot_context_fn = renderer.component.get_unique_name(
|
||||
`get_${sanitize(slot_name)}_slot_context`
|
||||
);
|
||||
const changes = /** @type {import('estree').ObjectExpression} */ (x`{}`);
|
||||
const spread_dynamic_dependencies = new Set();
|
||||
this.node.values.forEach((attribute) => {
|
||||
if (attribute.type === 'Spread') {
|
||||
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)}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
renderer.blocks.push(b`
|
||||
const ${get_slot_changes_fn} = #dirty => ${changes};
|
||||
const ${get_slot_context_fn} = #ctx => ${get_slot_data(this.node.values, block)};
|
||||
`);
|
||||
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)
|
||||
)};
|
||||
`);
|
||||
}
|
||||
} else {
|
||||
get_slot_changes_fn = 'null';
|
||||
get_slot_context_fn = 'null';
|
||||
}
|
||||
let has_fallback = !!this.fallback;
|
||||
if (this.fallback) {
|
||||
this.fragment.render(
|
||||
this.fallback,
|
||||
null,
|
||||
/** @type {import('estree').Identifier} */ (x`#nodes`)
|
||||
);
|
||||
has_fallback = this.fallback.has_content();
|
||||
if (!has_fallback) {
|
||||
renderer.remove_block(this.fallback);
|
||||
}
|
||||
}
|
||||
const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`);
|
||||
const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
|
||||
const slot_or_fallback = has_fallback
|
||||
? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`)
|
||||
: slot;
|
||||
block.chunks.init.push(b`
|
||||
const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
|
||||
const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference(
|
||||
'$$scope'
|
||||
)}, ${get_slot_context_fn});
|
||||
${has_fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
|
||||
`);
|
||||
block.chunks.create.push(b`if (${slot_or_fallback}) ${slot_or_fallback}.c();`);
|
||||
if (renderer.options.hydratable) {
|
||||
block.chunks.claim.push(b`if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});`);
|
||||
}
|
||||
block.chunks.mount.push(b`
|
||||
if (${slot_or_fallback}) {
|
||||
${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});
|
||||
}
|
||||
`);
|
||||
block.chunks.intro.push(b`@transition_in(${slot_or_fallback}, #local);`);
|
||||
block.chunks.outro.push(b`@transition_out(${slot_or_fallback}, #local);`);
|
||||
const dynamic_dependencies = Array.from(this.dependencies).filter((name) =>
|
||||
this.is_dependency_dynamic(name)
|
||||
);
|
||||
const fallback_dynamic_dependencies = has_fallback
|
||||
? Array.from(this.fallback.dependencies).filter((name) => this.is_dependency_dynamic(name))
|
||||
: [];
|
||||
let condition = renderer.dirty(dynamic_dependencies);
|
||||
if (block.has_outros) {
|
||||
condition = x`!#current || ${condition}`;
|
||||
}
|
||||
// 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;
|
||||
|
||||
/** @type {import('estree').Node[]} */
|
||||
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});
|
||||
}
|
||||
`;
|
||||
}
|
||||
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, ${fallback_dirty});
|
||||
}
|
||||
`;
|
||||
if (fallback_update) {
|
||||
block.chunks.update.push(b`
|
||||
if (${slot}) {
|
||||
${slot_update}
|
||||
} else {
|
||||
${fallback_update}
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
block.chunks.update.push(b`
|
||||
if (${slot}) {
|
||||
${slot_update}
|
||||
}
|
||||
`);
|
||||
}
|
||||
block.chunks.destroy.push(b`if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);`);
|
||||
}
|
||||
|
||||
/** @param {string} name */
|
||||
is_dependency_dynamic(name) {
|
||||
if (name === '$$scope') return true;
|
||||
if (this.node.scope.is_let(name)) return true;
|
||||
if (is_reserved_keyword(name)) return true;
|
||||
const variable = this.renderer.component.var_lookup.get(name);
|
||||
return is_dynamic(variable);
|
||||
}
|
||||
}
|
74
node_modules/svelte/src/compiler/compile/render_dom/wrappers/SlotTemplate.js
generated
vendored
Normal file
74
node_modules/svelte/src/compiler/compile/render_dom/wrappers/SlotTemplate.js
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import FragmentWrapper from './Fragment.js';
|
||||
import create_debugging_comment from './shared/create_debugging_comment.js';
|
||||
import { get_slot_definition } from './shared/get_slot_definition.js';
|
||||
import { b, x } from 'code-red';
|
||||
import { sanitize } from '../../../utils/names.js';
|
||||
import { extract_names } from 'periscopic';
|
||||
import { add_const_tags, add_const_tags_context } from './shared/add_const_tags.js';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/SlotTemplate.js').default> */
|
||||
export default class SlotTemplateWrapper extends Wrapper {
|
||||
/** @type {import('./Fragment.js').default} */
|
||||
fragment;
|
||||
|
||||
/** @type {import('../Block.js').default} */
|
||||
block;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/SlotTemplate.js').default} node
|
||||
* @param {boolean} strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, strip_whitespace, next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
const { scope, lets, const_tags, slot_template_name } = this.node;
|
||||
lets.forEach((l) => {
|
||||
extract_names(l.value || l.name).forEach((name) => {
|
||||
renderer.add_to_context(name, true);
|
||||
});
|
||||
});
|
||||
add_const_tags_context(renderer, const_tags);
|
||||
this.block = block.child({
|
||||
comment: create_debugging_comment(this.node, this.renderer.component),
|
||||
name: this.renderer.component.get_unique_name(`create_${sanitize(slot_template_name)}_slot`),
|
||||
type: 'slot'
|
||||
});
|
||||
this.renderer.blocks.push(this.block);
|
||||
|
||||
/** @type {import('./InlineComponent/index.js').default} */ (this.parent).set_slot(
|
||||
slot_template_name,
|
||||
get_slot_definition(this.block, scope, lets)
|
||||
);
|
||||
this.fragment = new FragmentWrapper(
|
||||
renderer,
|
||||
this.block,
|
||||
node.type === 'SlotTemplate' ? node.children : [node],
|
||||
this,
|
||||
strip_whitespace,
|
||||
next_sibling
|
||||
);
|
||||
this.block.parent.add_dependencies(this.block.dependencies);
|
||||
}
|
||||
render() {
|
||||
this.fragment.render(this.block, null, /** @type {import('estree').Identifier} */ (x`#nodes`));
|
||||
if (this.node.const_tags.length > 0) {
|
||||
this.render_get_context();
|
||||
}
|
||||
}
|
||||
render_get_context() {
|
||||
const get_context = this.block.renderer.component.get_unique_name('get_context');
|
||||
this.block.renderer.blocks.push(b`
|
||||
function ${get_context}(#ctx) {
|
||||
${add_const_tags(this.block, this.node.const_tags, '#ctx')}
|
||||
}
|
||||
`);
|
||||
this.block.chunks.declarations.push(b`${get_context}(#ctx)`);
|
||||
if (this.block.has_update_method) {
|
||||
this.block.chunks.update.unshift(b`${get_context}(#ctx)`);
|
||||
}
|
||||
}
|
||||
}
|
69
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Text.js
generated
vendored
Normal file
69
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Text.js
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import { x } from 'code-red';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Text.js').default> */
|
||||
export default class TextWrapper extends Wrapper {
|
||||
/** @type {string} */
|
||||
_data;
|
||||
|
||||
/** @type {boolean} */
|
||||
skip;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Text.js').default} node
|
||||
* @param {string} data
|
||||
*/
|
||||
constructor(renderer, block, parent, node, data) {
|
||||
super(renderer, block, parent, node);
|
||||
this.skip = this.node.should_skip();
|
||||
this._data = data;
|
||||
this.var = /** @type {unknown} */ /** @type {import('estree').Identifier} */ (
|
||||
this.skip ? null : x`t`
|
||||
);
|
||||
}
|
||||
use_space() {
|
||||
return this.node.use_space();
|
||||
}
|
||||
set data(value) {
|
||||
// when updating `this.data` during optimisation
|
||||
// propagate the changes over to the underlying node
|
||||
// so that the node.use_space reflects on the latest `data` value
|
||||
this.node.data = this._data = value;
|
||||
}
|
||||
get data() {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
render(block, parent_node, parent_nodes) {
|
||||
if (this.skip) return;
|
||||
const use_space = this.use_space();
|
||||
const string_literal = {
|
||||
type: 'Literal',
|
||||
value: this.data,
|
||||
loc: {
|
||||
start: this.renderer.locate(this.node.start),
|
||||
end: this.renderer.locate(this.node.end)
|
||||
}
|
||||
};
|
||||
block.add_element(
|
||||
this.var,
|
||||
use_space ? x`@space()` : x`@text(${string_literal})`,
|
||||
parent_nodes &&
|
||||
(use_space
|
||||
? x`@claim_space(${parent_nodes})`
|
||||
: x`@claim_text(${parent_nodes}, ${string_literal})`),
|
||||
/** @type {import('estree').Identifier} */ (parent_node)
|
||||
);
|
||||
}
|
||||
}
|
88
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Title.js
generated
vendored
Normal file
88
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Title.js
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
import { b, x } from 'code-red';
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import { string_literal } from '../../utils/stringify.js';
|
||||
import add_to_set from '../../utils/add_to_set.js';
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Title.js').default> */
|
||||
export default class TitleWrapper extends Wrapper {
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Title.js').default} node
|
||||
* @param {boolean} _strip_whitespace
|
||||
* @param {import('./shared/Wrapper.js').default} _next_sibling
|
||||
*/
|
||||
constructor(renderer, block, parent, node, _strip_whitespace, _next_sibling) {
|
||||
super(renderer, block, parent, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, _parent_node, _parent_nodes) {
|
||||
const is_dynamic = !!this.node.children.find((node) => node.type !== 'Text');
|
||||
if (is_dynamic) {
|
||||
let value;
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const all_dependencies = new Set();
|
||||
// TODO some of this code is repeated in Tag.ts — would be good to
|
||||
// DRY it out if that's possible without introducing crazy indirection
|
||||
if (this.node.children.length === 1) {
|
||||
// single {tag} — may be a non-string
|
||||
// @ts-ignore todo: check this
|
||||
const { expression } = this.node.children[0];
|
||||
value = expression.manipulate(block);
|
||||
add_to_set(all_dependencies, expression.dependencies);
|
||||
} else {
|
||||
// '{foo} {bar}' — treat as string concatenation
|
||||
value = this.node.children
|
||||
.map((chunk) => {
|
||||
if (chunk.type === 'Text') return string_literal(chunk.data);
|
||||
/** @type {import('../../nodes/MustacheTag.js').default} */ (
|
||||
chunk
|
||||
).expression.dependencies.forEach((d) => {
|
||||
all_dependencies.add(d);
|
||||
});
|
||||
return /** @type {import('../../nodes/MustacheTag.js').default} */ (
|
||||
chunk
|
||||
).expression.manipulate(block);
|
||||
})
|
||||
.reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
|
||||
if (this.node.children[0].type !== 'Text') {
|
||||
value = x`"" + ${value}`;
|
||||
}
|
||||
}
|
||||
const last = this.node.should_cache && block.get_unique_name('title_value');
|
||||
if (this.node.should_cache) block.add_variable(last);
|
||||
const init = this.node.should_cache ? x`${last} = ${value}` : value;
|
||||
block.chunks.init.push(b`@_document.title = ${init};`);
|
||||
const updater = b`@_document.title = ${this.node.should_cache ? last : value};`;
|
||||
if (all_dependencies.size) {
|
||||
const dependencies = Array.from(all_dependencies);
|
||||
let condition = block.renderer.dirty(dependencies);
|
||||
if (block.has_outros) {
|
||||
condition = x`!#current || ${condition}`;
|
||||
}
|
||||
if (this.node.should_cache) {
|
||||
condition = x`${condition} && (${last} !== (${last} = ${value}))`;
|
||||
}
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${updater}
|
||||
}`);
|
||||
}
|
||||
} else {
|
||||
const value =
|
||||
this.node.children.length > 0
|
||||
? string_literal(
|
||||
/** @type {import('../../nodes/Text.js').default} */ (this.node.children[0]).data
|
||||
)
|
||||
: x`""`;
|
||||
block.chunks.hydrate.push(b`@_document.title = ${value};`);
|
||||
}
|
||||
}
|
||||
}
|
171
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Window.js
generated
vendored
Normal file
171
node_modules/svelte/src/compiler/compile/render_dom/wrappers/Window.js
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
import Wrapper from './shared/Wrapper.js';
|
||||
import { b, x } from 'code-red';
|
||||
import add_event_handlers from './shared/add_event_handlers.js';
|
||||
import add_actions from './shared/add_actions.js';
|
||||
import EventHandler from './Element/EventHandler.js';
|
||||
|
||||
const associated_events = {
|
||||
innerWidth: 'resize',
|
||||
innerHeight: 'resize',
|
||||
outerWidth: 'resize',
|
||||
outerHeight: 'resize',
|
||||
devicePixelRatio: 'resize',
|
||||
scrollX: 'scroll',
|
||||
scrollY: 'scroll'
|
||||
};
|
||||
const properties = {
|
||||
scrollX: 'pageXOffset',
|
||||
scrollY: 'pageYOffset'
|
||||
};
|
||||
const readonly = new Set([
|
||||
'innerWidth',
|
||||
'innerHeight',
|
||||
'outerWidth',
|
||||
'outerHeight',
|
||||
'devicePixelRatio',
|
||||
'online'
|
||||
]);
|
||||
|
||||
/** @extends Wrapper<import('../../nodes/Window.js').default> */
|
||||
export default class WindowWrapper extends Wrapper {
|
||||
/** @type {import('./Element/EventHandler.js').default[]} */
|
||||
handlers;
|
||||
|
||||
/**
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('./shared/Wrapper.js').default} parent
|
||||
* @param {import('../../nodes/Window.js').default} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
this.handlers = this.node.handlers.map((handler) => new EventHandler(handler, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../Block.js').default} block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
*/
|
||||
render(block, _parent_node, _parent_nodes) {
|
||||
const { renderer } = this;
|
||||
const { component } = renderer;
|
||||
|
||||
/** @type {Record<string, Array<{ name: string; value: string }>>} */
|
||||
const events = {};
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
const bindings = {};
|
||||
add_actions(block, '@_window', this.node.actions);
|
||||
add_event_handlers(block, '@_window', this.handlers);
|
||||
this.node.bindings.forEach((binding) => {
|
||||
// TODO: what if it's a MemberExpression?
|
||||
const binding_name = /** @type {import('estree').Identifier} */ (binding.expression.node)
|
||||
.name;
|
||||
// in dev mode, throw if read-only values are written to
|
||||
if (readonly.has(binding.name)) {
|
||||
renderer.readonly.add(binding_name);
|
||||
}
|
||||
bindings[binding.name] = binding_name;
|
||||
// bind:online is a special case, we need to listen for two separate events
|
||||
if (binding.name === 'online') return;
|
||||
const associated_event = associated_events[binding.name];
|
||||
const property = properties[binding.name] || binding.name;
|
||||
if (!events[associated_event]) events[associated_event] = [];
|
||||
events[associated_event].push({
|
||||
name: binding_name,
|
||||
value: property
|
||||
});
|
||||
});
|
||||
const scrolling = block.get_unique_name('scrolling');
|
||||
const clear_scrolling = block.get_unique_name('clear_scrolling');
|
||||
const scrolling_timeout = block.get_unique_name('scrolling_timeout');
|
||||
Object.keys(events).forEach((event) => {
|
||||
const id = block.get_unique_name(`onwindow${event}`);
|
||||
const props = events[event];
|
||||
renderer.add_to_context(id.name);
|
||||
const fn = renderer.reference(id.name);
|
||||
if (event === 'scroll') {
|
||||
// TODO other bidirectional bindings...
|
||||
block.add_variable(scrolling, x`false`);
|
||||
block.add_variable(clear_scrolling, x`() => { ${scrolling} = false }`);
|
||||
block.add_variable(scrolling_timeout);
|
||||
const condition =
|
||||
bindings.scrollX && bindings.scrollY
|
||||
? x`"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
|
||||
: x`"${bindings.scrollX || bindings.scrollY}" in this._state`;
|
||||
const scroll_x = bindings.scrollX && x`this._state.${bindings.scrollX}`;
|
||||
const scroll_y = bindings.scrollY && x`this._state.${bindings.scrollY}`;
|
||||
renderer.meta_bindings.push(b`
|
||||
if (${condition}) {
|
||||
@_scrollTo(${scroll_x || '@_window.pageXOffset'}, ${scroll_y || '@_window.pageYOffset'});
|
||||
}
|
||||
${scroll_x && `${scroll_x} = @_window.pageXOffset;`}
|
||||
${scroll_y && `${scroll_y} = @_window.pageYOffset;`}
|
||||
`);
|
||||
block.event_listeners.push(x`
|
||||
@listen(@_window, "${event}", () => {
|
||||
${scrolling} = true;
|
||||
@_clearTimeout(${scrolling_timeout});
|
||||
${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
|
||||
${fn}();
|
||||
})
|
||||
`);
|
||||
} else {
|
||||
props.forEach((prop) => {
|
||||
renderer.meta_bindings.push(b`this._state.${prop.name} = @_window.${prop.value};`);
|
||||
});
|
||||
block.event_listeners.push(x`
|
||||
@listen(@_window, "${event}", ${fn})
|
||||
`);
|
||||
}
|
||||
component.partly_hoisted.push(b`
|
||||
function ${id}() {
|
||||
${props.map((prop) => renderer.invalidate(prop.name, x`${prop.name} = @_window.${prop.value}`))}
|
||||
}
|
||||
`);
|
||||
block.chunks.init.push(b`
|
||||
@add_render_callback(${fn});
|
||||
`);
|
||||
component.has_reactive_assignments = true;
|
||||
});
|
||||
// special case... might need to abstract this out if we add more special cases
|
||||
if (bindings.scrollX || bindings.scrollY) {
|
||||
const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
|
||||
const scroll_x = bindings.scrollX
|
||||
? renderer.reference(bindings.scrollX)
|
||||
: x`@_window.pageXOffset`;
|
||||
const scroll_y = bindings.scrollY
|
||||
? renderer.reference(bindings.scrollY)
|
||||
: x`@_window.pageYOffset`;
|
||||
block.chunks.update.push(b`
|
||||
if (${condition} && !${scrolling}) {
|
||||
${scrolling} = true;
|
||||
@_clearTimeout(${scrolling_timeout});
|
||||
@_scrollTo(${scroll_x}, ${scroll_y});
|
||||
${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
|
||||
}
|
||||
`);
|
||||
}
|
||||
// another special case. (I'm starting to think these are all special cases.)
|
||||
if (bindings.online) {
|
||||
const id = block.get_unique_name('onlinestatuschanged');
|
||||
const name = bindings.online;
|
||||
renderer.add_to_context(id.name);
|
||||
const reference = renderer.reference(id.name);
|
||||
component.partly_hoisted.push(b`
|
||||
function ${id}() {
|
||||
${renderer.invalidate(name, x`${name} = @_navigator.onLine`)}
|
||||
}
|
||||
`);
|
||||
block.chunks.init.push(b`
|
||||
@add_render_callback(${reference});
|
||||
`);
|
||||
block.event_listeners.push(
|
||||
x`@listen(@_window, "online", ${reference})`,
|
||||
x`@listen(@_window, "offline", ${reference})`
|
||||
);
|
||||
component.has_reactive_assignments = true;
|
||||
}
|
||||
}
|
||||
}
|
46
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/Tag.js
generated
vendored
Normal file
46
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/Tag.js
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
import { b, x } from 'code-red';
|
||||
import Wrapper from './Wrapper.js';
|
||||
|
||||
/**
|
||||
* @template {import('../../../nodes/MustacheTag.js').default | import('../../../nodes/RawMustacheTag.js').default} NodeType
|
||||
* @extends Wrapper<NodeType>
|
||||
*/
|
||||
export default class Tag extends Wrapper {
|
||||
/**
|
||||
* @param {import('../../Renderer.js').default} renderer
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('./Wrapper.js').default} parent
|
||||
* @param {NodeType} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
super(renderer, block, parent, node);
|
||||
block.add_dependencies(node.expression.dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {(value: import('estree').Node) => import('estree').Node | import('estree').Node[]} update
|
||||
*/
|
||||
rename_this_method(block, update) {
|
||||
const dependencies = this.node.expression.dynamic_dependencies();
|
||||
let snippet = this.node.expression.manipulate(block);
|
||||
const value = this.node.should_cache && block.get_unique_name(`${this.var.name}_value`);
|
||||
const content = this.node.should_cache ? value : snippet;
|
||||
snippet = x`${snippet} + ""`;
|
||||
if (this.node.should_cache) block.add_variable(value, snippet); // TODO may need to coerce snippet to string
|
||||
if (dependencies.length > 0) {
|
||||
let condition = block.renderer.dirty(dependencies);
|
||||
if (block.has_outros) {
|
||||
condition = x`!#current || ${condition}`;
|
||||
}
|
||||
const update_cached_value = x`${value} !== (${value} = ${snippet})`;
|
||||
if (this.node.should_cache) {
|
||||
condition = x`${condition} && ${update_cached_value}`;
|
||||
}
|
||||
block.chunks.update.push(
|
||||
b`if (${condition}) ${update(/** @type {import('estree').Node} */ (content))}`
|
||||
);
|
||||
}
|
||||
return { init: content };
|
||||
}
|
||||
}
|
95
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/Wrapper.js
generated
vendored
Normal file
95
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/Wrapper.js
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
import { x } from 'code-red';
|
||||
|
||||
/**
|
||||
* @template {import('../../../../interfaces.js').TemplateNode} [NodeType=import('../../../../interfaces.js').TemplateNode]
|
||||
*/
|
||||
export default class Wrapper {
|
||||
/** @type {import('../../Renderer.js').default} */
|
||||
renderer;
|
||||
|
||||
/** @type {Wrapper} */
|
||||
parent;
|
||||
|
||||
/** @type {NodeType} */
|
||||
node;
|
||||
|
||||
/** @type {Wrapper | null} */
|
||||
prev;
|
||||
|
||||
/** @type {Wrapper | null} */
|
||||
next;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
var;
|
||||
|
||||
/**
|
||||
* @param {import('../../Renderer.js').default} renderer
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {Wrapper} parent
|
||||
* @param {NodeType} node
|
||||
*/
|
||||
constructor(renderer, block, parent, node) {
|
||||
this.node = node;
|
||||
// make these non-enumerable so that they can be logged sensibly
|
||||
// (TODO in dev only?)
|
||||
Object.defineProperties(this, {
|
||||
renderer: {
|
||||
value: renderer
|
||||
},
|
||||
parent: {
|
||||
value: parent
|
||||
}
|
||||
});
|
||||
block.wrappers.push(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('estree').Identifier} parent_node
|
||||
* @param {import('estree').Identifier} parent_nodes
|
||||
*/
|
||||
get_or_create_anchor(block, parent_node, parent_nodes) {
|
||||
// TODO use this in EachBlock and IfBlock — tricky because
|
||||
// children need to be created first
|
||||
const needs_anchor = this.next
|
||||
? !this.next.is_dom_node()
|
||||
: !parent_node || !this.parent.is_dom_node();
|
||||
const anchor = needs_anchor
|
||||
? block.get_unique_name(`${this.var.name}_anchor`)
|
||||
: (this.next && this.next.var) || { type: 'Identifier', name: 'null' };
|
||||
if (needs_anchor) {
|
||||
block.add_element(
|
||||
anchor,
|
||||
x`@empty()`,
|
||||
parent_nodes && x`@empty()`,
|
||||
/** @type {import('estree').Identifier} */ (parent_node)
|
||||
);
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('estree').Identifier} anchor
|
||||
* @returns {import('estree').Identifier}
|
||||
*/
|
||||
get_update_mount_node(anchor) {
|
||||
return /** @type {import('estree').Identifier} */ (
|
||||
this.parent && this.parent.is_dom_node() ? this.parent.var : x`${anchor}.parentNode`
|
||||
);
|
||||
}
|
||||
is_dom_node() {
|
||||
return (
|
||||
this.node.type === 'Element' || this.node.type === 'Text' || this.node.type === 'MustacheTag'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} _block
|
||||
* @param {import('estree').Identifier} _parent_node
|
||||
* @param {import('estree').Identifier} _parent_nodes
|
||||
* @param {Record<string, any>} _data
|
||||
*/
|
||||
render(_block, _parent_node, _parent_nodes, _data = undefined) {
|
||||
throw Error('Wrapper class is not renderable');
|
||||
}
|
||||
}
|
57
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/add_actions.js
generated
vendored
Normal file
57
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/add_actions.js
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
import { b, x } from 'code-red';
|
||||
import is_contextual from '../../../nodes/shared/is_contextual.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {string | import('estree').Expression} target
|
||||
* @param {import('../../../nodes/Action.js').default[]} actions
|
||||
*/
|
||||
export default function add_actions(block, target, actions) {
|
||||
actions.forEach((action) => add_action(block, target, action));
|
||||
}
|
||||
|
||||
const regex_invalid_variable_identifier_characters = /[^a-zA-Z0-9_$]/g;
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {string | import('estree').Expression} target
|
||||
* @param {import('../../../nodes/Action.js').default} action
|
||||
*/
|
||||
export function add_action(block, target, action) {
|
||||
const { expression, template_scope } = action;
|
||||
|
||||
/** @type {import('estree').Node | undefined} */
|
||||
let snippet;
|
||||
|
||||
/** @type {string[] | undefined} */
|
||||
let dependencies;
|
||||
if (expression) {
|
||||
snippet = expression.manipulate(block);
|
||||
dependencies = expression.dynamic_dependencies();
|
||||
}
|
||||
const id = block.get_unique_name(
|
||||
`${action.name.replace(regex_invalid_variable_identifier_characters, '_')}_action`
|
||||
);
|
||||
block.add_variable(id);
|
||||
const [obj, ...properties] = action.name.split('.');
|
||||
const fn = is_contextual(action.component, template_scope, obj)
|
||||
? block.renderer.reference(obj)
|
||||
: obj;
|
||||
if (properties.length) {
|
||||
const member_expression = properties.reduce((lhs, rhs) => x`${lhs}.${rhs}`, fn);
|
||||
block.event_listeners.push(
|
||||
x`@action_destroyer(${id} = ${member_expression}(${target}, ${snippet}))`
|
||||
);
|
||||
} else {
|
||||
block.event_listeners.push(
|
||||
x`@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))`
|
||||
);
|
||||
}
|
||||
if (dependencies && dependencies.length > 0) {
|
||||
let condition = x`${id} && @is_function(${id}.update)`;
|
||||
if (dependencies.length > 0) {
|
||||
condition = x`${condition} && ${block.renderer.dirty(dependencies)}`;
|
||||
}
|
||||
block.chunks.update.push(b`if (${condition}) ${id}.update.call(null, ${snippet});`);
|
||||
}
|
||||
}
|
54
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/add_const_tags.js
generated
vendored
Normal file
54
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/add_const_tags.js
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
import { b, x } from 'code-red';
|
||||
import Expression from '../../../nodes/shared/Expression.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('../../../nodes/ConstTag.js').default[]} const_tags
|
||||
* @param {string} ctx
|
||||
*/
|
||||
export function add_const_tags(block, const_tags, ctx) {
|
||||
const const_tags_props = [];
|
||||
const_tags.forEach((const_tag, i) => {
|
||||
const name = `#constants_${i}`;
|
||||
const_tags_props.push(b`const ${name} = ${const_tag.expression.manipulate(block, ctx)}`);
|
||||
|
||||
/** @param {string} name */
|
||||
const to_ctx = (name) =>
|
||||
block.renderer.context_lookup.has(name)
|
||||
? x`${ctx}[${block.renderer.context_lookup.get(name).index}]`
|
||||
: /** @type {import('code-red').Node} */ ({ type: 'Identifier', name });
|
||||
const_tag.contexts.forEach((context) => {
|
||||
if (context.type === 'DestructuredVariable') {
|
||||
const_tags_props.push(
|
||||
b`${ctx}[${
|
||||
block.renderer.context_lookup.get(context.key.name).index
|
||||
}] = ${context.default_modifier(context.modifier({ type: 'Identifier', name }), to_ctx)}`
|
||||
);
|
||||
} else {
|
||||
const expression = new Expression(
|
||||
block.renderer.component,
|
||||
const_tag,
|
||||
const_tag.scope,
|
||||
context.key
|
||||
);
|
||||
const_tags_props.push(
|
||||
b`const ${context.property_name} = ${expression.manipulate(block, ctx)}`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
return const_tags_props;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Renderer.js').default} renderer
|
||||
* @param {import('../../../nodes/ConstTag.js').default[]} const_tags
|
||||
*/
|
||||
export function add_const_tags_context(renderer, const_tags) {
|
||||
const_tags.forEach((const_tag) => {
|
||||
const_tag.contexts.forEach((context) => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
renderer.add_to_context(context.key.name, true);
|
||||
});
|
||||
});
|
||||
}
|
17
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.js
generated
vendored
Normal file
17
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {string | import('estree').Expression} target
|
||||
* @param {import('../Element/EventHandler.js').default[]} handlers
|
||||
*/
|
||||
export default function add_event_handlers(block, target, handlers) {
|
||||
handlers.forEach((handler) => add_event_handler(block, target, handler));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {string | import('estree').Expression} target
|
||||
* @param {import('../Element/EventHandler.js').default} handler
|
||||
*/
|
||||
export function add_event_handler(block, target, handler) {
|
||||
handler.render(block, target);
|
||||
}
|
89
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/bind_this.js
generated
vendored
Normal file
89
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/bind_this.js
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
import { b, x } from 'code-red';
|
||||
import { compare_node } from '../../../utils/compare_node.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../../Component.js').default} component
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('../Element/Binding.js').default} binding
|
||||
* @param {import('estree').Identifier} variable
|
||||
*/
|
||||
export default function bind_this(component, block, binding, variable) {
|
||||
const fn = component.get_unique_name(`${variable.name}_binding`);
|
||||
block.renderer.add_to_context(fn.name);
|
||||
const callee = block.renderer.reference(fn.name);
|
||||
const { contextual_dependencies, mutation } = binding.handler;
|
||||
const dependencies = binding.get_update_dependencies();
|
||||
const body = b`
|
||||
${mutation}
|
||||
${Array.from(dependencies)
|
||||
.filter((dep) => dep[0] !== '$')
|
||||
.filter((dep) => !contextual_dependencies.has(dep))
|
||||
.map((dep) => b`${block.renderer.invalidate(dep)};`)}
|
||||
`;
|
||||
if (contextual_dependencies.size) {
|
||||
/** @type {import('estree').Identifier[]} */
|
||||
const params = Array.from(contextual_dependencies).map((name) => ({
|
||||
type: 'Identifier',
|
||||
name
|
||||
}));
|
||||
component.partly_hoisted.push(b`
|
||||
function ${fn}($$value, ${params}) {
|
||||
@binding_callbacks[$$value ? 'unshift' : 'push'](() => {
|
||||
${body}
|
||||
});
|
||||
}
|
||||
`);
|
||||
const alias_map = new Map();
|
||||
const args = [];
|
||||
for (let id of params) {
|
||||
const value = block.renderer.reference(id.name);
|
||||
let found = false;
|
||||
if (block.variables.has(id.name)) {
|
||||
let alias = id.name;
|
||||
for (
|
||||
let i = 1;
|
||||
block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value);
|
||||
alias = `${id.name}_${i++}`
|
||||
);
|
||||
alias_map.set(alias, id.name);
|
||||
id = { type: 'Identifier', name: alias };
|
||||
found = block.variables.has(alias);
|
||||
}
|
||||
args.push(id);
|
||||
if (!found) {
|
||||
block.add_variable(id, value);
|
||||
}
|
||||
}
|
||||
const assign = block.get_unique_name(`assign_${variable.name}`);
|
||||
const unassign = block.get_unique_name(`unassign_${variable.name}`);
|
||||
block.chunks.init.push(b`
|
||||
const ${assign} = () => ${callee}(${variable}, ${args});
|
||||
const ${unassign} = () => ${callee}(null, ${args});
|
||||
`);
|
||||
const condition = Array.from(args)
|
||||
.map(
|
||||
(name) => x`${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`
|
||||
)
|
||||
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`);
|
||||
// we push unassign and unshift assign so that references are
|
||||
// nulled out before they're created, to avoid glitches
|
||||
// with shifting indices
|
||||
block.chunks.update.push(b`
|
||||
if (${condition}) {
|
||||
${unassign}();
|
||||
${args.map((a) => b`${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
|
||||
${assign}();
|
||||
}`);
|
||||
block.chunks.destroy.push(b`${unassign}();`);
|
||||
return b`${assign}();`;
|
||||
}
|
||||
component.partly_hoisted.push(b`
|
||||
function ${fn}($$value) {
|
||||
@binding_callbacks[$$value ? 'unshift' : 'push'](() => {
|
||||
${body}
|
||||
});
|
||||
}
|
||||
`);
|
||||
block.chunks.destroy.push(b`${callee}(null);`);
|
||||
return b`${callee}(${variable});`;
|
||||
}
|
37
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.js
generated
vendored
Normal file
37
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.js
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
import { regex_whitespace_characters } from '../../../../utils/patterns.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../../nodes/interfaces.js').INode} node
|
||||
* @param {import('../../../Component.js').default} component
|
||||
*/
|
||||
export default function create_debugging_comment(node, component) {
|
||||
const { locate, source } = component;
|
||||
let c = node.start;
|
||||
if (node.type === 'ElseBlock') {
|
||||
while (source[c - 1] !== '{') c -= 1;
|
||||
while (source[c - 1] === '{') c -= 1;
|
||||
}
|
||||
|
||||
/** @type {number} */
|
||||
let d;
|
||||
if (node.type === 'InlineComponent' || node.type === 'Element' || node.type === 'SlotTemplate') {
|
||||
if (node.children.length) {
|
||||
d = node.children[0].start;
|
||||
while (source[d - 1] !== '>') d -= 1;
|
||||
} else {
|
||||
d = node.start;
|
||||
while (source[d] !== '>') d += 1;
|
||||
d += 1;
|
||||
}
|
||||
} else if (node.type === 'Text' || node.type === 'Comment') {
|
||||
d = node.end;
|
||||
} else {
|
||||
// @ts-ignore
|
||||
d = node.expression ? node.expression.node.end : c;
|
||||
while (source[d] !== '}' && d <= source.length) d += 1;
|
||||
while (source[d] === '}') d += 1;
|
||||
}
|
||||
const start = locate(c);
|
||||
const loc = `(${start.line}:${start.column})`;
|
||||
return `${loc} ${source.slice(c, d)}`.replace(regex_whitespace_characters, ' ');
|
||||
}
|
108
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.js
generated
vendored
Normal file
108
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.js
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
import { x, p } from 'code-red';
|
||||
|
||||
/**
|
||||
* @param {import('../../Block.js').default} block
|
||||
* @param {import('../../../nodes/shared/TemplateScope.js').default} scope
|
||||
* @param {import('../../../nodes/Let.js').default[]} lets
|
||||
*/
|
||||
export function get_slot_definition(block, scope, lets) {
|
||||
if (lets.length === 0) return { block, scope };
|
||||
const context_input = {
|
||||
type: 'ObjectPattern',
|
||||
properties: lets.map((l) => ({
|
||||
type: 'Property',
|
||||
kind: 'init',
|
||||
key: l.name,
|
||||
value: l.value || l.name
|
||||
}))
|
||||
};
|
||||
const properties = [];
|
||||
const value_map = new Map();
|
||||
lets.forEach((l) => {
|
||||
/** @type {import('estree').Identifier} */
|
||||
let value;
|
||||
if (l.names.length > 1) {
|
||||
// more than one, probably destructuring
|
||||
const unique_name = block.get_unique_name(l.names.join('_')).name;
|
||||
value_map.set(l.value, unique_name);
|
||||
value = { type: 'Identifier', name: unique_name };
|
||||
} else {
|
||||
value = l.value || l.name;
|
||||
}
|
||||
properties.push({
|
||||
type: 'Property',
|
||||
kind: 'init',
|
||||
key: l.name,
|
||||
value
|
||||
});
|
||||
});
|
||||
const changes_input = {
|
||||
type: 'ObjectPattern',
|
||||
properties
|
||||
};
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const names = new Set();
|
||||
|
||||
/** @type {Map<string, string>} */
|
||||
const names_lookup = new Map();
|
||||
lets.forEach((l) => {
|
||||
l.names.forEach((name) => {
|
||||
names.add(name);
|
||||
if (value_map.has(l.value)) {
|
||||
names_lookup.set(name, value_map.get(l.value));
|
||||
}
|
||||
});
|
||||
});
|
||||
const context = {
|
||||
type: 'ObjectExpression',
|
||||
properties: Array.from(names).map(
|
||||
(name) => p`${block.renderer.context_lookup.get(name).index}: ${name}`
|
||||
)
|
||||
};
|
||||
const { context_lookup } = block.renderer;
|
||||
// i am well aware that this code is gross
|
||||
// TODO: context-overflow make it less gross
|
||||
const changes = {
|
||||
type: 'ParenthesizedExpression',
|
||||
get expression() {
|
||||
if (block.renderer.context_overflow) {
|
||||
const grouped = [];
|
||||
Array.from(names).forEach((name) => {
|
||||
const i = /** @type {number} */ (context_lookup.get(name).index.value);
|
||||
const g = Math.floor(i / 31);
|
||||
const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
|
||||
if (!grouped[g]) grouped[g] = [];
|
||||
grouped[g].push({ name: lookup_name, n: i % 31 });
|
||||
});
|
||||
const elements = [];
|
||||
for (let g = 0; g < grouped.length; g += 1) {
|
||||
elements[g] = grouped[g]
|
||||
? grouped[g]
|
||||
.map(({ name, n }) => x`${name} ? ${1 << n} : 0`)
|
||||
.reduce((lhs, rhs) => x`${lhs} | ${rhs}`)
|
||||
: x`0`;
|
||||
}
|
||||
return {
|
||||
type: 'ArrayExpression',
|
||||
elements
|
||||
};
|
||||
}
|
||||
return /** @type {import('estree').BinaryExpression} */ (
|
||||
Array.from(names)
|
||||
.map((name) => {
|
||||
const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
|
||||
const i = /** @type {number} */ (context_lookup.get(name).index.value);
|
||||
return x`${lookup_name} ? ${1 << i} : 0`;
|
||||
})
|
||||
.reduce((lhs, rhs) => x`${lhs} | ${rhs}`)
|
||||
);
|
||||
}
|
||||
};
|
||||
return {
|
||||
block,
|
||||
scope,
|
||||
get_context: x`${context_input} => ${context}`,
|
||||
get_changes: x`${changes_input} => ${changes}`
|
||||
};
|
||||
}
|
14
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/is_dynamic.js
generated
vendored
Normal file
14
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/is_dynamic.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { is_reserved_keyword } from '../../../utils/reserved_keywords.js';
|
||||
|
||||
/** @param {import('../../../../interfaces.js').Var} variable */
|
||||
export default function is_dynamic(variable) {
|
||||
if (variable) {
|
||||
// Only variables declared in the instance script tags should be considered dynamic
|
||||
const is_declared_in_reactive_context = !variable.module && !variable.global;
|
||||
|
||||
if (is_declared_in_reactive_context && (variable.mutated || variable.reassigned)) return true; // dynamic internal state
|
||||
if (is_declared_in_reactive_context && variable.writable && variable.export_name) return true; // writable props
|
||||
if (is_reserved_keyword(variable.name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
11
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/is_head.js
generated
vendored
Normal file
11
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/is_head.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @param {import("estree").Node} node
|
||||
*/
|
||||
export function is_head(node) {
|
||||
return (
|
||||
node &&
|
||||
node.type === 'MemberExpression' &&
|
||||
node.object['name'] === '@_document' &&
|
||||
node.property['name'] === 'head'
|
||||
);
|
||||
}
|
30
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/mark_each_block_bindings.js
generated
vendored
Normal file
30
node_modules/svelte/src/compiler/compile/render_dom/wrappers/shared/mark_each_block_bindings.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @param {import('../Element/index.js').default | import('../InlineComponent/index.js').default} parent
|
||||
* @param {import('../../../nodes/Binding.js').default} binding
|
||||
*/
|
||||
export default function mark_each_block_bindings(parent, binding) {
|
||||
// we need to ensure that the each block creates a context including
|
||||
// the list and the index, if they're not otherwise referenced
|
||||
binding.expression.references.forEach((name) => {
|
||||
const each_block = parent.node.scope.get_owner(name);
|
||||
if (each_block) {
|
||||
/** @type {import('../../../nodes/EachBlock.js').default} */ (each_block).has_binding = true;
|
||||
}
|
||||
});
|
||||
if (binding.name === 'group') {
|
||||
/** @param {string} name */
|
||||
const add_index_binding = (name) => {
|
||||
const each_block = parent.node.scope.get_owner(name);
|
||||
if (each_block.type === 'EachBlock') {
|
||||
each_block.has_index_binding = true;
|
||||
for (const dep of each_block.expression.contextual_dependencies) {
|
||||
add_index_binding(dep);
|
||||
}
|
||||
}
|
||||
};
|
||||
// for `<input bind:group={} >`, we make sure that all the each blocks creates context with `index`
|
||||
for (const name of binding.expression.contextual_dependencies) {
|
||||
add_index_binding(name);
|
||||
}
|
||||
}
|
||||
}
|
120
node_modules/svelte/src/compiler/compile/render_ssr/Renderer.js
generated
vendored
Normal file
120
node_modules/svelte/src/compiler/compile/render_ssr/Renderer.js
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
import AwaitBlock from './handlers/AwaitBlock.js';
|
||||
import Comment from './handlers/Comment.js';
|
||||
import DebugTag from './handlers/DebugTag.js';
|
||||
import EachBlock from './handlers/EachBlock.js';
|
||||
import Element from './handlers/Element.js';
|
||||
import Head from './handlers/Head.js';
|
||||
import HtmlTag from './handlers/HtmlTag.js';
|
||||
import IfBlock from './handlers/IfBlock.js';
|
||||
import InlineComponent from './handlers/InlineComponent.js';
|
||||
import KeyBlock from './handlers/KeyBlock.js';
|
||||
import Slot from './handlers/Slot.js';
|
||||
import SlotTemplate from './handlers/SlotTemplate.js';
|
||||
import Tag from './handlers/Tag.js';
|
||||
import Text from './handlers/Text.js';
|
||||
import Title from './handlers/Title.js';
|
||||
import { collapse_template_literal } from '../utils/collapse_template_literal.js';
|
||||
import { escape_template } from '../utils/stringify.js';
|
||||
|
||||
function noop() {}
|
||||
|
||||
/** @type {Record<string, {(node: any, renderer: Renderer, options: import('../../interfaces.js').CompileOptions): void}>} */
|
||||
const handlers = {
|
||||
AwaitBlock,
|
||||
Body: noop,
|
||||
Comment,
|
||||
DebugTag,
|
||||
Document: noop,
|
||||
EachBlock,
|
||||
Element,
|
||||
Head,
|
||||
IfBlock,
|
||||
InlineComponent,
|
||||
KeyBlock,
|
||||
MustacheTag: Tag,
|
||||
Options: noop,
|
||||
RawMustacheTag: HtmlTag,
|
||||
Slot,
|
||||
SlotTemplate,
|
||||
Text,
|
||||
Title,
|
||||
Window: noop
|
||||
};
|
||||
|
||||
export default class Renderer {
|
||||
has_bindings = false;
|
||||
|
||||
/** @type {import('estree').Identifier} */
|
||||
name = undefined;
|
||||
|
||||
/** @type {Array<{ current: { value: string }; literal: import('estree').TemplateLiteral }>} */
|
||||
stack = [];
|
||||
|
||||
/** @type {{ value: string }} */
|
||||
current = undefined; // TODO can it just be `current: string`?
|
||||
|
||||
/** @type {import('estree').TemplateLiteral} */
|
||||
literal = undefined;
|
||||
|
||||
/** @type {import('../../interfaces.js').AppendTarget[]} */
|
||||
targets = [];
|
||||
constructor({ name }) {
|
||||
this.name = name;
|
||||
this.push();
|
||||
}
|
||||
|
||||
/** @param {string} str */
|
||||
add_string(str) {
|
||||
this.current.value += escape_template(str);
|
||||
}
|
||||
|
||||
/** @param {import('estree').Expression} node */
|
||||
add_expression(node) {
|
||||
this.literal.quasis.push({
|
||||
type: 'TemplateElement',
|
||||
value: { raw: this.current.value, cooked: null },
|
||||
tail: false
|
||||
});
|
||||
this.literal.expressions.push(node);
|
||||
this.current.value = '';
|
||||
}
|
||||
push() {
|
||||
const current = (this.current = { value: '' });
|
||||
const literal = (this.literal = {
|
||||
type: 'TemplateLiteral',
|
||||
expressions: [],
|
||||
quasis: []
|
||||
});
|
||||
this.stack.push({ current, literal });
|
||||
}
|
||||
pop() {
|
||||
this.literal.quasis.push({
|
||||
type: 'TemplateElement',
|
||||
value: { raw: this.current.value, cooked: null },
|
||||
tail: true
|
||||
});
|
||||
const popped = this.stack.pop();
|
||||
const last = this.stack[this.stack.length - 1];
|
||||
if (last) {
|
||||
this.literal = last.literal;
|
||||
this.current = last.current;
|
||||
}
|
||||
// Optimize the TemplateLiteral to remove unnecessary nodes
|
||||
collapse_template_literal(popped.literal);
|
||||
return popped.literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../nodes/interfaces.js').INode[]} nodes
|
||||
* @param {import('./private.js').RenderOptions} options
|
||||
*/
|
||||
render(nodes, options) {
|
||||
nodes.forEach((node) => {
|
||||
const handler = handlers[node.type];
|
||||
if (!handler) {
|
||||
throw new Error(`No handler for '${node.type}' nodes`);
|
||||
}
|
||||
handler(node, this, options);
|
||||
});
|
||||
}
|
||||
}
|
29
node_modules/svelte/src/compiler/compile/render_ssr/handlers/AwaitBlock.js
generated
vendored
Normal file
29
node_modules/svelte/src/compiler/compile/render_ssr/handlers/AwaitBlock.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
import { x } from 'code-red';
|
||||
import { get_const_tags } from './shared/get_const_tags.js';
|
||||
|
||||
/**
|
||||
* @param {import('../../nodes/AwaitBlock.js').default} node
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../private.js').RenderOptions} options
|
||||
*/
|
||||
export default function (node, renderer, options) {
|
||||
renderer.push();
|
||||
renderer.render(node.pending.children, options);
|
||||
|
||||
const pending = renderer.pop();
|
||||
renderer.push();
|
||||
renderer.render(node.then.children, options);
|
||||
|
||||
const then = renderer.pop();
|
||||
renderer.add_expression(x`
|
||||
function(__value) {
|
||||
if (@is_promise(__value)) {
|
||||
__value.then(null, @noop);
|
||||
return ${pending};
|
||||
}
|
||||
return (function(${node.then_node ? node.then_node : ''}) { ${get_const_tags(
|
||||
node.then.const_tags
|
||||
)}; return ${then}; }(__value));
|
||||
}(${node.expression.node})
|
||||
`);
|
||||
}
|
10
node_modules/svelte/src/compiler/compile/render_ssr/handlers/Comment.js
generated
vendored
Normal file
10
node_modules/svelte/src/compiler/compile/render_ssr/handlers/Comment.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @param {import('../../nodes/Comment.js').default} node
|
||||
* @param {import('../Renderer.js').default} renderer
|
||||
* @param {import('../private.js').RenderOptions} options
|
||||
*/
|
||||
export default function (node, renderer, options) {
|
||||
if (options.preserveComments) {
|
||||
renderer.add_string(`<!--${node.data}-->`);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user