UNPKG

rolldown

Version:

Fast JavaScript/TypeScript bundler in Rust with Rollup-compatible API.

117 lines (105 loc) 3.18 kB
// @ts-check /** @import { DevRuntime } from './runtime-extra-dev-common.js' */ /** @type {typeof DevRuntime} */ // @ts-expect-error -- there's no way to declare a variable by JSDoc var BaseDevRuntime = DevRuntime; class ModuleHotContext { /** * @type {{ deps: [string], fn: (moduleExports: Record<string, any>[]) => void }[]} */ acceptCallbacks = []; /** * @param {string} moduleId * @param {InstanceType<BaseDevRuntime>} devRuntime */ constructor(moduleId, devRuntime) { this.moduleId = moduleId; this.devRuntime = devRuntime; } /** * @overload * @param {(mod: Record<string, any>) => void} cb * @returns {void} */ /** * @param {...any} args * @returns {void} */ accept(...args) { if (args.length === 1) { const [cb] = /** @type {[(mod: Record<string, any>) => void]} */ (args); const acceptingPath = this.moduleId; this.acceptCallbacks.push({ deps: [acceptingPath], fn: cb, }); } else if (args.length === 0) {} else { throw new Error('Invalid arguments for `import.meta.hot.accept`'); } } invalidate() { socket.send(JSON.stringify({ type: 'hmr:invalidate', moduleId: this.moduleId, })); } } class DefaultDevRuntime extends BaseDevRuntime { /** * @type {Map<string, ModuleHotContext>} */ moduleHotContexts = new Map(); /** * @override * @param {string} moduleId */ createModuleHotContext(moduleId) { const hotContext = new ModuleHotContext(moduleId, this); this.moduleHotContexts.set(moduleId, hotContext); return hotContext; } } /** @param {string} url */ function loadScript(url) { var script = document.createElement('script'); script.src = url; script.type = 'module'; script.onerror = function() { console.error('Failed to load script: ' + url); }; document.body.appendChild(script); } console.debug('HMR runtime loaded', '$ADDR'); // Generate client ID immediately at runtime initialization // This ensures the client ID is available before any lazy imports const clientId = crypto.randomUUID(); const addr = new URL('ws://$ADDR'); addr.searchParams.set('clientId', clientId); const socket = new WebSocket(addr); (/** @type {any} */ (globalThis)).__rolldown_runtime__ ??= new DefaultDevRuntime(clientId); /** @param {MessageEvent} event */ socket.onmessage = function(event) { const data = JSON.parse(event.data); console.debug('Received message:', data); if (data.type === 'connected') { // Server acknowledged the connection console.debug('[hmr]: Connection established with server'); } else if (data.type === 'hmr:update') { if (typeof process === 'object') { import(data.path); console.debug(`[hmr]: Importing HMR patch: ${data.path}`); } else { console.debug(`[hmr]: Loading HMR patch: ${data.path}`); loadScript(data.url); } } else if (data.type === 'hmr:reload') { console.log('[hmr]: Full reload required, reloading page'); if (typeof location !== 'undefined') { location.reload(); } else { console.log('[hmr]: location is undefined, cannot reload page'); } } };