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.');
}
if (current_component_context.r) {
if (current_component_context.l !== null) {
init_update_callbacks(current_component_context).m.push(fn);
} else {
user_effect(() => {
const cleanup = untrack(fn);
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');
}
if (current_component_context.r) {
if (current_component_context.l === null) {
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.');
}
if (current_component_context.r) {
if (current_component_context.l === null) {
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
* @param {import('./internal/client/types.js').ComponentContext} context
* @param {import('#client').ComponentContext} 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
*/
export function init() {
const context = /** @type {import('#client').ComponentContext} */ (current_component_context);
const callbacks = context.u;
const context = /** @type {import('#client').ComponentContextLegacy} */ (
current_component_context
);
const callbacks = context.l.u;
if (!callbacks) return;
// beforeUpdate
@ -58,11 +60,11 @@ export function init() {
/**
* Invoke the getter of all signals associated with a component
* 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) {
if (context.d) {
for (const signal of context.d) get(signal);
if (context.l.s) {
for (const signal of context.l.s) get(signal);
}
deep_read_state(context.s);

@ -182,11 +182,11 @@ export function effect(fn) {
* @param {() => void | (() => void)} 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 }} */
var token = { effect: null, ran: false };
context.l1.push(token);
context.l.r1.push(token);
token.effect = render_effect(() => {
deps();
@ -196,19 +196,19 @@ export function legacy_pre_effect(deps, fn) {
if (token.ran) return;
token.ran = true;
set(context.l2, true);
set(context.l.r2, true);
untrack(fn);
});
}
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(() => {
if (!get(context.l2)) return;
if (!get(context.l.r2)) return;
// Run dirty `$:` statements
for (var token of context.l1) {
for (var token of context.l.r1) {
var effect = token.effect;
if (check_dirtiness(effect)) {
@ -218,7 +218,7 @@ export function legacy_pre_effect_reset() {
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
// track updates to trigger beforeUpdate/afterUpdate callbacks
if (current_component_context) {
(current_component_context.d ??= []).push(s);
if (current_component_context !== null && current_component_context.l !== null) {
(current_component_context.l.s ??= []).push(s);
}
return s;

@ -115,7 +115,7 @@ export function set_current_component_context(context) {
/** @returns {boolean} */
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) {
current_component_context = {
// exports (and props, if `accessors: true`)
x: null,
// context
p: current_component_context,
c: null,
// effects
e: null,
// mounted
m: false,
// parent
p: current_component_context,
// signals
d: null,
// props
s: props,
// runes
r: runes,
// legacy $:
l1: [],
l2: source(false),
// update_callbacks
u: null
x: null,
l: null
};
if (!runes) {
current_component_context.l = {
s: null,
u: null,
r1: [],
r2: source(false)
};
}
if (DEV) {
// component function
// @ts-expect-error

@ -10,37 +10,51 @@ export type EventCallbackMap = Record<string, EventCallback | EventCallback[]>;
// when the JS VM JITs the code.
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 */
p: null | ComponentContext;
/** context */
c: null | Map<unknown, unknown>;
/** runes */
r: boolean;
/** legacy mode: if `$:` statements are allowed to run (ensures they only run once per render) */
l1: any[];
/** legacy mode: if `$:` statements are allowed to run (ensures they only run once per render) */
l2: Source<boolean>;
/** update_callbacks */
u: null | {
/** afterUpdate callbacks */
a: Array<() => void>;
/** beforeUpdate callbacks */
b: Array<() => void>;
/** onMount callbacks */
m: Array<() => any>;
/** deferred effects */
e: null | Array<() => void | (() => void)>;
/** mounted */
m: boolean;
/**
* props needed for legacy mode lifecycle functions, and for `createEventDispatcher`
* @deprecated remove in 6.0
*/
s: Record<string, unknown>;
/**
* exports (and props, if `accessors: true`) needed for `createEventDispatcher`
* @deprecated remove in 6.0
*/
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 TemplateNode = Text | Element | Comment;

Loading…
Cancel
Save