From 6c5257beb26094ed42105a0f59b4f04e18fe20b5 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Wed, 31 Mar 2021 23:07:32 +0800 Subject: [PATCH] allow passing in context in constructor (#6032) Co-authored-by: Conduitry --- CHANGELOG.md | 4 +++ site/content/docs/03-run-time.md | 27 ++++++++++++++++ src/runtime/internal/Component.ts | 2 +- src/runtime/internal/ssr.ts | 8 ++--- .../constructor-pass-context/Component.svelte | 9 ++++++ .../constructor-pass-context/_config.js | 32 +++++++++++++++++++ .../constructor-pass-context/main.svelte | 0 test/server-side-rendering/index.ts | 5 +++ 8 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 test/runtime/samples/constructor-pass-context/Component.svelte create mode 100644 test/runtime/samples/constructor-pass-context/_config.js create mode 100644 test/runtime/samples/constructor-pass-context/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 09e9808546..86c9bff955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Allow root-level context to be passed to the component constructor ([#6032](https://github.com/sveltejs/svelte/pull/6032)) + ## 3.36.0 * Add `this: void` typing to store functions ([#6094](https://github.com/sveltejs/svelte/pull/6094)) diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index 386c18d5fd..7fbc8850de 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -904,6 +904,7 @@ The following initialisation options can be provided: | `target` | **none** | An `HTMLElement` to render to. This option is required | `anchor` | `null` | A child of `target` to render the component immediately before | `props` | `{}` | An object of properties to supply to the component +| `context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component | `hydrate` | `false` | See below | `intro` | `false` | If `true`, will play transitions on initial render, rather than waiting for subsequent state changes @@ -1081,3 +1082,29 @@ const { head, html, css } = App.render({ answer: 42 }); ``` + +--- + +The `.render()` method accepts the following parameters: + +| parameter | default | description | +| --- | --- | --- | +| `props` | `{}` | An object of properties to supply to the component +| `options` | `{}` | An object of options + +The `options` object takes in the following options: + +| option | default | description | +| --- | --- | --- | +| `context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component + +```js +const { head, html, css } = App.render( + // props + { answer: 42 }, + // options + { + context: new Map([['context-key', 'context-value']]) + } +); +``` diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 5a2a966d0b..32de46506a 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -120,7 +120,7 @@ export function init(component, options, instance, create_fragment, not_equal, p on_disconnect: [], before_update: [], after_update: [], - context: new Map(parent_component ? parent_component.$$.context : []), + context: new Map(parent_component ? parent_component.$$.context : options.context || []), // everything else callbacks: blank_object(), diff --git a/src/runtime/internal/ssr.ts b/src/runtime/internal/ssr.ts index 2d843abb2f..5e7977571c 100644 --- a/src/runtime/internal/ssr.ts +++ b/src/runtime/internal/ssr.ts @@ -74,12 +74,12 @@ export function debug(file, line, column, values) { let on_destroy; export function create_ssr_component(fn) { - function $$render(result, props, bindings, slots) { + function $$render(result, props, bindings, slots, context) { const parent_component = current_component; const $$ = { on_destroy, - context: new Map(parent_component ? parent_component.$$.context : []), + context: new Map(parent_component ? parent_component.$$.context : context || []), // these will be immediately discarded on_mount: [], @@ -97,7 +97,7 @@ export function create_ssr_component(fn) { } return { - render: (props = {}, options = {}) => { + render: (props = {}, { $$slots = {}, context = new Map() } = {}) => { on_destroy = []; const result: { @@ -109,7 +109,7 @@ export function create_ssr_component(fn) { }>; } = { title: '', head: '', css: new Set() }; - const html = $$render(result, props, {}, options); + const html = $$render(result, props, {}, $$slots, context); run_all(on_destroy); diff --git a/test/runtime/samples/constructor-pass-context/Component.svelte b/test/runtime/samples/constructor-pass-context/Component.svelte new file mode 100644 index 0000000000..ae27a0d57a --- /dev/null +++ b/test/runtime/samples/constructor-pass-context/Component.svelte @@ -0,0 +1,9 @@ + + +
{value}
+'); + + const button = target.querySelector('button'); + await button.dispatchEvent(new window.MouseEvent('click')); + + assert.deepEqual(called, ['hello world']); + + component.$destroy(); + }, + test_ssr({ assert }) { + const Component = require('./Component.svelte').default; + + const called = []; + const { html } = Component.render(undefined, { context: new Map([ + ['key', 'svelte'], + ['fn', (value) => called.push(value)] + ]) }); + assert.htmlEqual(html, '
svelte
'); + } +}; diff --git a/test/runtime/samples/constructor-pass-context/main.svelte b/test/runtime/samples/constructor-pass-context/main.svelte new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/server-side-rendering/index.ts b/test/server-side-rendering/index.ts index f44bf17ab9..e81058181d 100644 --- a/test/server-side-rendering/index.ts +++ b/test/server-side-rendering/index.ts @@ -13,6 +13,7 @@ import { shouldUpdateExpected, mkdirp } from '../helpers'; +import { set_current_component } from '../../internal'; function tryToReadFile(file) { try { @@ -127,6 +128,8 @@ describe('ssr', () => { showOutput(dir, { generate: 'ssr', format: 'cjs' }); err.stack += `\n\ncmd-click: ${path.relative(process.cwd(), dir)}/main.svelte`; throw err; + } finally { + set_current_component(null); } }); }); @@ -223,6 +226,8 @@ describe('ssr', () => { showOutput(cwd, compileOptions); throw err; } + } finally { + set_current_component(null); } }); });