remove createPortalKey

portals
Simon Holthausen 1 month ago
parent 10bd29a258
commit 8a7ae2e89f
No known key found for this signature in database

@ -1121,12 +1121,12 @@ export function expected_attribute_value(node) {
}
/**
* Expected 'if', 'each', 'await', 'key', 'portal' or 'snippet'
* Expected 'if', 'each', 'await', 'key' or 'snippet'
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function expected_block_type(node) {
e(node, 'expected_block_type', `Expected 'if', 'each', 'await', 'key', 'portal' or 'snippet'\nhttps://svelte.dev/e/expected_block_type`);
e(node, 'expected_block_type', `Expected 'if', 'each', 'await', 'key' or 'snippet'\nhttps://svelte.dev/e/expected_block_type`);
}
/**
@ -1734,4 +1734,4 @@ export function unterminated_string_constant(node) {
*/
export function void_element_invalid_content(node) {
e(node, 'void_element_invalid_content', `Void elements cannot have children or closing tags\nhttps://svelte.dev/e/void_element_invalid_content`);
}
}

@ -253,5 +253,3 @@ export { hydratable } from './internal/client/hydratable.js';
export { hydrate, mount, unmount } from './internal/client/render.js';
export { tick, untrack, settled } from './internal/client/runtime.js';
export { createRawSnippet } from './internal/client/dom/blocks/snippet.js';
export { createPortalKey } from './internal/shared/portal.js';

@ -54,5 +54,3 @@ export {
export { hydratable } from './internal/server/hydratable.js';
export { createRawSnippet } from './internal/server/blocks/snippet.js';
export { createPortalKey } from './internal/shared/portal.js';

@ -1,6 +1,5 @@
/** @import { Effect, EffectNodes, TemplateNode } from '#client' */
import { HYDRATION_END, HYDRATION_START, HYDRATION_START_ELSE } from '../../../../constants.js';
import { PortalKey } from '../../../shared/portal.js';
import { block, remove_effect_dom, render_effect } from '../../reactivity/effects.js';
import { active_effect, set_active_effect } from '../../runtime.js';
import { hydrate_node, hydrating, set_hydrate_node, set_hydrating } from '../hydration.js';
@ -107,12 +106,6 @@ export function portal(target, content) {
if (target == null) return;
const is_dom_node = target instanceof Element;
if (!is_dom_node && !(target instanceof PortalKey)) {
throw new Error(
'TODO error code: target can only be a key instantiated with createPortalKey, or a DOM node'
);
}
/** @type {TemplateNode} */
var anchor;
if (is_dom_node) {

@ -14,7 +14,6 @@ import { sha256 } from './crypto.js';
import * as devalue from 'devalue';
import { has_own_property, noop } from '../shared/utils.js';
import { escape_html } from '../../escaping.js';
import { PortalKey } from '../shared/portal.js';
/** @typedef {'head' | 'body'} RendererType */
/** @typedef {{ [key in RendererType]: string }} AccumulatedContent */
@ -422,40 +421,34 @@ export class Renderer {
});
}
/** @param {PortalKey} key */
/** @param {any} key */
portal_outlet(key) {
if (key == null) return;
this.push(BLOCK_OPEN);
const id = `<!--portal:${key.v}-->`;
this.push(id);
if (!this.global.portals.has(id)) {
this.global.portals.set(id, []);
}
const portal = this.global.portals.get(key) ?? { id: undefined, renderers: [] };
portal.id = `<!--portal:${this.global.portal_id++}-->`;
this.global.portals.set(key, portal);
this.push(portal.id);
this.push(BLOCK_CLOSE);
}
/**
* @param {PortalKey | undefined} target
* @param {any} target
* @param {(p: Renderer) => void} content
*/
portal(target, content) {
this.push(EMPTY_COMMENT);
if (!target) return; // probably targets a DOM node - not possible in SSR, ignore
if (target == null) return; // probably targets a DOM node - not possible in SSR, ignore
if (!(target instanceof PortalKey)) {
throw new Error(
'TODO error code: target can only be a key instantiated with createPortalKey, or a DOM node'
);
}
const id = `<!--portal:${target.v}-->`;
const portal = this.global.portals.get(id) ?? [];
this.global.portals.set(id, portal);
const portal = this.global.portals.get(target) ?? { id: undefined, renderers: [] };
this.global.portals.set(target, portal);
const tmp_payload = new Renderer(this.global, this);
content(tmp_payload);
tmp_payload.push(EMPTY_COMMENT);
portal.push(tmp_payload);
portal.renderers.push(tmp_payload);
}
/**
@ -675,13 +668,15 @@ export class Renderer {
const renderer = Renderer.#open_render('sync', component, options);
const content = renderer.#collect_content();
for (const [id, portal] of renderer.global.portals) {
for (const item of portal) {
for (const portal of renderer.global.portals.values()) {
if (portal.id === undefined) continue;
for (const item of portal.renderers) {
if (item instanceof Renderer) {
const portal_content = item.#collect_content();
item.#out.length = 0;
content.body = content.body.replace(id, id + portal_content.body);
content.head = content.head.replace(id, id + portal_content.body);
content.body = content.body.replace(portal.id, portal.id + portal_content.body);
content.head = content.head.replace(portal.id, portal.id + portal_content.body);
}
}
}
@ -712,12 +707,14 @@ export class Renderer {
content.head = hydratables + content.head;
}
for (const [id, portal] of renderer.global.portals) {
for (const item of portal) {
for (const portal of renderer.global.portals.values()) {
if (portal.id === undefined) continue;
for (const item of portal.renderers) {
if (item instanceof Renderer) {
const portal_content = await item.#collect_content_async();
content.body = content.body.replace(id, id + portal_content.body);
content.head = content.head.replace(id, id + portal_content.body);
content.body = content.body.replace(portal.id, portal.id + portal_content.body);
content.head = content.head.replace(portal.id, portal.id + portal_content.body);
}
}
}
@ -954,9 +951,12 @@ export class SSRState {
*/
transformError;
/** @type {Map<string, Renderer[]>} */
/** @type {Map<any, { id: string | undefined, renderers: Renderer[] }>} */
portals = new Map();
/** @type {number} */
portal_id = 1;
/** @type {{ path: number[], value: string }} */
#title = { path: [], value: '' };

@ -1,15 +0,0 @@
export class PortalKey {
/** @param {string} name */
constructor(name) {
this.v = name;
}
}
/**
* Creates a key for use with `{#portal ...}` and `{@portal ...}`. It connects the portal source and outlet.
* Example: TODO write out once exact API clear.
* @param {string} name
*/
export function createPortalKey(name) {
return new PortalKey(name);
}

@ -1,11 +1,5 @@
<script>
import { createPortalKey } from 'svelte';
{@portal 'example'}
const key = createPortalKey('example');
</script>
{@portal key}
{#portal key}
{#portal 'example'}
<p>portaled</p>
{/portal}

@ -2,91 +2,86 @@
"css": null,
"js": [],
"start": 0,
"end": 160,
"end": 67,
"type": "Root",
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 103,
"end": 105,
"raw": "\n\n",
"data": "\n\n"
},
{
"type": "PortalTag",
"start": 105,
"end": 118,
"start": 0,
"end": 19,
"expression": {
"type": "Identifier",
"start": 114,
"end": 117,
"type": "Literal",
"start": 9,
"end": 18,
"loc": {
"start": {
"line": 7,
"line": 1,
"column": 9
},
"end": {
"line": 7,
"column": 12
"line": 1,
"column": 18
}
},
"name": "key"
"value": "example",
"raw": "'example'"
}
},
{
"type": "Text",
"start": 118,
"end": 120,
"start": 19,
"end": 21,
"raw": "\n\n",
"data": "\n\n"
},
{
"type": "PortalBlock",
"start": 120,
"end": 160,
"start": 21,
"end": 67,
"expression": {
"type": "Identifier",
"start": 129,
"end": 132,
"type": "Literal",
"start": 30,
"end": 39,
"loc": {
"start": {
"line": 9,
"line": 3,
"column": 9
},
"end": {
"line": 9,
"column": 12
"line": 3,
"column": 18
}
},
"name": "key"
"value": "example",
"raw": "'example'"
},
"fragment": {
"type": "Fragment",
"nodes": [
{
"type": "Text",
"start": 133,
"end": 135,
"start": 40,
"end": 42,
"raw": "\n\t",
"data": "\n\t"
},
{
"type": "RegularElement",
"start": 135,
"end": 150,
"start": 42,
"end": 57,
"name": "p",
"name_loc": {
"start": {
"line": 10,
"line": 4,
"column": 2,
"character": 136
"character": 43
},
"end": {
"line": 10,
"line": 4,
"column": 3,
"character": 137
"character": 44
}
},
"attributes": [],
@ -95,8 +90,8 @@
"nodes": [
{
"type": "Text",
"start": 138,
"end": 146,
"start": 45,
"end": 53,
"raw": "portaled",
"data": "portaled"
}
@ -105,8 +100,8 @@
},
{
"type": "Text",
"start": 150,
"end": 151,
"start": 57,
"end": 58,
"raw": "\n",
"data": "\n"
}
@ -116,212 +111,5 @@
]
},
"options": null,
"comments": [],
"instance": {
"type": "Script",
"start": 0,
"end": 103,
"context": "default",
"content": {
"type": "Program",
"start": 8,
"end": 94,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 9
}
},
"body": [
{
"type": "ImportDeclaration",
"start": 10,
"end": 51,
"loc": {
"start": {
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 42
}
},
"specifiers": [
{
"type": "ImportSpecifier",
"start": 19,
"end": 34,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 25
}
},
"imported": {
"type": "Identifier",
"start": 19,
"end": 34,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 25
}
},
"name": "createPortalKey"
},
"local": {
"type": "Identifier",
"start": 19,
"end": 34,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 25
}
},
"name": "createPortalKey"
}
}
],
"source": {
"type": "Literal",
"start": 42,
"end": 50,
"loc": {
"start": {
"line": 2,
"column": 33
},
"end": {
"line": 2,
"column": 41
}
},
"value": "svelte",
"raw": "'svelte'"
},
"attributes": []
},
{
"type": "VariableDeclaration",
"start": 54,
"end": 93,
"loc": {
"start": {
"line": 4,
"column": 1
},
"end": {
"line": 4,
"column": 40
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 60,
"end": 92,
"loc": {
"start": {
"line": 4,
"column": 7
},
"end": {
"line": 4,
"column": 39
}
},
"id": {
"type": "Identifier",
"start": 60,
"end": 63,
"loc": {
"start": {
"line": 4,
"column": 7
},
"end": {
"line": 4,
"column": 10
}
},
"name": "key"
},
"init": {
"type": "CallExpression",
"start": 66,
"end": 92,
"loc": {
"start": {
"line": 4,
"column": 13
},
"end": {
"line": 4,
"column": 39
}
},
"callee": {
"type": "Identifier",
"start": 66,
"end": 81,
"loc": {
"start": {
"line": 4,
"column": 13
},
"end": {
"line": 4,
"column": 28
}
},
"name": "createPortalKey"
},
"arguments": [
{
"type": "Literal",
"start": 82,
"end": 91,
"loc": {
"start": {
"line": 4,
"column": 29
},
"end": {
"line": 4,
"column": 38
}
},
"value": "example",
"raw": "'example'"
}
],
"optional": false
}
}
],
"kind": "const"
}
],
"sourceType": "module"
},
"attributes": []
}
"comments": []
}

@ -1,7 +1,4 @@
<script>
import { createPortalKey } from 'svelte';
const key = createPortalKey('example');
let target = $state(null);
</script>

@ -1,13 +1,7 @@
<script>
import { createPortalKey } from 'svelte';
const key = createPortalKey('example');
</script>
{#portal key}
{#portal 'example'}
<p>portaled</p>
{/portal}
<main>
{@portal key}
{@portal 'example'}
</main>

@ -1,13 +1,7 @@
<script>
import { createPortalKey } from 'svelte';
const key = createPortalKey('example');
</script>
<main>
{@portal key}
{@portal 'example'}
</main>
{#portal key}
{#portal 'example'}
<p>portaled</p>
{/portal}

@ -466,16 +466,6 @@ declare module 'svelte' {
render: () => string;
setup?: (element: Element) => void | (() => void);
}): Snippet<Params>;
/**
* Creates a key for use with `{#portal ...}` and `{@portal ...}`. It connects the portal source and outlet.
* Example: TODO write out once exact API clear.
* */
export function createPortalKey(name: string): PortalKey;
class PortalKey {
constructor(name: string);
v: string;
}
/** Anything except a function */
type NotFunction<T> = T extends Function ? never : T;
/**

Loading…
Cancel
Save