mirror of https://github.com/sveltejs/svelte
commit
fa4d3730f9
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: correctly compile $effect.root in svelte modules
|
||||||
@ -1,74 +0,0 @@
|
|||||||
export const reserved = [
|
|
||||||
'arguments',
|
|
||||||
'await',
|
|
||||||
'break',
|
|
||||||
'case',
|
|
||||||
'catch',
|
|
||||||
'class',
|
|
||||||
'const',
|
|
||||||
'continue',
|
|
||||||
'debugger',
|
|
||||||
'default',
|
|
||||||
'delete',
|
|
||||||
'do',
|
|
||||||
'else',
|
|
||||||
'enum',
|
|
||||||
'eval',
|
|
||||||
'export',
|
|
||||||
'extends',
|
|
||||||
'false',
|
|
||||||
'finally',
|
|
||||||
'for',
|
|
||||||
'function',
|
|
||||||
'if',
|
|
||||||
'implements',
|
|
||||||
'import',
|
|
||||||
'in',
|
|
||||||
'instanceof',
|
|
||||||
'interface',
|
|
||||||
'let',
|
|
||||||
'new',
|
|
||||||
'null',
|
|
||||||
'package',
|
|
||||||
'private',
|
|
||||||
'protected',
|
|
||||||
'public',
|
|
||||||
'return',
|
|
||||||
'static',
|
|
||||||
'super',
|
|
||||||
'switch',
|
|
||||||
'this',
|
|
||||||
'throw',
|
|
||||||
'true',
|
|
||||||
'try',
|
|
||||||
'typeof',
|
|
||||||
'var',
|
|
||||||
'void',
|
|
||||||
'while',
|
|
||||||
'with',
|
|
||||||
'yield'
|
|
||||||
];
|
|
||||||
|
|
||||||
const void_element_names = [
|
|
||||||
'area',
|
|
||||||
'base',
|
|
||||||
'br',
|
|
||||||
'col',
|
|
||||||
'command',
|
|
||||||
'embed',
|
|
||||||
'hr',
|
|
||||||
'img',
|
|
||||||
'input',
|
|
||||||
'keygen',
|
|
||||||
'link',
|
|
||||||
'meta',
|
|
||||||
'param',
|
|
||||||
'source',
|
|
||||||
'track',
|
|
||||||
'wbr'
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @param {string} name */
|
|
||||||
export function is_void(name) {
|
|
||||||
return void_element_names.includes(name) || name.toLowerCase() === '!doctype';
|
|
||||||
}
|
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
html: '<button>0</button><button>0</button><button>cleanup</button>',
|
||||||
|
|
||||||
|
async test({ assert, target, logs }) {
|
||||||
|
const [b1, b2, b3] = target.querySelectorAll('button');
|
||||||
|
|
||||||
|
flushSync(() => {
|
||||||
|
b1.click();
|
||||||
|
b2.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(logs, [0, 1]);
|
||||||
|
|
||||||
|
flushSync(() => {
|
||||||
|
b3.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(logs, [0, 1, 'cleanup 1', 'cleanup 2']);
|
||||||
|
|
||||||
|
flushSync(() => {
|
||||||
|
b1.click();
|
||||||
|
b2.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(logs, [0, 1, 'cleanup 1', 'cleanup 2']);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
import { with_root } from './root.svelte.js';
|
||||||
|
let x = $state(0);
|
||||||
|
let y = $state(0);
|
||||||
|
|
||||||
|
const cleanup = with_root(() => x)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => x++}>{x}</button>
|
||||||
|
<button onclick={() => y++}>{y}</button>
|
||||||
|
<button onclick={cleanup}>cleanup</button>
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
export function with_root(get_x) {
|
||||||
|
const cleanup = $effect.root(() => {
|
||||||
|
$effect(() => {
|
||||||
|
console.log(get_x());
|
||||||
|
});
|
||||||
|
|
||||||
|
const nested_cleanup = $effect.root(() => {
|
||||||
|
return () => {
|
||||||
|
console.log('cleanup 2');
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
console.log('cleanup 1');
|
||||||
|
nested_cleanup();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return cleanup;
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
// Ensure we don't use any methods that are not available in all browser for a long period of time
|
||||||
|
// so that people don't need to polyfill them. Example array.at(...) was introduced to Safari only in 2022
|
||||||
|
"target": "es2021",
|
||||||
|
"lib": ["es2021", "DOM", "DOM.Iterable"],
|
||||||
|
"types": [] // prevent automatic inclusion of @types/node
|
||||||
|
},
|
||||||
|
"include": ["./src/"],
|
||||||
|
// Compiler is allowed to use more recent methods; people using it in the browser are expected to know
|
||||||
|
// how to polyfill missing methods. Also make sure to not include test files as these include Vitest
|
||||||
|
// which then loads node globals.
|
||||||
|
"exclude": ["./src/compiler/**/*", "./src/**/*.test.ts"]
|
||||||
|
}
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import { mount, hydrate, unmount } from 'svelte';
|
|
||||||
import App from './src/main.svelte';
|
|
||||||
|
|
||||||
const root = document.getElementById('root')!;
|
|
||||||
const render = root.firstChild?.nextSibling ? hydrate : mount;
|
|
||||||
|
|
||||||
const component = render(App, {
|
|
||||||
target: document.getElementById('root')!,
|
|
||||||
recover: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
window.unmount = () => unmount(component);
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
import fs from 'node:fs';
|
|
||||||
import path from 'node:path';
|
|
||||||
import { fileURLToPath } from 'node:url';
|
|
||||||
import polka from 'polka';
|
|
||||||
import { createServer as createViteServer } from 'vite';
|
|
||||||
|
|
||||||
const PORT = process.env.PORT || '5173';
|
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
process.env.NODE_ENV = 'development';
|
|
||||||
|
|
||||||
async function createServer() {
|
|
||||||
const app = polka();
|
|
||||||
|
|
||||||
const vite = await createViteServer({
|
|
||||||
server: { middlewareMode: true },
|
|
||||||
appType: 'custom'
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(vite.middlewares);
|
|
||||||
|
|
||||||
app.use('*', async (req, res) => {
|
|
||||||
if (req.originalUrl !== '/') {
|
|
||||||
const file = path.resolve('./dist' + req.originalUrl);
|
|
||||||
if (fs.existsSync(file)) {
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'application/javascript'
|
|
||||||
});
|
|
||||||
res.end(fs.createReadStream(file));
|
|
||||||
} else {
|
|
||||||
res.writeHead(404);
|
|
||||||
res.end('not found');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8');
|
|
||||||
const transformed_template = await vite.transformIndexHtml(req.originalUrl, template);
|
|
||||||
const { render } = await vite.ssrLoadModule('svelte/server');
|
|
||||||
const { default: App } = await vite.ssrLoadModule('./src/main.svelte');
|
|
||||||
const { head, body } = render(App);
|
|
||||||
|
|
||||||
const html = transformed_template
|
|
||||||
.replace(`<!--ssr-head-->`, head)
|
|
||||||
.replace(`<!--ssr-body-->`, body);
|
|
||||||
|
|
||||||
res.writeHead(200, { 'Content-Type': 'text/html' }).end(html);
|
|
||||||
});
|
|
||||||
|
|
||||||
return { app, vite };
|
|
||||||
}
|
|
||||||
|
|
||||||
createServer()
|
|
||||||
.then(({ app }) =>
|
|
||||||
app.listen(PORT, () => {
|
|
||||||
console.log(`http://localhost:${PORT}`);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('Error Starting Server:\n', err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
import fs from 'node:fs';
|
|
||||||
import path from 'node:path';
|
|
||||||
import express from 'express';
|
|
||||||
import { head, body } from './server/entry-server.js';
|
|
||||||
|
|
||||||
const rendered = fs
|
|
||||||
.readFileSync(path.resolve('./dist/client/index.html'), 'utf-8')
|
|
||||||
.replace(`<!--ssr-html-->`, body)
|
|
||||||
.replace(`<!--ssr-head-->`, head);
|
|
||||||
|
|
||||||
express()
|
|
||||||
.use('*', async (req, res) => {
|
|
||||||
if (req.originalUrl !== '/') {
|
|
||||||
res.sendFile(path.resolve('./dist/client' + req.originalUrl));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status(200).set({ 'Content-Type': 'text/html' }).end(rendered);
|
|
||||||
})
|
|
||||||
.listen('3000');
|
|
||||||
|
|
||||||
console.log('listening on http://localhost:3000');
|
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
// @ts-check
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import polka from 'polka';
|
||||||
|
import { createServer as createViteServer } from 'vite';
|
||||||
|
import { render } from 'svelte/server';
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || '5173';
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
process.env.NODE_ENV = 'development';
|
||||||
|
|
||||||
|
const vite = await createViteServer({
|
||||||
|
server: { middlewareMode: true },
|
||||||
|
appType: 'custom'
|
||||||
|
});
|
||||||
|
|
||||||
|
polka()
|
||||||
|
.use(vite.middlewares)
|
||||||
|
.use(async (req, res) => {
|
||||||
|
const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8');
|
||||||
|
const transformed_template = await vite.transformIndexHtml(req.url, template);
|
||||||
|
const { default: App } = await vite.ssrLoadModule('./src/main.svelte');
|
||||||
|
const { head, body } = render(App);
|
||||||
|
|
||||||
|
const html = transformed_template
|
||||||
|
.replace(`<!--ssr-head-->`, head)
|
||||||
|
.replace(`<!--ssr-body-->`, body);
|
||||||
|
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/html' }).end(html);
|
||||||
|
})
|
||||||
|
.listen(PORT, () => {
|
||||||
|
console.log(`http://localhost:${PORT}`);
|
||||||
|
});
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import polka from 'polka';
|
||||||
|
import { render } from 'svelte/server';
|
||||||
|
import App from './src/main.svelte';
|
||||||
|
|
||||||
|
const { head, body } = render(App);
|
||||||
|
|
||||||
|
const rendered = fs
|
||||||
|
.readFileSync(path.resolve('./dist/client/index.html'), 'utf-8')
|
||||||
|
.replace(`<!--ssr-body-->`, body)
|
||||||
|
.replace(`<!--ssr-head-->`, head);
|
||||||
|
|
||||||
|
const types = {
|
||||||
|
'.js': 'application/javascript',
|
||||||
|
'.css': 'text/css'
|
||||||
|
};
|
||||||
|
|
||||||
|
polka()
|
||||||
|
.use((req, res) => {
|
||||||
|
if (req.url === '/') {
|
||||||
|
res.writeHead(200, { 'content-type': 'text/html' });
|
||||||
|
res.end(rendered);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = path.resolve('./dist/client' + req.url);
|
||||||
|
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
const type = types[path.extname(req.url)] ?? 'application/octet-stream';
|
||||||
|
res.writeHead(200, { 'content-type': type });
|
||||||
|
fs.createReadStream(file).pipe(res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.writeHead(404);
|
||||||
|
res.end('not found');
|
||||||
|
})
|
||||||
|
.listen('3000');
|
||||||
|
|
||||||
|
console.log('listening on http://localhost:3000');
|
||||||
Loading…
Reference in new issue