move stuff off `state.metadata.context` and onto `state.template`

pull/15538/head
Rich Harris 4 months ago
parent 9106533053
commit 310f82d4f7

@ -154,10 +154,6 @@ export function client_component(analysis, options) {
legacy_reactive_imports: [],
legacy_reactive_statements: new Map(),
metadata: {
context: {
template_needs_import_node: false,
template_contains_script_tag: false
},
namespace: options.namespace,
bound_contenteditable: false
},

@ -14,7 +14,7 @@ import { template_to_string } from './to-string.js';
* @returns
*/
function get_template_function(namespace, state) {
const contains_script_tag = state.metadata.context.template_contains_script_tag;
const contains_script_tag = state.template.contains_script_tag;
return (
namespace === 'svg'
? contains_script_tag

@ -2,6 +2,15 @@
/** @import { Node, Element } from './types'; */
export class Template {
/**
* `true` if HTML template contains a `<script>` tag. In this case we need to invoke a special
* template instantiation function (see `create_fragment_with_script_from_html` for more info)
*/
contains_script_tag = false;
/** `true` if the HTML template needs to be instantiated with `importNode` */
needs_import_node = false;
/** @type {Node[]} */
nodes = [];

@ -59,21 +59,6 @@ export interface ComponentClientTransformState extends ClientTransformState {
readonly metadata: {
namespace: Namespace;
bound_contenteditable: boolean;
/**
* Stuff that is set within the children of one `Fragment` visitor that is relevant
* to said fragment. Shouldn't be destructured or otherwise spread unless inside the
* `Fragment` visitor to keep the object reference intact (it's also nested
* within `metadata` for this reason).
*/
context: {
/** `true` if the HTML template needs to be instantiated with `importNode` */
template_needs_import_node: boolean;
/**
* `true` if HTML template contains a `<script>` tag. In this case we need to invoke a special
* template instantiation function (see `create_fragment_with_script_from_html` for more info)
*/
template_contains_script_tag: boolean;
};
};
readonly preserve_whitespace: boolean;

@ -70,10 +70,6 @@ export function Fragment(node, context) {
locations: [],
transform: { ...context.state.transform },
metadata: {
context: {
template_needs_import_node: false,
template_contains_script_tag: false
},
namespace,
bound_contenteditable: context.state.metadata.bound_contenteditable
}
@ -98,11 +94,7 @@ export function Fragment(node, context) {
node: id
});
let flags = undefined;
if (state.metadata.context.template_needs_import_node) {
flags = TEMPLATE_USE_IMPORT_NODE;
}
let flags = state.template.needs_import_node ? TEMPLATE_USE_IMPORT_NODE : undefined;
transform_template(state, context, namespace, template_name, flags);
@ -144,7 +136,7 @@ export function Fragment(node, context) {
let flags = TEMPLATE_FRAGMENT;
if (state.metadata.context.template_needs_import_node) {
if (state.template.needs_import_node) {
flags |= TEMPLATE_USE_IMPORT_NODE;
}

@ -58,19 +58,15 @@ export function RegularElement(node, context) {
const is_custom_element = is_custom_element_node(node);
if (node.name === 'video' || is_custom_element) {
// cloneNode is faster, but it does not instantiate the underlying class of the
// custom element until the template is connected to the dom, which would
// cause problems when setting properties on the custom element.
// Therefore we need to use importNode instead, which doesn't have this caveat.
// Additionally, Webkit browsers need importNode for video elements for autoplay
// to work correctly.
context.state.metadata.context.template_needs_import_node = true;
}
context.state.template.needs_import_node ||= node.name === 'video' || is_custom_element;
if (node.name === 'script') {
context.state.metadata.context.template_contains_script_tag = true;
}
context.state.template.contains_script_tag ||= node.name === 'script';
context.state.template.create_element(node.name);

Loading…
Cancel
Save