mirror of https://github.com/sveltejs/svelte
commit
29406c9f63
@ -0,0 +1,18 @@
|
||||
const svg_attributes =
|
||||
'accent-height accumulate additive alignment-baseline allowReorder alphabetic amplitude arabic-form ascent attributeName attributeType autoReverse azimuth baseFrequency baseline-shift baseProfile bbox begin bias by calcMode cap-height class clip clipPathUnits clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominant-baseline dur dx dy edgeMode elevation enable-background end exponent externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format from fr fx fy g1 g2 glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits hanging height href horiz-adv-x horiz-origin-x id ideographic image-rendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lang lengthAdjust letter-spacing lighting-color limitingConeAngle local marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask maskContentUnits maskUnits mathematical max media method min mode name numOctaves offset onabort onactivate onbegin onclick onend onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onrepeat onresize onscroll onunload opacity operator order orient orientation origin overflow overline-position overline-thickness panose-1 paint-order pathLength patternContentUnits patternTransform patternUnits pointer-events points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shape-rendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness string stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale systemLanguage tabindex tableValues target targetX targetY text-anchor text-decoration text-rendering textLength to transform type u1 u2 underline-position underline-thickness unicode unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical values version vert-adv-y vert-origin-x vert-origin-y viewBox viewTarget visibility width widths word-spacing writing-mode x x-height x1 x2 xChannelSelector xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y y1 y2 yChannelSelector z zoomAndPan'.split(
|
||||
' '
|
||||
);
|
||||
|
||||
const svg_attribute_lookup = new Map();
|
||||
|
||||
svg_attributes.forEach((name) => {
|
||||
svg_attribute_lookup.set(name.toLowerCase(), name);
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
export default function fix_attribute_casing(name) {
|
||||
name = name.toLowerCase();
|
||||
return svg_attribute_lookup.get(name) || name;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/** @import { Location } from 'locate-character' */
|
||||
/** @import { Namespace } from '#compiler' */
|
||||
/** @import { ComponentClientTransformState } from '../types.js' */
|
||||
/** @import { Node } from './types.js' */
|
||||
import { TEMPLATE_USE_MATHML, TEMPLATE_USE_SVG } from '../../../../../constants.js';
|
||||
import { dev, locator } from '../../../../state.js';
|
||||
import * as b from '../../../../utils/builders.js';
|
||||
|
||||
/**
|
||||
* @param {Node[]} nodes
|
||||
*/
|
||||
function build_locations(nodes) {
|
||||
const array = b.array([]);
|
||||
|
||||
for (const node of nodes) {
|
||||
if (node.type !== 'element') continue;
|
||||
|
||||
const { line, column } = /** @type {Location} */ (locator(node.start));
|
||||
|
||||
const expression = b.array([b.literal(line), b.literal(column)]);
|
||||
const children = build_locations(node.children);
|
||||
|
||||
if (children.elements.length > 0) {
|
||||
expression.elements.push(children);
|
||||
}
|
||||
|
||||
array.elements.push(expression);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ComponentClientTransformState} state
|
||||
* @param {Namespace} namespace
|
||||
* @param {number} [flags]
|
||||
*/
|
||||
export function transform_template(state, namespace, flags = 0) {
|
||||
const tree = state.options.fragments === 'tree';
|
||||
|
||||
const expression = tree ? state.template.as_tree() : state.template.as_html();
|
||||
|
||||
if (tree) {
|
||||
if (namespace === 'svg') flags |= TEMPLATE_USE_SVG;
|
||||
if (namespace === 'mathml') flags |= TEMPLATE_USE_MATHML;
|
||||
}
|
||||
|
||||
let call = b.call(
|
||||
tree ? `$.from_tree` : `$.from_${namespace}`,
|
||||
expression,
|
||||
flags ? b.literal(flags) : undefined
|
||||
);
|
||||
|
||||
if (state.template.contains_script_tag) {
|
||||
call = b.call(`$.with_script`, call);
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
call = b.call(
|
||||
'$.add_locations',
|
||||
call,
|
||||
b.member(b.id(state.analysis.name), '$.FILENAME', true),
|
||||
build_locations(state.template.nodes)
|
||||
);
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
/** @import { AST } from '#compiler' */
|
||||
/** @import { Node, Element } from './types'; */
|
||||
import { escape_html } from '../../../../../escaping.js';
|
||||
import { is_void } from '../../../../../utils.js';
|
||||
import * as b from '#compiler/builders';
|
||||
import fix_attribute_casing from './fix-attribute-casing.js';
|
||||
import { regex_starts_with_newline } from '../../../patterns.js';
|
||||
|
||||
export class Template {
|
||||
/**
|
||||
* `true` if HTML template contains a `<script>` tag. In this case we need to invoke a special
|
||||
* template instantiation function (see `create_fragment_with_script_from_html` for more info)
|
||||
*/
|
||||
contains_script_tag = false;
|
||||
|
||||
/** `true` if the HTML template needs to be instantiated with `importNode` */
|
||||
needs_import_node = false;
|
||||
|
||||
/** @type {Node[]} */
|
||||
nodes = [];
|
||||
|
||||
/** @type {Node[][]} */
|
||||
#stack = [this.nodes];
|
||||
|
||||
/** @type {Element | undefined} */
|
||||
#element;
|
||||
|
||||
#fragment = this.nodes;
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {number} start
|
||||
*/
|
||||
push_element(name, start) {
|
||||
this.#element = {
|
||||
type: 'element',
|
||||
name,
|
||||
attributes: {},
|
||||
children: [],
|
||||
start
|
||||
};
|
||||
|
||||
this.#fragment.push(this.#element);
|
||||
|
||||
this.#fragment = /** @type {Element} */ (this.#element).children;
|
||||
this.#stack.push(this.#fragment);
|
||||
}
|
||||
|
||||
/** @param {string} [data] */
|
||||
push_comment(data) {
|
||||
this.#fragment.push({ type: 'comment', data });
|
||||
}
|
||||
|
||||
/** @param {AST.Text[]} nodes */
|
||||
push_text(nodes) {
|
||||
this.#fragment.push({ type: 'text', nodes });
|
||||
}
|
||||
|
||||
pop_element() {
|
||||
this.#stack.pop();
|
||||
this.#fragment = /** @type {Node[]} */ (this.#stack.at(-1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {string | undefined} value
|
||||
*/
|
||||
set_prop(key, value) {
|
||||
/** @type {Element} */ (this.#element).attributes[key] = value;
|
||||
}
|
||||
|
||||
as_html() {
|
||||
return b.template([b.quasi(this.nodes.map(stringify).join(''), true)], []);
|
||||
}
|
||||
|
||||
as_tree() {
|
||||
// if the first item is a comment we need to add another comment for effect.start
|
||||
if (this.nodes[0].type === 'comment') {
|
||||
this.nodes.unshift({ type: 'comment', data: undefined });
|
||||
}
|
||||
|
||||
return b.array(this.nodes.map(objectify));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} item
|
||||
*/
|
||||
function stringify(item) {
|
||||
if (item.type === 'text') {
|
||||
return item.nodes.map((node) => node.raw).join('');
|
||||
}
|
||||
|
||||
if (item.type === 'comment') {
|
||||
return item.data ? `<!--${item.data}-->` : '<!>';
|
||||
}
|
||||
|
||||
let str = `<${item.name}`;
|
||||
|
||||
for (const key in item.attributes) {
|
||||
const value = item.attributes[key];
|
||||
|
||||
str += ` ${key}`;
|
||||
if (value !== undefined) str += `="${escape_html(value, true)}"`;
|
||||
}
|
||||
|
||||
if (is_void(item.name)) {
|
||||
str += '/>'; // XHTML compliance
|
||||
} else {
|
||||
str += `>`;
|
||||
str += item.children.map(stringify).join('');
|
||||
str += `</${item.name}>`;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/** @param {Node} item */
|
||||
function objectify(item) {
|
||||
if (item.type === 'text') {
|
||||
return b.literal(item.nodes.map((node) => node.data).join(''));
|
||||
}
|
||||
|
||||
if (item.type === 'comment') {
|
||||
return item.data ? b.array([b.literal(`// ${item.data}`)]) : null;
|
||||
}
|
||||
|
||||
const element = b.array([b.literal(item.name)]);
|
||||
|
||||
const attributes = b.object([]);
|
||||
|
||||
for (const key in item.attributes) {
|
||||
const value = item.attributes[key];
|
||||
|
||||
attributes.properties.push(
|
||||
b.prop(
|
||||
'init',
|
||||
b.key(fix_attribute_casing(key)),
|
||||
value === undefined ? b.void0 : b.literal(value)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (attributes.properties.length > 0 || item.children.length > 0) {
|
||||
element.elements.push(attributes.properties.length > 0 ? attributes : b.null);
|
||||
}
|
||||
|
||||
if (item.children.length > 0) {
|
||||
const children = item.children.map(objectify);
|
||||
element.elements.push(...children);
|
||||
|
||||
// special case — strip leading newline from `<pre>` and `<textarea>`
|
||||
if (item.name === 'pre' || item.name === 'textarea') {
|
||||
const first = children[0];
|
||||
if (first?.type === 'Literal') {
|
||||
first.value = /** @type {string} */ (first.value).replace(regex_starts_with_newline, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import type { AST } from '#compiler';
|
||||
|
||||
export interface Element {
|
||||
type: 'element';
|
||||
name: string;
|
||||
attributes: Record<string, string | undefined>;
|
||||
children: Node[];
|
||||
/** used for populating __svelte_meta */
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface Text {
|
||||
type: 'text';
|
||||
nodes: AST.Text[];
|
||||
}
|
||||
|
||||
export interface Comment {
|
||||
type: 'comment';
|
||||
data: string | undefined;
|
||||
}
|
||||
|
||||
export type Node = Element | Text | Comment;
|
@ -0,0 +1,23 @@
|
||||
/** @import { ClassBody, MemberExpression } from 'estree' */
|
||||
/** @import { Context } from '../types.js' */
|
||||
import * as b from '#compiler/builders';
|
||||
|
||||
/**
|
||||
* @param {MemberExpression} node
|
||||
* @param {Context} context
|
||||
*/
|
||||
export function MemberExpression(node, context) {
|
||||
if (
|
||||
context.state.analysis.runes &&
|
||||
node.object.type === 'ThisExpression' &&
|
||||
node.property.type === 'PrivateIdentifier'
|
||||
) {
|
||||
const field = context.state.state_fields?.get(`#${node.property.name}`);
|
||||
|
||||
if (field?.type === '$derived' || field?.type === '$derived.by') {
|
||||
return b.call(node);
|
||||
}
|
||||
}
|
||||
|
||||
context.next();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/** @param {string} html */
|
||||
export function create_fragment_from_html(html) {
|
||||
var elem = document.createElement('template');
|
||||
elem.innerHTML = html;
|
||||
elem.innerHTML = html.replaceAll('<!>', '<!---->'); // XHTML compliance
|
||||
return elem.content;
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
export type TemplateStructure =
|
||||
| string
|
||||
| undefined
|
||||
| [string, Record<string, string> | undefined, ...TemplateStructure[]];
|
@ -0,0 +1,76 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
warnings: [
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector ".\\61 sdf"',
|
||||
start: {
|
||||
line: 22,
|
||||
column: 1,
|
||||
character: 465
|
||||
},
|
||||
end: {
|
||||
line: 22,
|
||||
column: 10,
|
||||
character: 474
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector ".\\61\n\tsdf"',
|
||||
start: {
|
||||
line: 23,
|
||||
column: 1,
|
||||
character: 492
|
||||
},
|
||||
end: {
|
||||
line: 24,
|
||||
column: 4,
|
||||
character: 501
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector ".\\61\n sdf"',
|
||||
start: {
|
||||
line: 25,
|
||||
column: 1,
|
||||
character: 519
|
||||
},
|
||||
end: {
|
||||
line: 26,
|
||||
column: 4,
|
||||
character: 528
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector "#\\31span"',
|
||||
start: {
|
||||
line: 28,
|
||||
column: 1,
|
||||
character: 547
|
||||
},
|
||||
end: {
|
||||
line: 28,
|
||||
column: 9,
|
||||
character: 555
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector "#\\31 span"',
|
||||
start: {
|
||||
line: 29,
|
||||
column: 1,
|
||||
character: 573
|
||||
},
|
||||
end: {
|
||||
line: 29,
|
||||
column: 10,
|
||||
character: 582
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
@ -0,0 +1,21 @@
|
||||
#\31\32\33 .svelte-xyz{ color: green; }
|
||||
#\31 23.svelte-xyz { color: green; }
|
||||
#line\a break.svelte-xyz { color: green; }
|
||||
#line\a
|
||||
break.svelte-xyz { color: green; }
|
||||
#line\00000abreak.svelte-xyz { color: green; }
|
||||
#line\00000a break.svelte-xyz { color: green; }
|
||||
#line\00000a break.svelte-xyz { color: green; }
|
||||
.a\1f642 b.svelte-xyz { color: green; }
|
||||
|
||||
.\61sdf.svelte-xyz { color: green; }
|
||||
|
||||
/* (unused) .\61 sdf { color: red; }*/
|
||||
/* (unused) .\61
|
||||
sdf { color: red; }*/
|
||||
/* (unused) .\61
|
||||
sdf { color: red; }*/
|
||||
|
||||
/* (unused) #\31span { color: red; }*/
|
||||
/* (unused) #\31 span { color: red; }*/
|
||||
#\31 .svelte-xyz span:where(.svelte-xyz) { color: green; }
|
@ -0,0 +1,7 @@
|
||||
<div id="123" class="svelte-xyz"></div>
|
||||
<div class="svelte-xyz" id="line
|
||||
break"></div>
|
||||
<div class="a🙂b svelte-xyz"></div>
|
||||
<div class="asdf svelte-xyz"></div>
|
||||
<div class="asdf svelte-xyz"></div>
|
||||
<div id="1" class="svelte-xyz"><span class="svelte-xyz"></span></div>
|
@ -0,0 +1,31 @@
|
||||
<div id="123"></div>
|
||||
<div id="line
|
||||
break"></div>
|
||||
<div class="a🙂b"></div>
|
||||
<div class="asdf"></div>
|
||||
<div class="asdf"></div>
|
||||
<div id="1"><span></span></div>
|
||||
|
||||
<style>
|
||||
#\31\32\33 { color: green; }
|
||||
#\31 23 { color: green; }
|
||||
#line\a break { color: green; }
|
||||
#line\a
|
||||
break { color: green; }
|
||||
#line\00000abreak { color: green; }
|
||||
#line\00000a break { color: green; }
|
||||
#line\00000a break { color: green; }
|
||||
.a\1f642 b { color: green; }
|
||||
|
||||
.\61sdf { color: green; }
|
||||
|
||||
.\61 sdf { color: red; }
|
||||
.\61
|
||||
sdf { color: red; }
|
||||
.\61
|
||||
sdf { color: red; }
|
||||
|
||||
#\31span { color: red; }
|
||||
#\31 span { color: red; }
|
||||
#\31 span { color: green; }
|
||||
</style>
|
@ -0,0 +1,19 @@
|
||||
import { test } from '../../assert';
|
||||
const tick = () => Promise.resolve();
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
target.innerHTML = '<custom-element name="world"></custom-element>';
|
||||
await tick();
|
||||
/** @type {any} */
|
||||
const el = target.querySelector('custom-element');
|
||||
|
||||
assert.htmlEqual(
|
||||
el.shadowRoot.innerHTML,
|
||||
`
|
||||
<p>name: world</p>
|
||||
`
|
||||
);
|
||||
assert.equal(el.test, `test`);
|
||||
}
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
<svelte:options customElement={{
|
||||
tag: "custom-element",
|
||||
extend: (customClass)=>{
|
||||
return class extends customClass{
|
||||
public test: string = "test";
|
||||
}
|
||||
},
|
||||
}}/>
|
||||
|
||||
<script lang="ts">
|
||||
let { name } = $props();
|
||||
</script>
|
||||
|
||||
<p>name: {name}</p>
|
@ -0,0 +1,22 @@
|
||||
import { test } from '../../test';
|
||||
import { flushSync } from 'svelte';
|
||||
|
||||
export default test({
|
||||
html: `<button>toggle (false)</button>`,
|
||||
|
||||
async test({ assert, target, logs }) {
|
||||
assert.deepEqual(logs, ['up', { foo: false, bar: false }]);
|
||||
|
||||
const button = target.querySelector('button');
|
||||
|
||||
flushSync(() => button?.click());
|
||||
assert.deepEqual(logs, [
|
||||
'up',
|
||||
{ foo: false, bar: false },
|
||||
'down',
|
||||
{ foo: false, bar: false },
|
||||
'up',
|
||||
{ foo: true, bar: true }
|
||||
]);
|
||||
}
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
let foo = $state(false)
|
||||
let bar = $derived(foo)
|
||||
|
||||
$effect(() => {
|
||||
console.log('up', { foo, bar });
|
||||
|
||||
return () =>{
|
||||
console.log('down', { foo, bar });
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<button onclick={() => foo = !foo}>toggle ({foo})</button>
|
@ -0,0 +1,20 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
import { expect, vi } from 'vitest';
|
||||
|
||||
const handler = vi.fn();
|
||||
|
||||
export default test({
|
||||
props: {
|
||||
handler
|
||||
},
|
||||
async test({ target }) {
|
||||
const button = target.querySelector('button');
|
||||
const video = target.querySelector('video');
|
||||
|
||||
button?.click();
|
||||
flushSync();
|
||||
video?.dispatchEvent(new Event('someevent'));
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
}
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
const { handler } = $props();
|
||||
let show = $state(true);
|
||||
</script>
|
||||
|
||||
<button onclick={() => show = false}>show/hide</button>
|
||||
{#if show}
|
||||
<video onsomeevent={handler}></video>
|
||||
{/if}
|
@ -0,0 +1,9 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
fragments: 'tree'
|
||||
},
|
||||
|
||||
html: `<p>hello</p>`
|
||||
});
|
@ -0,0 +1 @@
|
||||
<p>hello</p>
|
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
warnings: [
|
||||
'The `value` property of a `<select multiple>` element should be an array, but it received a non-array value. The selection will be kept as is.'
|
||||
]
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
<select multiple value={null}>
|
||||
<option>option</option>
|
||||
</select>
|
||||
<select multiple value={undefined}>
|
||||
<option>option</option>
|
||||
</select>
|
||||
<select multiple value={123}>
|
||||
<option>option</option>
|
||||
</select>
|
@ -0,0 +1,7 @@
|
||||
<h2>hello from component</h2>
|
||||
|
||||
<style>
|
||||
h2 {
|
||||
color: var(--color);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,42 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true
|
||||
},
|
||||
|
||||
html: `
|
||||
<h1>hello</h1>
|
||||
<svelte-css-wrapper style="display: contents; --color: red;">
|
||||
<h2 class="svelte-13kae5a">hello from component</h2>
|
||||
</svelte-css-wrapper>
|
||||
<p>goodbye</p>
|
||||
`,
|
||||
|
||||
async test({ target, assert }) {
|
||||
const h1 = target.querySelector('h1');
|
||||
const h2 = target.querySelector('h2');
|
||||
const p = target.querySelector('p');
|
||||
|
||||
// @ts-expect-error
|
||||
assert.deepEqual(h1.__svelte_meta.loc, {
|
||||
file: 'main.svelte',
|
||||
line: 5,
|
||||
column: 0
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
assert.deepEqual(h2.__svelte_meta.loc, {
|
||||
file: 'Component.svelte',
|
||||
line: 1,
|
||||
column: 0
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
assert.deepEqual(p.__svelte_meta.loc, {
|
||||
file: 'main.svelte',
|
||||
line: 7,
|
||||
column: 0
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import Component from './Component.svelte';
|
||||
</script>
|
||||
|
||||
<h1>hello</h1>
|
||||
<Component --color="red" />
|
||||
<p>goodbye</p>
|
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `3 3 3 3`
|
||||
});
|
@ -0,0 +1,29 @@
|
||||
<script>
|
||||
class X {
|
||||
x = $state(1);
|
||||
on_class = $derived(this.x * 2);
|
||||
#on_class_private = $derived(this.x * 2);
|
||||
#in_constructor_private
|
||||
|
||||
constructor() {
|
||||
this.#in_constructor_private = $derived(this.x * 2);
|
||||
this.in_constructor = $derived(this.x * 2);
|
||||
this.#on_class_private = 3;
|
||||
this.#in_constructor_private = 3;
|
||||
}
|
||||
|
||||
get on_class_private() {
|
||||
return this.#on_class_private;
|
||||
}
|
||||
|
||||
get in_constructor_private() {
|
||||
return this.#in_constructor_private;
|
||||
}
|
||||
}
|
||||
|
||||
const x = new X();
|
||||
x.on_class = 3;
|
||||
x.in_constructor = 3;
|
||||
</script>
|
||||
|
||||
{x.on_class} {x.in_constructor} {x.on_class_private} {x.in_constructor_private}
|
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
fragments: 'tree'
|
||||
}
|
||||
});
|
@ -0,0 +1,25 @@
|
||||
import 'svelte/internal/disclose-version';
|
||||
import 'svelte/internal/flags/legacy';
|
||||
import * as $ from 'svelte/internal/client';
|
||||
|
||||
var root = $.from_tree(
|
||||
[
|
||||
['h1', null, 'hello'],
|
||||
' ',
|
||||
[
|
||||
'div',
|
||||
{ class: 'potato' },
|
||||
['p', null, 'child element'],
|
||||
' ',
|
||||
['p', null, 'another child element']
|
||||
]
|
||||
],
|
||||
1
|
||||
);
|
||||
|
||||
export default function Functional_templating($$anchor) {
|
||||
var fragment = root();
|
||||
|
||||
$.next(2);
|
||||
$.append($$anchor, fragment);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import * as $ from 'svelte/internal/server';
|
||||
|
||||
export default function Functional_templating($$payload) {
|
||||
$$payload.out += `<h1>hello</h1> <div class="potato"><p>child element</p> <p>another child element</p></div>`;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<h1>hello</h1>
|
||||
|
||||
<div class="potato">
|
||||
<p>child element</p>
|
||||
<p>another child element</p>
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue