From 4ae5eb3f23df00de4d60bf40ff5a96580a0719dc Mon Sep 17 00:00:00 2001 From: Adnane Taghi Date: Thu, 27 Aug 2026 21:58:40 +0100 Subject: [PATCH] feat: add has function to createContext (#18472) closes #18471. --------- Co-authored-by: Simon Holthausen --- .changeset/short-feet-admire.md | 5 +++++ documentation/docs/06-runtime/02-context.md | 2 +- .../docs/98-reference/.generated/shared-errors.md | 2 +- packages/svelte/messages/shared-errors/errors.md | 2 +- packages/svelte/src/internal/client/context.js | 6 +++--- packages/svelte/src/internal/server/context.js | 4 ++-- packages/svelte/src/internal/shared/context.js | 5 +++-- .../create-context-programmatic/Child.svelte | 8 +++++++- .../samples/create-context-programmatic/_config.js | 2 +- .../create-context-programmatic/main.svelte | 14 +++++++++----- .../samples/create-context/Child.svelte | 8 +++++++- .../samples/create-context/_config.js | 2 +- .../samples/create-context/main.svelte | 6 ++++-- packages/svelte/types/index.d.ts | 4 ++-- 14 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 .changeset/short-feet-admire.md diff --git a/.changeset/short-feet-admire.md b/.changeset/short-feet-admire.md new file mode 100644 index 0000000000..fdf56477c9 --- /dev/null +++ b/.changeset/short-feet-admire.md @@ -0,0 +1,5 @@ +--- +'svelte': minor +--- + +feat: add `has` function to `createContext` diff --git a/documentation/docs/06-runtime/02-context.md b/documentation/docs/06-runtime/02-context.md index a1e0347b7b..f67339c6cf 100644 --- a/documentation/docs/06-runtime/02-context.md +++ b/documentation/docs/06-runtime/02-context.md @@ -4,7 +4,7 @@ title: Context Context allows components to access values owned by parent components without passing them down as props (potentially through many layers of intermediate components, known as 'prop-drilling'). -By creating a `[get, set]` pair of functions with `createContext`, you can set the context in a parent component and get it in a child component: +By creating a `[get, set, has]` triplet of functions with `createContext`, you can set the context in a parent component and get it in a child component: ```svelte diff --git a/documentation/docs/98-reference/.generated/shared-errors.md b/documentation/docs/98-reference/.generated/shared-errors.md index d7596fc068..44616d7c8d 100644 --- a/documentation/docs/98-reference/.generated/shared-errors.md +++ b/documentation/docs/98-reference/.generated/shared-errors.md @@ -78,7 +78,7 @@ Certain lifecycle methods can only be used during component initialisation. To f Context was not set in the current component or any of its ancestors ``` -The [`createContext()`](svelte#createContext) utility returns a `[get, set]` pair of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors. +The [`createContext()`](svelte#createContext) utility returns a `[get, set, has]` triplet of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors. ### snippet_without_render_tag diff --git a/packages/svelte/messages/shared-errors/errors.md b/packages/svelte/messages/shared-errors/errors.md index 43dca57ac8..e005e34fc8 100644 --- a/packages/svelte/messages/shared-errors/errors.md +++ b/packages/svelte/messages/shared-errors/errors.md @@ -64,7 +64,7 @@ Certain lifecycle methods can only be used during component initialisation. To f > Context was not set in the current component or any of its ancestors -The [`createContext()`](svelte#createContext) utility returns a `[get, set]` pair of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors. +The [`createContext()`](svelte#createContext) utility returns a `[get, set, has]` triplet of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors. ## snippet_without_render_tag diff --git a/packages/svelte/src/internal/client/context.js b/packages/svelte/src/internal/client/context.js index e1571862ed..c3bb660e8c 100644 --- a/packages/svelte/src/internal/client/context.js +++ b/packages/svelte/src/internal/client/context.js @@ -72,17 +72,17 @@ export function set_dev_current_component_function(fn) { } /** - * Returns a `[get, set]` pair of functions for working with context in a type-safe way. + * Returns a `[get, set, has]` triplet of functions for working with context in a type-safe way. * * `get` will throw an error if `set` has not yet been called in the current component or any of * its ancestors. * * @template T - * @returns {[() => T, (context: T) => T]} + * @returns {[() => T, (context: T) => T, () => boolean]} * @since 5.40.0 */ export function createContext() { - return /** @type {[() => T, (context: T) => T]} */ ( + return /** @type {[() => T, (context: T) => T, () => boolean]} */ ( create_context(getContext, setContext, hasContext) ); } diff --git a/packages/svelte/src/internal/server/context.js b/packages/svelte/src/internal/server/context.js index de11c11282..b204c4c138 100644 --- a/packages/svelte/src/internal/server/context.js +++ b/packages/svelte/src/internal/server/context.js @@ -12,11 +12,11 @@ export function set_ssr_context(v) { /** * @template T - * @returns {[() => T, (context: T) => T]} + * @returns {[() => T, (context: T) => T, () => boolean]} * @since 5.40.0 */ export function createContext() { - return /** @type {[() => T, (context: T) => T]} */ ( + return /** @type {[() => T, (context: T) => T, () => boolean]} */ ( create_context(getContext, setContext, hasContext) ); } diff --git a/packages/svelte/src/internal/shared/context.js b/packages/svelte/src/internal/shared/context.js index 943e15e415..005c009101 100644 --- a/packages/svelte/src/internal/shared/context.js +++ b/packages/svelte/src/internal/shared/context.js @@ -5,7 +5,7 @@ import { lifecycle_outside_component, missing_context } from './errors.js'; * @param {(key: object) => T} get_context * @param {(key: object, context: T) => T} set_context * @param {(key: object) => boolean} has_context - * @returns {[() => T, (context: T) => T]} + * @returns {[() => T, (context: T) => T, () => boolean]} */ export function create_context(get_context, set_context, has_context) { const key = {}; @@ -18,7 +18,8 @@ export function create_context(get_context, set_context, has_context) { return get_context(key); }, - (context) => set_context(key, context) + (context) => set_context(key, context), + () => has_context(key) ]; } diff --git a/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/Child.svelte b/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/Child.svelte index 3e39d5043e..0255132ad6 100644 --- a/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/Child.svelte +++ b/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/Child.svelte @@ -1,7 +1,13 @@

{message}

+{#if has()} +

it's me

+{/if} +{#if !has_unset()} +

or not

+{/if} diff --git a/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/_config.js b/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/_config.js index f4374c8759..c2eeca0de8 100644 --- a/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/_config.js @@ -2,7 +2,7 @@ import { test } from '../../test'; export default test({ ssrHtml: `
`, - html: `

hello

`, + html: `

hello

it's me

or not

`, test() {} }); diff --git a/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/main.svelte b/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/main.svelte index 3c42dbf180..8f4fb67d23 100644 --- a/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/create-context-programmatic/main.svelte @@ -3,9 +3,11 @@ import Child from './Child.svelte'; /** @type {ReturnType>} */ - const [get, set] = createContext(); + const [get, set, has] = createContext(); + /** @type {ReturnType>} */ + const [, , has_unset] = createContext(); - export { get }; + export { get, has, has_unset }; function Wrapper(Component) { return (...args) => { @@ -15,6 +17,8 @@ } -
{ - mount(Wrapper(Child), { target }); -}}>
+
{ + mount(Wrapper(Child), { target }); + }} +>
diff --git a/packages/svelte/tests/runtime-runes/samples/create-context/Child.svelte b/packages/svelte/tests/runtime-runes/samples/create-context/Child.svelte index 3e39d5043e..0255132ad6 100644 --- a/packages/svelte/tests/runtime-runes/samples/create-context/Child.svelte +++ b/packages/svelte/tests/runtime-runes/samples/create-context/Child.svelte @@ -1,7 +1,13 @@

{message}

+{#if has()} +

it's me

+{/if} +{#if !has_unset()} +

or not

+{/if} diff --git a/packages/svelte/tests/runtime-runes/samples/create-context/_config.js b/packages/svelte/tests/runtime-runes/samples/create-context/_config.js index 4ae28e68bd..fa782095de 100644 --- a/packages/svelte/tests/runtime-runes/samples/create-context/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/create-context/_config.js @@ -1,5 +1,5 @@ import { test } from '../../test'; export default test({ - html: `

hello

` + html: `

hello

it's me

or not

` }); diff --git a/packages/svelte/tests/runtime-runes/samples/create-context/main.svelte b/packages/svelte/tests/runtime-runes/samples/create-context/main.svelte index 8d3c50ba55..35093f4c4e 100644 --- a/packages/svelte/tests/runtime-runes/samples/create-context/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/create-context/main.svelte @@ -2,9 +2,11 @@ import { createContext } from 'svelte'; /** @type {ReturnType>} */ - const [get, set] = createContext(); + const [get, set, has] = createContext(); + /** @type {ReturnType>} */ + const [, , has_unset] = createContext(); - export { get }; + export { get, has, has_unset };