chore: add `custom_renderer` flag

paoloricciuti 3 weeks ago committed by Paolo Ricciuti
parent ecd1c90e0e
commit ed44feef9a

@ -71,6 +71,9 @@
"./internal/flags/tracing": {
"default": "./src/internal/flags/tracing.js"
},
"./internal/flags/custom-renderer": {
"default": "./src/internal/flags/custom-renderer.js"
},
"./internal/server": {
"default": "./src/internal/server/index.js"
},

@ -59,6 +59,7 @@ for (const key in pkg.exports) {
if (key === './internal/disclose-version') continue;
if (key === './internal/flags/legacy') continue;
if (key === './internal/flags/tracing') continue;
if (key === './internal/flags/custom-renderer') continue;
if (key === './internal/init-operations') continue;
for (const type of ['browser', 'default']) {
@ -149,6 +150,7 @@ function check_bundle(case_name, ...strings) {
check_bundle('Hydration code', 'hydrate_node', 'hydrate_next');
check_bundle('Legacy code', 'component_context.l');
check_bundle('$inspect.trace', `'CreatedAt'`);
check_bundle('Custom renderer code', 'push_renderer', 'insertForeign', 'renderer_missing_foreign');
if (failed) {
// eslint-disable-next-line no-console

@ -555,6 +555,10 @@ export function client_component(analysis, options) {
if (options.discloseVersion) {
body.unshift(b.imports([], 'svelte/internal/disclose-version'));
}
// this needs to be !== undefined because we want to enable the flag even if the custom renderer is null (which is a valid value meaning "no renderer")
if (custom_renderer !== undefined) {
body.unshift(b.imports([], 'svelte/internal/flags/custom-renderer'));
}
if (custom_renderer) {
body.unshift(b.imports([['$renderer', '$renderer', true]], custom_renderer));

@ -49,6 +49,7 @@ import {
import { defer_effect } from '../../reactivity/utils.js';
import { set_signal_status } from '../../reactivity/status.js';
import { push_renderer } from '../../custom-renderer/state.js';
import { custom_renderers_flag } from '../../../flags/index.js';
/**
* @typedef {{
@ -230,7 +231,9 @@ export class Boundary {
this.#pending_effect = branch(() => pending(this.#anchor));
queue_micro_task(() => {
var pop_renderer = push_renderer(this.#effect.r, this.#effect.pr);
var pop_renderer = custom_renderers_flag
? push_renderer(this.#effect.r, this.#effect.pr)
: undefined;
var fragment = (this.#offscreen_fragment = create_fragment());
var anchor = create_text();
@ -324,7 +327,9 @@ export class Boundary {
set_active_reaction(this.#effect);
set_component_context(this.#effect.ctx);
var pop_renderer = push_renderer(this.#effect.r, this.#effect.pr);
var pop_renderer = custom_renderers_flag
? push_renderer(this.#effect.r, this.#effect.pr)
: undefined;
try {
Batch.ensure();
@ -368,7 +373,9 @@ export class Boundary {
}
if (this.#offscreen_fragment) {
var pop_renderer = push_renderer(this.#effect.r, this.#effect.pr);
var pop_renderer = custom_renderers_flag
? push_renderer(this.#effect.r, this.#effect.pr)
: undefined;
insert_before(this.#anchor, this.#offscreen_fragment);
this.#offscreen_fragment = null;
pop_renderer?.();

@ -24,9 +24,9 @@ import {
push_renderer,
current_renderer,
parent_renderer,
set_parent_renderer,
set_renderer
set_parent_renderer
} from '../../custom-renderer/state.js';
import { custom_renderers_flag } from '../../../flags/index.js';
/**
* @typedef {{ effect: Effect, fragment: DocumentFragment }} Branch
@ -108,14 +108,18 @@ export class BranchManager {
#create_branch(fn) {
// we push current renderer twice because branches will always
// append to the current renderer
var pop_renderer = push_renderer(this.#renderer, this.#renderer);
var pop_renderer = custom_renderers_flag
? push_renderer(this.#renderer, this.#renderer)
: undefined;
try {
return branch(fn);
} finally {
pop_renderer?.();
// we restore the parent_renderer so that an append after a
// branch will append to the correct renderer
set_parent_renderer(this.#parent_renderer);
if (custom_renderers_flag) {
set_parent_renderer(this.#parent_renderer);
}
}
}
@ -126,7 +130,9 @@ export class BranchManager {
// if this batch was made obsolete, bail
if (!this.#batches.has(batch)) return;
var pop_renderer = push_renderer(this.#renderer, this.#parent_renderer);
var pop_renderer = custom_renderers_flag
? push_renderer(this.#renderer, this.#parent_renderer)
: undefined;
var key = /** @type {Key} */ (this.#batches.get(batch));

@ -56,6 +56,7 @@ import {
parent_renderer,
set_parent_renderer
} from '../../custom-renderer/state.js';
import { custom_renderers_flag } from '../../../flags/index.js';
// When making substantive changes to this file, validate them with the each block stress test:
// https://svelte.dev/playground/1972b2cf46564476ad8c8c6405b23b7b
@ -272,7 +273,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
return;
}
var pop_renderer = push_renderer(renderer, parent);
var pop_renderer = custom_renderers_flag ? push_renderer(renderer, parent) : undefined;
state.pending.delete(batch);
@ -309,7 +310,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
// we push current renderer twice because branches will always
// append to the current renderer
var pop_renderer = push_renderer(renderer, renderer);
var pop_renderer = custom_renderers_flag ? push_renderer(renderer, renderer) : undefined;
var effect = block(() => {
array = /** @type {V[]} */ (get(each_array));
@ -447,7 +448,9 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
pop_renderer?.();
// we restore the parent_renderer so that an append after a
// branch will append to the correct renderer
set_parent_renderer(parent);
if (custom_renderers_flag) {
set_parent_renderer(parent);
}
/** @type {EachState} */
var state = { effect, flags, items, pending, outrogroups: null, fallback };

@ -18,6 +18,7 @@ import { prevent_snippet_stringification } from '../../../shared/validate.js';
import { has_own_property } from '../../../shared/utils.js';
import { BranchManager } from './branches.js';
import { current_renderer, push_renderer } from '../../custom-renderer/state.js';
import { custom_renderers_flag } from '../../../flags/index.js';
/**
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn
@ -40,16 +41,18 @@ export function snippet(node, get_snippet, ...args) {
snippet,
snippet &&
((anchor) => {
var renderer = /** @type {any} */ (snippet).__renderer;
var has_renderer = has_own_property.call(/** @type {any} */ (snippet), '__renderer');
if (has_renderer) {
var pop_renderer = push_renderer(renderer, renderer);
try {
return snippet(anchor, ...args);
} finally {
pop_renderer();
if (custom_renderers_flag) {
var renderer = /** @type {any} */ (snippet).__renderer;
var has_renderer = has_own_property.call(/** @type {any} */ (snippet), '__renderer');
if (has_renderer) {
var pop_renderer = push_renderer(renderer, renderer);
try {
return snippet(anchor, ...args);
} finally {
pop_renderer();
}
}
}

@ -16,6 +16,7 @@ import {
TEMPLATE_USE_SVG
} from '../../../constants.js';
import { current_renderer, parent_renderer } from '../custom-renderer/state.js';
import { custom_renderers_flag } from '../../flags/index.js';
import { active_effect } from '../runtime.js';
import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
import {
@ -75,6 +76,7 @@ export function assign_nodes(start, end) {
*/
function should_segment_nodes(effect) {
return (
custom_renderers_flag &&
(current_renderer !== effect.r || parent_renderer !== effect.pr) &&
(current_renderer?.foreign != null || parent_renderer?.foreign != null)
);

@ -15,6 +15,7 @@ import {
set_parent_renderer,
set_renderer
} from '../custom-renderer/state.js';
import { custom_renderers_flag } from '../../flags/index.js';
import { invoke_error_boundary } from '../error-handling.js';
import {
active_effect,
@ -138,8 +139,8 @@ export function capture() {
var previous_reaction = active_reaction;
var previous_component_context = component_context;
var previous_batch = /** @type {Batch} */ (current_batch);
var previous_renderer = current_renderer;
var previous_parent_renderer = parent_renderer;
var previous_renderer = custom_renderers_flag ? current_renderer : null;
var previous_parent_renderer = custom_renderers_flag ? parent_renderer : null;
if (DEV) {
var previous_dev_stack = dev_stack;
@ -150,8 +151,10 @@ export function capture() {
set_active_reaction(previous_reaction);
set_component_context(previous_component_context);
set_renderer(previous_renderer);
set_parent_renderer(previous_parent_renderer);
if (custom_renderers_flag) {
set_renderer(previous_renderer);
set_parent_renderer(previous_parent_renderer);
}
if (activate_batch && (previous_effect.f & DESTROYED) === 0) {
// TODO we only need optional chaining here because `{#await ...}` blocks
@ -283,8 +286,10 @@ export function unset_context(deactivate_batch = true) {
set_active_effect(null);
set_active_reaction(null);
set_component_context(null);
set_renderer(null);
set_parent_renderer(null);
if (custom_renderers_flag) {
set_renderer(null);
set_parent_renderer(null);
}
if (deactivate_batch) current_batch?.deactivate();
if (DEV) {

@ -46,6 +46,7 @@ import { flatten } from './async.js';
import { without_reactive_context } from '../dom/elements/bindings/shared.js';
import { set_signal_status } from './status.js';
import { push_renderer, current_renderer, parent_renderer } from '../custom-renderer/state.js';
import { custom_renderers_flag } from '../../flags/index.js';
/**
* @param {'$effect' | '$effect.pre' | '$inspect'} rune
@ -514,7 +515,7 @@ export function destroy_block_effect_children(signal) {
export function destroy_effect(effect, remove_dom = true) {
var removed = false;
var pop_renderer = push_renderer(effect.r, effect.pr);
var pop_renderer = custom_renderers_flag ? push_renderer(effect.r, effect.pr) : undefined;
if (
(remove_dom || (effect.f & HEAD_EFFECT) !== 0) &&
@ -600,7 +601,7 @@ function remove_effect_nodes(effect) {
for (var i = segments.length - 1; i >= 0; i--) {
var segment = segments[i];
var pop_renderer = push_renderer(segment.r, segment.pr);
var pop_renderer = custom_renderers_flag ? push_renderer(segment.r, segment.pr) : undefined;
remove_effect_dom(segment.start, /** @type {TemplateNode} */ (segment.end));
pop_renderer?.();
}
@ -760,7 +761,7 @@ export function aborted(effect = /** @type {Effect} */ (active_effect)) {
export function move_effect(effect, fragment) {
if (!effect.nodes) return;
var pop_renderer = push_renderer(effect.r, effect.pr);
var pop_renderer = custom_renderers_flag ? push_renderer(effect.r, effect.pr) : undefined;
/** @type {TemplateNode | null} */
var node = effect.nodes.start;

@ -34,6 +34,7 @@ import { is_passive_event } from '../../utils.js';
import { COMMENT_NODE, STATE_SYMBOL, TEXT_CACHE } from './constants.js';
import { boundary } from './dom/blocks/boundary.js';
import { push_renderer } from './custom-renderer/state.js';
import { custom_renderers_flag } from '../flags/index.js';
/**
* This is normally true block effects should run their intro transitions
@ -167,7 +168,7 @@ const listeners = new Map();
* @returns {Exports}
*/
function _mount(Component, options) {
if (options.renderer) {
if (custom_renderers_flag && options.renderer) {
var pop_renderer = push_renderer(options.renderer, options.renderer);
try {

@ -34,7 +34,7 @@ import {
unfreeze_derived_effects,
update_derived
} from './reactivity/deriveds.js';
import { async_mode_flag, tracing_mode_flag } from '../flags/index.js';
import { async_mode_flag, tracing_mode_flag, custom_renderers_flag } from '../flags/index.js';
import { tracing_expressions } from './dev/tracing.js';
import { get_error } from '../shared/dev.js';
import {
@ -447,7 +447,7 @@ export function update_effect(effect) {
active_effect = effect;
is_updating_effect = true;
var pop_renderer = push_renderer(effect.r, effect.pr);
var pop_renderer = custom_renderers_flag ? push_renderer(effect.r, effect.pr) : undefined;
if (DEV) {
var previous_component_fn = dev_current_component_function;

@ -0,0 +1,3 @@
import { enable_custom_renderers_flag } from './index.js';
enable_custom_renderers_flag();

@ -4,6 +4,8 @@ export let async_mode_flag = false;
export let legacy_mode_flag = false;
/** True if $inspect.trace is used */
export let tracing_mode_flag = false;
/** True if custom renderers are used */
export let custom_renderers_flag = false;
export function enable_async_mode_flag() {
async_mode_flag = true;
@ -21,3 +23,7 @@ export function enable_legacy_mode_flag() {
export function enable_tracing_mode_flag() {
tracing_mode_flag = true;
}
export function enable_custom_renderers_flag() {
custom_renderers_flag = true;
}

@ -1 +1,2 @@
import '../internal/flags/custom-renderer.js';
export { createRenderer } from '../internal/client/custom-renderer/index.js';

Loading…
Cancel
Save