chore: move legacy context stuff into its own object (#11298)

pull/11307/head
Rich Harris 8 months ago committed by GitHub
parent 7b55bd4d89
commit 1f04045052
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -21,13 +21,13 @@ export function onMount(fn) {
throw new Error('onMount can only be used during component initialisation.'); throw new Error('onMount can only be used during component initialisation.');
} }
if (current_component_context.r) { if (current_component_context.l !== null) {
init_update_callbacks(current_component_context).m.push(fn);
} else {
user_effect(() => { user_effect(() => {
const cleanup = untrack(fn); const cleanup = untrack(fn);
if (typeof cleanup === 'function') return /** @type {() => void} */ (cleanup); if (typeof cleanup === 'function') return /** @type {() => void} */ (cleanup);
}); });
} else {
init_update_callbacks(current_component_context).m.push(fn);
} }
} }
@ -129,7 +129,7 @@ export function beforeUpdate(fn) {
throw new Error('beforeUpdate can only be used during component initialisation'); throw new Error('beforeUpdate can only be used during component initialisation');
} }
if (current_component_context.r) { if (current_component_context.l === null) {
throw new Error('beforeUpdate cannot be used in runes mode'); throw new Error('beforeUpdate cannot be used in runes mode');
} }
@ -153,7 +153,7 @@ export function afterUpdate(fn) {
throw new Error('afterUpdate can only be used during component initialisation.'); throw new Error('afterUpdate can only be used during component initialisation.');
} }
if (current_component_context.r) { if (current_component_context.l === null) {
throw new Error('afterUpdate cannot be used in runes mode'); throw new Error('afterUpdate cannot be used in runes mode');
} }
@ -162,10 +162,11 @@ export function afterUpdate(fn) {
/** /**
* Legacy-mode: Init callbacks object for onMount/beforeUpdate/afterUpdate * Legacy-mode: Init callbacks object for onMount/beforeUpdate/afterUpdate
* @param {import('./internal/client/types.js').ComponentContext} context * @param {import('#client').ComponentContext} context
*/ */
function init_update_callbacks(context) { function init_update_callbacks(context) {
return (context.u ??= { a: [], b: [], m: [] }); var l = /** @type {import('#client').ComponentContextLegacy} */ (context).l;
return (l.u ??= { a: [], b: [], m: [] });
} }
/** /**

@ -14,9 +14,11 @@ import {
* Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects * Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects
*/ */
export function init() { export function init() {
const context = /** @type {import('#client').ComponentContext} */ (current_component_context); const context = /** @type {import('#client').ComponentContextLegacy} */ (
const callbacks = context.u; current_component_context
);
const callbacks = context.l.u;
if (!callbacks) return; if (!callbacks) return;
// beforeUpdate // beforeUpdate
@ -58,11 +60,11 @@ export function init() {
/** /**
* Invoke the getter of all signals associated with a component * Invoke the getter of all signals associated with a component
* so they can be registered to the effect this function is called in. * so they can be registered to the effect this function is called in.
* @param {import('#client').ComponentContext} context * @param {import('#client').ComponentContextLegacy} context
*/ */
function observe_all(context) { function observe_all(context) {
if (context.d) { if (context.l.s) {
for (const signal of context.d) get(signal); for (const signal of context.l.s) get(signal);
} }
deep_read_state(context.s); deep_read_state(context.s);

@ -182,11 +182,11 @@ export function effect(fn) {
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
*/ */
export function legacy_pre_effect(deps, fn) { export function legacy_pre_effect(deps, fn) {
var context = /** @type {import('#client').ComponentContext} */ (current_component_context); var context = /** @type {import('#client').ComponentContextLegacy} */ (current_component_context);
/** @type {{ effect: null | import('#client').Effect, ran: boolean }} */ /** @type {{ effect: null | import('#client').Effect, ran: boolean }} */
var token = { effect: null, ran: false }; var token = { effect: null, ran: false };
context.l1.push(token); context.l.r1.push(token);
token.effect = render_effect(() => { token.effect = render_effect(() => {
deps(); deps();
@ -196,19 +196,19 @@ export function legacy_pre_effect(deps, fn) {
if (token.ran) return; if (token.ran) return;
token.ran = true; token.ran = true;
set(context.l2, true); set(context.l.r2, true);
untrack(fn); untrack(fn);
}); });
} }
export function legacy_pre_effect_reset() { export function legacy_pre_effect_reset() {
var context = /** @type {import('#client').ComponentContext} */ (current_component_context); var context = /** @type {import('#client').ComponentContextLegacy} */ (current_component_context);
render_effect(() => { render_effect(() => {
if (!get(context.l2)) return; if (!get(context.l.r2)) return;
// Run dirty `$:` statements // Run dirty `$:` statements
for (var token of context.l1) { for (var token of context.l.r1) {
var effect = token.effect; var effect = token.effect;
if (check_dirtiness(effect)) { if (check_dirtiness(effect)) {
@ -218,7 +218,7 @@ export function legacy_pre_effect_reset() {
token.ran = false; token.ran = false;
} }
context.l2.v = false; // set directly to avoid rerunning this effect context.l.r2.v = false; // set directly to avoid rerunning this effect
}); });
} }

@ -55,8 +55,8 @@ export function mutable_source(initial_value) {
// bind the signal to the component context, in case we need to // bind the signal to the component context, in case we need to
// track updates to trigger beforeUpdate/afterUpdate callbacks // track updates to trigger beforeUpdate/afterUpdate callbacks
if (current_component_context) { if (current_component_context !== null && current_component_context.l !== null) {
(current_component_context.d ??= []).push(s); (current_component_context.l.s ??= []).push(s);
} }
return s; return s;

@ -115,7 +115,7 @@ export function set_current_component_context(context) {
/** @returns {boolean} */ /** @returns {boolean} */
export function is_runes() { export function is_runes() {
return current_component_context !== null && current_component_context.r; return current_component_context !== null && current_component_context.l === null;
} }
/** /**
@ -1043,29 +1043,24 @@ export async function value_or_fallback_async(value, fallback) {
*/ */
export function push(props, runes = false, fn) { export function push(props, runes = false, fn) {
current_component_context = { current_component_context = {
// exports (and props, if `accessors: true`) p: current_component_context,
x: null,
// context
c: null, c: null,
// effects
e: null, e: null,
// mounted
m: false, m: false,
// parent
p: current_component_context,
// signals
d: null,
// props
s: props, s: props,
// runes x: null,
r: runes, l: null
// legacy $:
l1: [],
l2: source(false),
// update_callbacks
u: null
}; };
if (!runes) {
current_component_context.l = {
s: null,
u: null,
r1: [],
r2: source(false)
};
}
if (DEV) { if (DEV) {
// component function // component function
// @ts-expect-error // @ts-expect-error

@ -10,37 +10,51 @@ export type EventCallbackMap = Record<string, EventCallback | EventCallback[]>;
// when the JS VM JITs the code. // when the JS VM JITs the code.
export type ComponentContext = { export type ComponentContext = {
/** local signals (needed for beforeUpdate/afterUpdate) */
d: null | Source[];
/** props */
s: Record<string, unknown>;
/** exports (and props, if `accessors: true`) */
x: Record<string, any> | null;
/** deferred effects */
e: null | Array<() => void | (() => void)>;
/** mounted */
m: boolean;
/** parent */ /** parent */
p: null | ComponentContext; p: null | ComponentContext;
/** context */ /** context */
c: null | Map<unknown, unknown>; c: null | Map<unknown, unknown>;
/** runes */ /** deferred effects */
r: boolean; e: null | Array<() => void | (() => void)>;
/** legacy mode: if `$:` statements are allowed to run (ensures they only run once per render) */ /** mounted */
l1: any[]; m: boolean;
/** legacy mode: if `$:` statements are allowed to run (ensures they only run once per render) */ /**
l2: Source<boolean>; * props needed for legacy mode lifecycle functions, and for `createEventDispatcher`
/** update_callbacks */ * @deprecated remove in 6.0
u: null | { */
/** afterUpdate callbacks */ s: Record<string, unknown>;
a: Array<() => void>; /**
/** beforeUpdate callbacks */ * exports (and props, if `accessors: true`) needed for `createEventDispatcher`
b: Array<() => void>; * @deprecated remove in 6.0
/** onMount callbacks */ */
m: Array<() => any>; x: Record<string, any> | null;
/**
* legacy stuff
* @deprecated remove in 6.0
*/
l: null | {
/** local signals (needed for beforeUpdate/afterUpdate) */
s: null | Source[];
/** update_callbacks */
u: null | {
/** afterUpdate callbacks */
a: Array<() => void>;
/** beforeUpdate callbacks */
b: Array<() => void>;
/** onMount callbacks */
m: Array<() => any>;
};
/** `$:` statements */
r1: any[];
/** This tracks whether `$:` statements have run in the current cycle, to ensure they only run once */
r2: Source<boolean>;
}; };
}; };
export type ComponentContextLegacy = ComponentContext & {
l: NonNullable<ComponentContext['l']>;
};
export type Equals = (this: Value, value: unknown) => boolean; export type Equals = (this: Value, value: unknown) => boolean;
export type TemplateNode = Text | Element | Comment; export type TemplateNode = Text | Element | Comment;

Loading…
Cancel
Save