Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
de8a38b
feat: templateless template generation
paoloricciuti Mar 18, 2025
575908a
fix: auto import fumble
paoloricciuti Mar 18, 2025
8a737f1
feat: add option `preventTemplateCloning` and functions transformation
paoloricciuti Mar 18, 2025
7c7a857
feat: make all tests pass with functional templates
paoloricciuti Mar 20, 2025
8424395
chore: remove `prevent-template-cloning` test
paoloricciuti Mar 20, 2025
c75c429
chore: run test suite on both `functional` and `string` templating
paoloricciuti Mar 20, 2025
64219ed
chore: change options from `boolean` to `list` (templatingMode: "func…
paoloricciuti Mar 20, 2025
95ce311
chore: revert unneeded change to `package.json`
paoloricciuti Mar 20, 2025
59902cc
chore: simplify `process_children`
paoloricciuti Mar 20, 2025
132ea2b
Merge remote-tracking branch 'origin/main' into templateless-template…
paoloricciuti Mar 20, 2025
403b17e
chore: update snapshots
paoloricciuti Mar 20, 2025
ba237c7
chore: don't write different `rendered`
paoloricciuti Mar 20, 2025
4daa63a
fix: snapshot test runner
paoloricciuti Mar 20, 2025
72f93e3
chore: sprinkle comments here and there
paoloricciuti Mar 21, 2025
ad56847
fix: silly goose am i 🪿
paoloricciuti Mar 21, 2025
d8afd8e
fix (this broke the sandbox)
Rich-Harris Mar 21, 2025
a48df4a
Merge remote-tracking branch 'origin/main' into templateless-template…
paoloricciuti Mar 24, 2025
be39867
chore: alterative functional templating syntax (#15599)
paoloricciuti Apr 1, 2025
eaf2aaf
Merge branch 'main' into templateless-template-generation
Rich-Harris Apr 17, 2025
97817a9
fix snapshot tests
Rich-Harris Apr 17, 2025
15c6306
Merge remote-tracking branch 'origin/main' into templateless-template…
paoloricciuti Apr 22, 2025
084f7f9
chore: update purity snapshot
paoloricciuti Apr 22, 2025
084e313
chore: update purity snapshot, this time in the proper way
paoloricciuti Apr 22, 2025
d294a66
chore: add `each-index-non-null` snapshot
paoloricciuti Apr 22, 2025
2d0db55
Merge remote-tracking branch 'origin/main' into templateless-template…
paoloricciuti Apr 22, 2025
7f732bf
chore: remove export of `seen`
paoloricciuti May 21, 2025
d3ee992
fix: revert exporting `seen`
paoloricciuti May 21, 2025
2e24fdc
chore: use more sane to-string code
paoloricciuti May 21, 2025
67183ce
Merge branch 'main' into templateless-template-generation
Rich-Harris May 21, 2025
173a7f7
update snapshots
Rich-Harris May 21, 2025
d9d24a2
this is already copied, no need to do it explicitly
Rich-Harris May 21, 2025
5b1f5e5
do the escaping inside `template_to_string`
Rich-Harris May 21, 2025
1c4503c
Apply suggestions from code review
Rich-Harris May 21, 2025
e81c669
chore: refactor `to-functions` to be sane
paoloricciuti May 21, 2025
324bd8a
use proper discriminated unions (TODO replace args with node-specific…
Rich-Harris May 21, 2025
4a3fc9d
remove instruction.args
Rich-Harris May 21, 2025
76d05e0
make process_children unaware of templating mode - the less visitors …
Rich-Harris May 21, 2025
22cf914
generate functional output in sandbox
Rich-Harris May 21, 2025
a9f2d6f
tidy up
Rich-Harris May 21, 2025
36c01ca
fix
Rich-Harris May 21, 2025
68de6b4
no longer need to pass `is_functional_template_mode` to `clean_nodes`
Rich-Harris May 21, 2025
d9237e2
simplify state
Rich-Harris May 21, 2025
17f1b6a
WIP
Rich-Harris May 21, 2025
1e6d85b
fixes
Rich-Harris May 21, 2025
f677792
fix
Rich-Harris May 21, 2025
a59f18a
fix
Rich-Harris May 21, 2025
8c819e5
unused
Rich-Harris May 21, 2025
448cff1
remove indirection
Rich-Harris May 21, 2025
747d24a
lint
Rich-Harris May 21, 2025
60813bc
tweak
Rich-Harris May 21, 2025
3afd814
tweak
Rich-Harris May 21, 2025
9106533
doh
Rich-Harris May 21, 2025
310f82d
move stuff off `state.metadata.context` and onto `state.template`
Rich-Harris May 21, 2025
98fa3c0
simplify
Rich-Harris May 21, 2025
f36df5f
remove unused arg
Rich-Harris May 21, 2025
ab5f15c
tweak
Rich-Harris May 21, 2025
bcc11ce
tweak
Rich-Harris May 21, 2025
92cc175
merge main
Rich-Harris May 21, 2025
af78465
unused
Rich-Harris May 21, 2025
40be734
put locations on template, instead of on the side
Rich-Harris May 22, 2025
7edf0c2
simplify
Rich-Harris May 22, 2025
941f266
simplify
Rich-Harris May 22, 2025
faf1822
optimise for the common case
Rich-Harris May 22, 2025
d8637fb
tweak
Rich-Harris May 22, 2025
84f15d0
tweak
Rich-Harris May 22, 2025
1be9120
tweak
Rich-Harris May 22, 2025
07aed41
colocate
Rich-Harris May 22, 2025
4039f9e
remove test duplication
Rich-Harris May 22, 2025
546fa28
more
Rich-Harris May 22, 2025
93c4d84
tweak
Rich-Harris May 22, 2025
99b7afc
undo
Rich-Harris May 22, 2025
78e3405
undo
Rich-Harris May 22, 2025
0cb475e
undo
Rich-Harris May 22, 2025
f432305
one snapshot test is probably enough
Rich-Harris May 22, 2025
32d2b4c
add a runtime test, we can always add more later if we need to
Rich-Harris May 22, 2025
19fae20
push on create
Rich-Harris May 22, 2025
408955d
rename stuff
Rich-Harris May 22, 2025
7d1551b
use function composition
Rich-Harris May 22, 2025
fa8e1ef
simplify
Rich-Harris May 22, 2025
dfde459
deduplicate stuff
Rich-Harris May 22, 2025
4ba3853
update names
Rich-Harris May 22, 2025
5884b8f
small tweak
Rich-Harris May 22, 2025
a86e52b
XHTML compliance
Rich-Harris May 22, 2025
27848a5
update snapshots
Rich-Harris May 22, 2025
7ac936f
update sandbox
Rich-Harris May 22, 2025
5a748f9
fix tests
Rich-Harris May 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: run test suite on both functional and string templating
  • Loading branch information
paoloricciuti committed Mar 20, 2025
commit c75c42949b3364d74089f1912900a7901f4079b4
2 changes: 1 addition & 1 deletion 2 packages/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@sveltejs/acorn-typescript": "^1.0.5",
"@types/estree": "^1.0.5",
"acorn": "^8.12.1",
"@sveltejs/acorn-typescript": "^1.0.5",
"aria-query": "^5.3.1",
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
Expand Down
2 changes: 1 addition & 1 deletion 2 packages/svelte/src/internal/server/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { current_component } from './context.js';
let parent = null;

/** @type {Set<string>} */
let seen;
export let seen;
paoloricciuti marked this conversation as resolved.
Outdated
Show resolved Hide resolved

/**
* @param {Element} element
Expand Down
9 changes: 6 additions & 3 deletions 9 packages/svelte/tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ export function create_deferred() {
* @param {Partial<CompileOptions>} compileOptions
* @param {boolean} [output_map]
* @param {any} [preprocessor]
* @param {import('./suite').TemplatingMode} [templating_mode]
*/
export async function compile_directory(
cwd,
generate,
compileOptions = {},
output_map = false,
preprocessor
preprocessor,
templating_mode
) {
const output_dir = `${cwd}/_output/${generate}`;
const output_dir = `${cwd}/_output/${generate}${templating_mode === 'functional' ? `-${templating_mode}` : ''}`;

fs.rmSync(output_dir, { recursive: true, force: true });

Expand All @@ -77,7 +79,8 @@ export async function compile_directory(
let opts = {
filename: path.join(cwd, file),
...compileOptions,
generate
generate,
preventTemplateCloning: templating_mode === 'functional'
};

if (file.endsWith('.js')) {
Expand Down
29 changes: 24 additions & 5 deletions 29 packages/svelte/tests/hydration/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,24 @@ function read(path: string): string | void {
return fs.existsSync(path) ? fs.readFileSync(path, 'utf-8') : undefined;
}

const { test, run } = suite<HydrationTest>(async (config, cwd) => {
const { test, run } = suite<HydrationTest>(async (config, cwd, templating_mode) => {
if (!config.load_compiled) {
await compile_directory(cwd, 'client', { accessors: true, ...config.compileOptions });
await compile_directory(cwd, 'server', config.compileOptions);
await compile_directory(
cwd,
'client',
{ accessors: true, ...config.compileOptions },
undefined,
undefined,
templating_mode
);
await compile_directory(
cwd,
'server',
config.compileOptions,
undefined,
undefined,
templating_mode
);
}

const target = window.document.body;
Expand Down Expand Up @@ -102,7 +116,11 @@ const { test, run } = suite<HydrationTest>(async (config, cwd) => {
};

const component = createClassComponent({
component: (await import(`${cwd}/_output/client/main.svelte.js`)).default,
component: (
await import(
`${cwd}/_output/client${templating_mode === 'functional' ? '-functional' : ''}/main.svelte.js`
)
).default,
target,
hydrate: true,
props: config.props,
Expand Down Expand Up @@ -169,4 +187,5 @@ const { test, run } = suite<HydrationTest>(async (config, cwd) => {
});
export { test, assert_ok };

await run(__dirname);
await run(__dirname, 'string');
await run(__dirname, 'functional');
Rich-Harris marked this conversation as resolved.
Outdated
Show resolved Hide resolved
44 changes: 32 additions & 12 deletions 44 packages/svelte/tests/runtime-browser/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as fs from 'node:fs';
import * as path from 'node:path';
import { compile } from 'svelte/compiler';
import { afterAll, assert, beforeAll, describe } from 'vitest';
import { suite, suite_with_variants } from '../suite';
import { suite, suite_with_variants, type TemplatingMode } from '../suite';
import { write } from '../helpers';
import type { Warning } from '#compiler';

Expand Down Expand Up @@ -35,35 +35,50 @@ const { run: run_browser_tests } = suite_with_variants<
return false;
},
() => {},
async (config, test_dir, variant) => {
await run_test(test_dir, config, variant === 'hydrate');
async (config, test_dir, variant, _, templating_mode) => {
await run_test(test_dir, config, variant === 'hydrate', templating_mode);
}
);

describe.concurrent(
'runtime-browser',
() => run_browser_tests(__dirname),
() => run_browser_tests(__dirname, 'string'),
// Browser tests are brittle and slow on CI
{ timeout: 20000, retry: process.env.CI ? 1 : 0 }
);

describe.concurrent(
'runtime-browser-functional',
() => run_browser_tests(__dirname, 'functional'),
// Browser tests are brittle and slow on CI
{ timeout: 20000, retry: process.env.CI ? 1 : 0 }
);

const { run: run_ce_tests } = suite<ReturnType<typeof import('./assert').test>>(
async (config, test_dir) => {
await run_test(test_dir, config, false);
async (config, test_dir, templating_mode) => {
await run_test(test_dir, config, false, templating_mode);
}
);

describe.concurrent(
'custom-elements',
() => run_ce_tests(__dirname, 'custom-elements-samples'),
() => run_ce_tests(__dirname, 'string', 'custom-elements-samples'),
// Browser tests are brittle and slow on CI
{ timeout: 20000, retry: process.env.CI ? 1 : 0 }
);

describe.concurrent(
'custom-elements',
() => run_ce_tests(__dirname, 'functional', 'custom-elements-samples'),
// Browser tests are brittle and slow on CI
{ timeout: 20000, retry: process.env.CI ? 1 : 0 }
);

async function run_test(
test_dir: string,
config: ReturnType<typeof import('./assert').test>,
hydrate: boolean
hydrate: boolean,
templating_mode: TemplatingMode
) {
const warnings: any[] = [];

Expand All @@ -90,10 +105,14 @@ async function run_test(
...config.compileOptions,
immutable: config.immutable,
customElement: test_dir.includes('custom-elements-samples'),
accessors: 'accessors' in config ? config.accessors : true
accessors: 'accessors' in config ? config.accessors : true,
preventTemplateCloning: templating_mode === 'functional'
});

write(`${test_dir}/_output/client/${path.basename(args.path)}.js`, compiled.js.code);
write(
`${test_dir}/_output/client${templating_mode === 'functional' ? '-functional' : ''}/${path.basename(args.path)}.js`,
compiled.js.code
);

compiled.warnings.forEach((warning) => {
if (warning.code === 'options_deprecated_accessors') return;
Expand All @@ -103,7 +122,7 @@ async function run_test(
if (compiled.css !== null) {
compiled.js.code += `document.head.innerHTML += \`<style>${compiled.css.code}</style>\``;
write(
`${test_dir}/_output/client/${path.basename(args.path)}.css`,
`${test_dir}/_output/${templating_mode === 'functional' ? '-functional' : ''}/${path.basename(args.path)}.css`,
compiled.css.code
);
}
Expand Down Expand Up @@ -151,7 +170,8 @@ async function run_test(
...config.compileOptions,
immutable: config.immutable,
customElement: test_dir.includes('custom-elements-samples'),
accessors: 'accessors' in config ? config.accessors : true
accessors: 'accessors' in config ? config.accessors : true,
preventTemplateCloning: templating_mode === 'functional'
});

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
this.innerHTML = 'Hello ' + this._obj.text + '!';
}
}

window.customElements.define('my-custom-element', MyCustomElement);
if(!window.customElements.get('my-custom-element')) {
window.customElements.define('my-custom-element', MyCustomElement);
}
</script>

<my-custom-element camelCase={{ text: 'World' }} />
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
}

class Extended extends MyCustomElement {}

window.customElements.define('my-custom-inheritance-element', Extended);

if(!window.customElements.get('my-custom-inheritance-element')) {
window.customElements.define('my-custom-inheritance-element', Extended);
}
</script>

<my-custom-inheritance-element camelCase={{ text: 'World' }} text="!" />
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default test({
Object.defineProperties(window, {
scrollY: {
value: 0,
configurable: true
configurable: true,
writable: true
}
});
original_scrollTo = window.scrollTo;
Expand Down
53 changes: 39 additions & 14 deletions 53 packages/svelte/tests/runtime-legacy/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { compile_directory } from '../helpers.js';
import { setup_html_equal } from '../html_equal.js';
import { raf } from '../animation-helpers.js';
import type { CompileOptions } from '#compiler';
import { suite_with_variants, type BaseTest } from '../suite.js';
import { suite_with_variants, type BaseTest, type TemplatingMode } from '../suite.js';
import { seen } from '../../src/internal/server/dev.js';

type Assert = typeof import('vitest').assert & {
htmlEqual(a: string, b: string, description?: string): void;
Expand Down Expand Up @@ -141,16 +142,21 @@ export function runtime_suite(runes: boolean) {

return false;
},
(config, cwd) => {
return common_setup(cwd, runes, config);
(config, cwd, templating_mode) => {
return common_setup(cwd, runes, config, templating_mode);
},
async (config, cwd, variant, common) => {
await run_test_variant(cwd, config, variant, common, runes);
async (config, cwd, variant, common, templating_mode) => {
await run_test_variant(cwd, config, variant, common, runes, templating_mode);
}
);
}

async function common_setup(cwd: string, runes: boolean | undefined, config: RuntimeTest) {
async function common_setup(
cwd: string,
runes: boolean | undefined,
config: RuntimeTest,
templating_mode: TemplatingMode
) {
const force_hmr = process.env.HMR && config.compileOptions?.dev !== false && !config.error;

const compileOptions: CompileOptions = {
Expand All @@ -161,13 +167,14 @@ async function common_setup(cwd: string, runes: boolean | undefined, config: Run
...config.compileOptions,
immutable: config.immutable,
accessors: 'accessors' in config ? config.accessors : true,
runes
runes,
preventTemplateCloning: templating_mode === 'functional'
};

// load_compiled can be used for debugging a test. It means the compiler will not run on the input
// so you can manipulate the output manually to see what fixes it, adding console.logs etc.
if (!config.load_compiled) {
await compile_directory(cwd, 'client', compileOptions);
await compile_directory(cwd, 'client', compileOptions, undefined, undefined, templating_mode);
await compile_directory(cwd, 'server', compileOptions);
}

Expand All @@ -179,7 +186,8 @@ async function run_test_variant(
config: RuntimeTest,
variant: 'dom' | 'hydrate' | 'ssr',
compileOptions: CompileOptions,
runes: boolean
runes: boolean,
templating_mode: TemplatingMode
) {
let unintended_error = false;

Expand Down Expand Up @@ -257,8 +265,15 @@ async function run_test_variant(
raf.reset();

// Put things we need on window for testing
const styles = globSync('**/*.css', { cwd: `${cwd}/_output/client` })
.map((file) => fs.readFileSync(`${cwd}/_output/client/${file}`, 'utf-8'))
const styles = globSync('**/*.css', {
cwd: `${cwd}/_output/client${templating_mode === 'functional' ? '-functional' : ''}`
})
.map((file) =>
fs.readFileSync(
`${cwd}/_output/client${templating_mode === 'functional' ? '-functional' : ''}/${file}`,
'utf-8'
)
)
.join('\n')
.replace(/\/\*<\/?style>\*\//g, '');

Expand All @@ -274,26 +289,36 @@ async function run_test_variant(

globalThis.requestAnimationFrame = globalThis.setTimeout;

let mod = await import(`${cwd}/_output/client/main.svelte.js`);
let mod = await import(
`${cwd}/_output/client${templating_mode === 'functional' ? '-functional' : ''}/main.svelte.js`
);

const target = window.document.querySelector('main') as HTMLElement;

let snapshot = undefined;

if (variant === 'hydrate' || variant === 'ssr') {
config.before_test?.();
// we need to clear the seen messages between tests
seen?.clear?.();
// ssr into target
const SsrSvelteComponent = (await import(`${cwd}/_output/server/main.svelte.js`)).default;
const { html, head } = render(SsrSvelteComponent, {
props: config.server_props ?? config.props ?? {},
idPrefix: config.id_prefix
});

fs.writeFileSync(`${cwd}/_output/rendered.html`, html);
fs.writeFileSync(
`${cwd}/_output/rendered${templating_mode === 'functional' ? '-functional' : ''}.html`,
html
);
target.innerHTML = html;

if (head) {
fs.writeFileSync(`${cwd}/_output/rendered_head.html`, head);
fs.writeFileSync(
`${cwd}/_output/rendered_head${templating_mode === 'functional' ? '-functional' : ''}.html`,
head
);
window.document.head.innerHTML = window.document.head.innerHTML + head;
}

Expand Down
3 changes: 2 additions & 1 deletion 3 packages/svelte/tests/runtime-legacy/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ const { test, run } = runtime_suite(false);

export { test, ok };

await run(__dirname);
await run(__dirname, 'string');
await run(__dirname, 'functional');
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<script module>
customElements.define('value-element', class extends HTMLElement {
if(!customElements.get('value-element')) {
customElements.define('value-element', class extends HTMLElement {

constructor() {
super();
this.attachShadow({ mode: 'open' });
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
}

set value(v) {
if (this.__value !== v) {
this.__value = v;
this.shadowRoot.innerHTML = `<span>${v}</span>`;
}
}
});
set value(v) {
if (this.__value !== v) {
this.__value = v;
this.shadowRoot.innerHTML = `<span>${v}</span>`;
}
}
});
}
</script>

<my-element string="test" object={{ test: true }}></my-element>
Expand Down
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.