mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 02:48:50 +00:00
a bit more, svelte doesnt fully import yet
This commit is contained in:
1
packages/bun-types/bun.d.ts
vendored
1
packages/bun-types/bun.d.ts
vendored
@@ -3873,7 +3873,6 @@ declare module "bun" {
|
||||
* The default loader for this file extension
|
||||
*/
|
||||
loader: Loader;
|
||||
|
||||
/**
|
||||
* Defer the execution of this callback until all other modules have been parsed.
|
||||
*
|
||||
|
||||
13
src/bake/bake.d.ts
vendored
13
src/bake/bake.d.ts
vendored
@@ -492,13 +492,23 @@ declare module "bun" {
|
||||
app?: Bake.Options | undefined;
|
||||
}
|
||||
|
||||
declare interface Plug {
|
||||
declare interface PluginBuilder {
|
||||
/**
|
||||
* Inject a module into the development server's runtime, to be loaded
|
||||
* before all other user code.
|
||||
*/
|
||||
addPreload(module: string, side: 'client' | 'server'): void;
|
||||
}
|
||||
|
||||
declare interface OnLoadArgs {
|
||||
/**
|
||||
* When using server-components, the same bundle has both client and server
|
||||
* files; A single plugin can operate on files from both module graphs.
|
||||
* Outside of server-components, this will be "client" when the target is
|
||||
* set to "browser" and "server" otherwise.
|
||||
*/
|
||||
side: 'server' | 'client';
|
||||
}
|
||||
}
|
||||
|
||||
/** Available in server-side files only. */
|
||||
@@ -557,6 +567,7 @@ declare module "bun:bake/server" {
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Available in client-side files. */
|
||||
|
||||
@@ -380,11 +380,14 @@ pub const Framework = struct {
|
||||
return global.throwInvalidArguments("Missing 'framework.serverComponents.serverRuntimeImportSource'", .{});
|
||||
},
|
||||
),
|
||||
.server_register_client_reference = refs.track(
|
||||
try sc.getOptional(global, "serverRegisterClientReferenceExport", ZigString.Slice) orelse {
|
||||
return global.throwInvalidArguments("Missing 'framework.serverComponents.serverRegisterClientReferenceExport'", .{});
|
||||
},
|
||||
),
|
||||
.server_register_client_reference = if (try sc.getOptional(
|
||||
global,
|
||||
"serverRegisterClientReferenceExport",
|
||||
ZigString.Slice,
|
||||
)) |slice|
|
||||
refs.track(slice)
|
||||
else
|
||||
"registerClientReference",
|
||||
};
|
||||
};
|
||||
const built_in_modules: bun.StringArrayHashMapUnmanaged(BuiltInModule) = built_in_modules: {
|
||||
@@ -456,9 +459,9 @@ pub const Framework = struct {
|
||||
break :exts &.{};
|
||||
}
|
||||
} else if (exts_js.isArray()) {
|
||||
var it_2 = array.arrayIterator(global);
|
||||
var it_2 = exts_js.arrayIterator(global);
|
||||
var i_2: usize = 0;
|
||||
const extensions = try arena.alloc([]const u8, len);
|
||||
const extensions = try arena.alloc([]const u8, array.getLength(global));
|
||||
while (it_2.next()) |array_item| : (i_2 += 1) {
|
||||
const slice = refs.track(try array_item.toSlice2(global, arena));
|
||||
if (bun.strings.eqlComptime(slice, "*"))
|
||||
|
||||
@@ -39,6 +39,7 @@ export class HotModule<E = any> {
|
||||
_cached_failure: any = undefined;
|
||||
// modules that import THIS module
|
||||
_deps: Map<HotModule, DepEntry | undefined> = new Map();
|
||||
_onDispose: HotDisposeFunction[] | undefined = undefined;
|
||||
|
||||
constructor(id: Id) {
|
||||
this.id = id;
|
||||
@@ -55,13 +56,14 @@ export class HotModule<E = any> {
|
||||
mod._deps.set(this, onReload ? { _callback: onReload, _expectedImports: expectedImports } : undefined);
|
||||
const { exports, __esModule } = mod;
|
||||
const object = __esModule ? exports : (mod._ext_exports ??= { ...exports, default: exports });
|
||||
if (expectedImports) {
|
||||
for (const key of expectedImports) {
|
||||
if (!(key in object)) {
|
||||
throw new SyntaxError(`The requested module '${id}' does not provide an export named '${key}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: restore this validation. not correct due to import cycles which are allowed usually
|
||||
// if (expectedImports) {
|
||||
// for (const key of expectedImports) {
|
||||
// if (!(key in object)) {
|
||||
// throw new SyntaxError(`The requested module '${id}' does not provide an export named '${key}'`);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -93,14 +95,73 @@ function initImportMeta(m: HotModule): ImportMeta {
|
||||
url: `bun://${m.id}`,
|
||||
main: false,
|
||||
// @ts-ignore
|
||||
hot: {
|
||||
accept() {
|
||||
throw new Error("Not implemented");
|
||||
},
|
||||
}
|
||||
get hot() {
|
||||
const hot = new Hot(m);
|
||||
Object.defineProperty(this, "hot", { value: hot });
|
||||
return hot;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
type HotAcceptFunction = (esmExports: any | void) => void;
|
||||
type HotArrayAcceptFunction = (esmExports: (any | void)[]) => void;
|
||||
type HotDisposeFunction = (data: any) => void;
|
||||
type HotEventHandler = (data: any) => void;
|
||||
|
||||
class Hot {
|
||||
private _module: HotModule;
|
||||
|
||||
constructor(module: HotModule) {
|
||||
this._module = module;
|
||||
}
|
||||
|
||||
accept(
|
||||
arg1: string | readonly string[] | HotAcceptFunction,
|
||||
arg2: HotAcceptFunction | HotArrayAcceptFunction | undefined,
|
||||
) {
|
||||
console.warn("TODO: implement ImportMetaHot.accept (called from " + JSON.stringify(this._module.id) + ")");
|
||||
}
|
||||
|
||||
dispose(cb: HotDisposeFunction) {
|
||||
(this._module._onDispose ??= []).push(cb);
|
||||
}
|
||||
|
||||
prune(cb: HotDisposeFunction) {
|
||||
throw new Error("TODO: implement ImportMetaHot.prune");
|
||||
}
|
||||
|
||||
invalidate() {
|
||||
throw new Error("TODO: implement ImportMetaHot.invalidate");
|
||||
}
|
||||
|
||||
on(event: string, cb: HotEventHandler) {
|
||||
if (isUnsupportedViteEventName(event)) {
|
||||
throw new Error(`Unsupported event name: ${event}`);
|
||||
}
|
||||
|
||||
throw new Error("TODO: implement ImportMetaHot.on");
|
||||
}
|
||||
|
||||
off(event: string, cb: HotEventHandler) {
|
||||
throw new Error("TODO: implement ImportMetaHot.off");
|
||||
}
|
||||
|
||||
send(event: string, cb: HotEventHandler) {
|
||||
throw new Error("TODO: implement ImportMetaHot.send");
|
||||
}
|
||||
}
|
||||
|
||||
function isUnsupportedViteEventName(str: string) {
|
||||
return str === 'vite:beforeUpdate'
|
||||
|| str === 'vite:afterUpdate'
|
||||
|| str === 'vite:beforeFullReload'
|
||||
|| str === 'vite:beforePrune'
|
||||
|| str === 'vite:invalidate'
|
||||
|| str === 'vite:error'
|
||||
|| str === 'vite:ws:disconnect'
|
||||
|| str === 'vite:ws:connect';
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a module by ID. Use `type` to specify if the module is supposed to be
|
||||
* present, or is something a user is able to dynamically specify.
|
||||
|
||||
@@ -771,6 +771,7 @@ pub const JSBundler = struct {
|
||||
load.namespace,
|
||||
load,
|
||||
load.default_loader,
|
||||
load.bakeGraph() != .client,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -881,6 +882,7 @@ pub const JSBundler = struct {
|
||||
path: *const String,
|
||||
context: *anyopaque,
|
||||
u8,
|
||||
bool,
|
||||
) void;
|
||||
|
||||
extern fn JSBundlerPlugin__matchOnResolve(
|
||||
@@ -921,6 +923,7 @@ pub const JSBundler = struct {
|
||||
namespace: []const u8,
|
||||
context: *anyopaque,
|
||||
default_loader: options.Loader,
|
||||
is_server_side: bool,
|
||||
) void {
|
||||
JSC.markBinding(@src());
|
||||
const tracer = bun.tracy.traceNamed(@src(), "JSBundler.matchOnLoad");
|
||||
@@ -933,7 +936,7 @@ pub const JSBundler = struct {
|
||||
const path_string = bun.String.createUTF8(path);
|
||||
defer namespace_string.deref();
|
||||
defer path_string.deref();
|
||||
JSBundlerPlugin__matchOnLoad(this, &namespace_string, &path_string, context, @intFromEnum(default_loader));
|
||||
JSBundlerPlugin__matchOnLoad(this, &namespace_string, &path_string, context, @intFromEnum(default_loader), is_server_side);
|
||||
}
|
||||
|
||||
pub fn matchOnResolve(
|
||||
|
||||
@@ -325,7 +325,7 @@ extern "C" bool JSBundlerPlugin__anyMatches(Bun::JSBundlerPlugin* pluginObject,
|
||||
return pluginObject->plugin.anyMatchesCrossThread(pluginObject->vm(), namespaceString, path, isOnLoad);
|
||||
}
|
||||
|
||||
extern "C" void JSBundlerPlugin__matchOnLoad(Bun::JSBundlerPlugin* plugin, const BunString* namespaceString, const BunString* path, void* context, uint8_t defaultLoaderId)
|
||||
extern "C" void JSBundlerPlugin__matchOnLoad(Bun::JSBundlerPlugin* plugin, const BunString* namespaceString, const BunString* path, void* context, uint8_t defaultLoaderId, bool isServerSide)
|
||||
{
|
||||
JSC::JSGlobalObject *globalObject = plugin->globalObject();
|
||||
WTF::String namespaceStringStr = namespaceString ? namespaceString->toWTFString(BunString::ZeroCopy) : WTF::String();
|
||||
@@ -346,6 +346,7 @@ extern "C" void JSBundlerPlugin__matchOnLoad(Bun::JSBundlerPlugin* plugin, const
|
||||
arguments.append(JSC::jsString(plugin->vm(), pathStr));
|
||||
arguments.append(JSC::jsString(plugin->vm(), namespaceStringStr));
|
||||
arguments.append(JSC::jsNumber(defaultLoaderId));
|
||||
arguments.append(JSC::jsBoolean(isServerSide));
|
||||
|
||||
call(globalObject, function, callData, plugin, arguments);
|
||||
|
||||
|
||||
@@ -2412,7 +2412,8 @@ pub const ModuleLoader = struct {
|
||||
else
|
||||
specifier[@min(namespace.len + 1, specifier.len)..];
|
||||
|
||||
return globalObject.runOnLoadPlugins(bun.String.init(namespace), bun.String.init(after_namespace), .bun) orelse return JSValue.zero;
|
||||
return globalObject.runOnLoadPlugins(bun.String.init(namespace), bun.String.init(after_namespace), .bun) orelse
|
||||
return JSValue.zero;
|
||||
}
|
||||
|
||||
pub fn fetchBuiltinModule(jsc_vm: *VirtualMachine, specifier: bun.String) !?ResolvedSource {
|
||||
|
||||
@@ -22,7 +22,7 @@ interface BundlerPlugin {
|
||||
/** Binding to `JSBundlerPlugin__addError` */
|
||||
addError(internalID: number, error: any, which: number): void;
|
||||
addFilter(filter, namespace, number): void;
|
||||
generateDeferPromise(): Promise<void>;
|
||||
generateDeferPromise(id: number): Promise<void>;
|
||||
promises: Array<Promise<any>> | undefined;
|
||||
}
|
||||
|
||||
@@ -335,12 +335,12 @@ export function runOnResolvePlugins(this: BundlerPlugin, specifier, inputNamespa
|
||||
}
|
||||
}
|
||||
|
||||
export function runOnLoadPlugins(this: BundlerPlugin, internalID, path, namespace, defaultLoaderId) {
|
||||
export function runOnLoadPlugins(this: BundlerPlugin, internalID, path, namespace, defaultLoaderId, isServerSide: boolean) {
|
||||
const LOADERS_MAP = $LoaderLabelToId;
|
||||
const loaderName = $LoaderIdToLabel[defaultLoaderId];
|
||||
|
||||
const generateDefer = () => this.generateDeferPromise(internalID);
|
||||
var promiseResult = (async (internalID, path, namespace, defaultLoader, generateDefer) => {
|
||||
var promiseResult = (async (internalID, path, namespace, isServerSide, defaultLoader, generateDefer) => {
|
||||
var results = this.onLoad.$get(namespace);
|
||||
if (!results) {
|
||||
this.onLoadAsync(internalID, null, null);
|
||||
@@ -356,6 +356,7 @@ export function runOnLoadPlugins(this: BundlerPlugin, internalID, path, namespac
|
||||
// pluginData
|
||||
loader: defaultLoader,
|
||||
defer: generateDefer,
|
||||
side: isServerSide ? "server" : "client",
|
||||
});
|
||||
|
||||
while (
|
||||
@@ -407,7 +408,7 @@ export function runOnLoadPlugins(this: BundlerPlugin, internalID, path, namespac
|
||||
|
||||
this.onLoadAsync(internalID, null, null);
|
||||
return null;
|
||||
})(internalID, path, namespace, loaderName, generateDefer);
|
||||
})(internalID, path, namespace, isServerSide, loaderName, generateDefer);
|
||||
|
||||
while (
|
||||
promiseResult &&
|
||||
|
||||
@@ -8986,64 +8986,62 @@ fn NewParser_(
|
||||
try p.is_import_item.ensureUnusedCapacity(p.allocator, count_excluding_namespace);
|
||||
var remap_count: u32 = 0;
|
||||
// Link the default item to the namespace
|
||||
if (stmt.default_name) |*name_loc| {
|
||||
outer: {
|
||||
const name = p.loadNameFromRef(name_loc.ref.?);
|
||||
const ref = try p.declareSymbol(.import, name_loc.loc, name);
|
||||
name_loc.ref = ref;
|
||||
try p.is_import_item.put(p.allocator, ref, {});
|
||||
if (stmt.default_name) |*name_loc| outer: {
|
||||
const name = p.loadNameFromRef(name_loc.ref.?);
|
||||
const ref = try p.declareSymbol(.import, name_loc.loc, name);
|
||||
name_loc.ref = ref;
|
||||
try p.is_import_item.put(p.allocator, ref, {});
|
||||
|
||||
// ensure every e_import_identifier holds the namespace
|
||||
if (p.options.features.hot_module_reloading) {
|
||||
const symbol = &p.symbols.items[ref.inner_index];
|
||||
if (symbol.namespace_alias == null) {
|
||||
symbol.namespace_alias = .{
|
||||
.namespace_ref = stmt.namespace_ref,
|
||||
.alias = "default",
|
||||
.import_record_index = stmt.import_record_index,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (macro_remap) |*remap| {
|
||||
if (remap.get("default")) |remapped_path| {
|
||||
const new_import_id = p.addImportRecord(.stmt, path.loc, remapped_path);
|
||||
try p.macro.refs.put(ref, new_import_id);
|
||||
|
||||
p.import_records.items[new_import_id].path.namespace = js_ast.Macro.namespace;
|
||||
p.import_records.items[new_import_id].is_unused = true;
|
||||
if (comptime only_scan_imports_and_do_not_visit) {
|
||||
p.import_records.items[new_import_id].is_internal = true;
|
||||
p.import_records.items[new_import_id].path.is_disabled = true;
|
||||
}
|
||||
stmt.default_name = null;
|
||||
remap_count += 1;
|
||||
break :outer;
|
||||
}
|
||||
}
|
||||
|
||||
if (comptime track_symbol_usage_during_parse_pass) {
|
||||
p.parse_pass_symbol_uses.put(name, .{
|
||||
.ref = ref,
|
||||
// ensure every e_import_identifier holds the namespace
|
||||
if (p.options.features.hot_module_reloading) {
|
||||
const symbol = &p.symbols.items[ref.inner_index];
|
||||
if (symbol.namespace_alias == null) {
|
||||
symbol.namespace_alias = .{
|
||||
.namespace_ref = stmt.namespace_ref,
|
||||
.alias = "default",
|
||||
.import_record_index = stmt.import_record_index,
|
||||
}) catch unreachable;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (is_macro) {
|
||||
try p.macro.refs.put(ref, stmt.import_record_index);
|
||||
if (macro_remap) |*remap| {
|
||||
if (remap.get("default")) |remapped_path| {
|
||||
const new_import_id = p.addImportRecord(.stmt, path.loc, remapped_path);
|
||||
try p.macro.refs.put(ref, new_import_id);
|
||||
|
||||
p.import_records.items[new_import_id].path.namespace = js_ast.Macro.namespace;
|
||||
p.import_records.items[new_import_id].is_unused = true;
|
||||
if (comptime only_scan_imports_and_do_not_visit) {
|
||||
p.import_records.items[new_import_id].is_internal = true;
|
||||
p.import_records.items[new_import_id].path.is_disabled = true;
|
||||
}
|
||||
stmt.default_name = null;
|
||||
remap_count += 1;
|
||||
break :outer;
|
||||
}
|
||||
|
||||
if (comptime ParsePassSymbolUsageType != void) {
|
||||
p.parse_pass_symbol_uses.put(name, .{
|
||||
.ref = ref,
|
||||
.import_record_index = stmt.import_record_index,
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
item_refs.putAssumeCapacity(name, name_loc.*);
|
||||
}
|
||||
|
||||
if (comptime track_symbol_usage_during_parse_pass) {
|
||||
p.parse_pass_symbol_uses.put(name, .{
|
||||
.ref = ref,
|
||||
.import_record_index = stmt.import_record_index,
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
if (is_macro) {
|
||||
try p.macro.refs.put(ref, stmt.import_record_index);
|
||||
stmt.default_name = null;
|
||||
break :outer;
|
||||
}
|
||||
|
||||
if (comptime ParsePassSymbolUsageType != void) {
|
||||
p.parse_pass_symbol_uses.put(name, .{
|
||||
.ref = ref,
|
||||
.import_record_index = stmt.import_record_index,
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
item_refs.putAssumeCapacity(name, name_loc.*);
|
||||
}
|
||||
var end: usize = 0;
|
||||
|
||||
@@ -12469,7 +12467,6 @@ fn NewParser_(
|
||||
|
||||
fn declareSymbolMaybeGenerated(p: *P, kind: Symbol.Kind, loc: logger.Loc, name: string, comptime is_generated: bool) !Ref {
|
||||
// p.checkForNonBMPCodePoint(loc, name)
|
||||
|
||||
if (comptime !is_generated) {
|
||||
// Forbid declaring a symbol with a reserved word in strict mode
|
||||
if (p.isStrictMode() and name.ptr != arguments_str.ptr and js_lexer.StrictModeReservedWords.has(name)) {
|
||||
@@ -19046,16 +19043,6 @@ fn NewParser_(
|
||||
}
|
||||
},
|
||||
.s_export_from => |data| {
|
||||
// When HMR is enabled, we need to transform this into
|
||||
// import {foo} from "./foo";
|
||||
// export {foo};
|
||||
|
||||
// From:
|
||||
// export {foo as default} from './foo';
|
||||
// To:
|
||||
// import {default as foo} from './foo';
|
||||
// export {foo};
|
||||
|
||||
// "export {foo} from 'path'"
|
||||
const name = p.loadNameFromRef(data.namespace_ref);
|
||||
|
||||
@@ -19079,7 +19066,7 @@ fn NewParser_(
|
||||
|
||||
const _name = p.loadNameFromRef(old_ref);
|
||||
|
||||
const ref = try p.newSymbol(.other, _name);
|
||||
const ref = try p.newSymbol(.import, _name);
|
||||
try p.current_scope.generated.push(p.allocator, ref);
|
||||
try p.recordDeclaredSymbol(ref);
|
||||
data.items[j] = item;
|
||||
@@ -19093,11 +19080,10 @@ fn NewParser_(
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
// This is a re-export and the symbols created here are used to reference
|
||||
for (data.items) |*item| {
|
||||
const _name = p.loadNameFromRef(item.name.ref.?);
|
||||
const ref = try p.newSymbol(.other, _name);
|
||||
const ref = try p.newSymbol(.import, _name);
|
||||
try p.current_scope.generated.push(p.allocator, ref);
|
||||
try p.recordDeclaredSymbol(ref);
|
||||
item.name.ref = ref;
|
||||
@@ -23961,19 +23947,37 @@ pub const ConvertESMExportsForHmr = struct {
|
||||
},
|
||||
.s_export_clause => |st| {
|
||||
for (st.items) |item| {
|
||||
try ctx.export_props.append(p.allocator, .{
|
||||
.key = Expr.init(E.String, .{
|
||||
.data = item.alias,
|
||||
}, stmt.loc),
|
||||
.value = Expr.initIdentifier(item.name.ref.?, item.name.loc),
|
||||
});
|
||||
const ref = item.name.ref.?;
|
||||
try ctx.visitRefForBakeModuleExports(p, ref, item.name.loc, false);
|
||||
}
|
||||
|
||||
return; // do not emit a statement here
|
||||
},
|
||||
|
||||
.s_export_from => {
|
||||
bun.todoPanic(@src(), "hot-module-reloading instrumentation for 'export {{ ... }} from'", .{});
|
||||
.s_export_from => |st| stmt: {
|
||||
for (st.items) |item| {
|
||||
const ref = item.name.ref.?;
|
||||
const symbol = &p.symbols.items[ref.innerIndex()];
|
||||
if (symbol.namespace_alias == null) {
|
||||
symbol.namespace_alias = .{
|
||||
.namespace_ref = st.namespace_ref,
|
||||
.alias = item.original_name,
|
||||
.import_record_index = st.import_record_index,
|
||||
};
|
||||
}
|
||||
try ctx.visitRefForBakeModuleExports(p, ref, item.name.loc, true);
|
||||
}
|
||||
|
||||
const gop = try ctx.imports_seen.getOrPut(p.allocator, st.import_record_index);
|
||||
if (gop.found_existing) return;
|
||||
break :stmt Stmt.alloc(S.Import, .{
|
||||
.import_record_index = st.import_record_index,
|
||||
.is_single_line = true,
|
||||
.default_name = null,
|
||||
.items = st.items,
|
||||
.namespace_ref = st.namespace_ref,
|
||||
.star_name_loc = null,
|
||||
}, stmt.loc);
|
||||
},
|
||||
.s_export_star => {
|
||||
bun.todoPanic(@src(), "hot-module-reloading instrumentation for 'export * from'", .{});
|
||||
@@ -24001,7 +24005,7 @@ pub const ConvertESMExportsForHmr = struct {
|
||||
switch (binding.data) {
|
||||
.b_missing => {},
|
||||
.b_identifier => |id| {
|
||||
try ctx.visitRefForKitModuleExports(p, id.ref, binding.loc, is_live_binding);
|
||||
try ctx.visitRefForBakeModuleExports(p, id.ref, binding.loc, is_live_binding);
|
||||
},
|
||||
.b_array => |array| {
|
||||
for (array.items) |item| {
|
||||
@@ -24016,16 +24020,24 @@ pub const ConvertESMExportsForHmr = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn visitRefForKitModuleExports(
|
||||
fn visitRefForBakeModuleExports(
|
||||
ctx: *ConvertESMExportsForHmr,
|
||||
p: anytype,
|
||||
ref: Ref,
|
||||
loc: logger.Loc,
|
||||
is_live_binding: bool,
|
||||
is_live_binding_source: bool,
|
||||
) !void {
|
||||
const symbol = p.symbols.items[ref.inner_index];
|
||||
const id = Expr.initIdentifier(ref, loc);
|
||||
if (is_live_binding) {
|
||||
std.debug.print("yolo {s}, {s}\n", .{ symbol.original_name, @tagName(symbol.kind) });
|
||||
const id = if (symbol.kind == .import)
|
||||
Expr.init(E.ImportIdentifier, .{ .ref = ref }, loc)
|
||||
else
|
||||
Expr.initIdentifier(ref, loc);
|
||||
if (is_live_binding_source or symbol.kind == .import) {
|
||||
// TODO: instead of requiring getters for live-bindings,
|
||||
// a callback propagation system should be considered.
|
||||
// mostly because here, these might not even be live
|
||||
// bindings, and re-exports are so, so common.
|
||||
const key = Expr.init(E.String, .{
|
||||
.data = symbol.original_name,
|
||||
}, loc);
|
||||
@@ -24052,24 +24064,7 @@ pub const ConvertESMExportsForHmr = struct {
|
||||
},
|
||||
} }, loc),
|
||||
});
|
||||
// 'set abc(abc2) { abc = abc2 }'
|
||||
try ctx.export_props.append(p.allocator, .{
|
||||
.kind = .set,
|
||||
.key = key,
|
||||
.value = Expr.init(E.Function, .{ .func = .{
|
||||
.args = try p.allocator.dupe(G.Arg, &.{.{
|
||||
.binding = Binding.alloc(p.allocator, B.Identifier{ .ref = arg1 }, loc),
|
||||
}}),
|
||||
.body = .{
|
||||
.stmts = try p.allocator.dupe(Stmt, &.{
|
||||
Stmt.alloc(S.SExpr, .{
|
||||
.value = Expr.assign(id, Expr.initIdentifier(arg1, loc)),
|
||||
}, loc),
|
||||
}),
|
||||
.loc = loc,
|
||||
},
|
||||
} }, loc),
|
||||
});
|
||||
// no setter is added since live bindings are read-only
|
||||
} else {
|
||||
// 'abc,'
|
||||
try ctx.export_props.append(p.allocator, .{
|
||||
|
||||
@@ -293,7 +293,7 @@ class OutputLineStream extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
export function devTest(description: string, options: DevServerTest) {
|
||||
export function devTest<T extends DevServerTest>(description: string, options: T): T {
|
||||
// Capture the caller name as part of the test tempdir
|
||||
const callerLocation = snapshotCallerLocation();
|
||||
const caller = stackTraceFileName(callerLocation);
|
||||
@@ -305,7 +305,7 @@ export function devTest(description: string, options: DevServerTest) {
|
||||
// TODO: Tests are too flaky on Windows. Cannot reproduce locally.
|
||||
if (isWindows) {
|
||||
jest.test.todo(`DevServer > ${basename}.${count}: ${description}`);
|
||||
return;
|
||||
return options;
|
||||
}
|
||||
|
||||
jest.test(`DevServer > ${basename}.${count}: ${description}`, async () => {
|
||||
@@ -377,4 +377,5 @@ export function devTest(description: string, options: DevServerTest) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ devTest("onLoad", {
|
||||
setup(build) {
|
||||
let a = 0;
|
||||
build.onLoad({ filter: /trigger/ }, (args) => {
|
||||
a += 1;
|
||||
return { contents: 'export const value = ' + a + ';', loader: 'ts' };
|
||||
return { contents: 'export const value = 1;', loader: 'ts' };
|
||||
});
|
||||
},
|
||||
}
|
||||
@@ -65,8 +64,43 @@ devTest("onLoad", {
|
||||
async test(dev) {
|
||||
await dev.fetch("/").expect('value: 1');
|
||||
await dev.fetch("/").expect('value: 1');
|
||||
await dev.write("trigger.ts", "throw new Error('should not be loaded 2');");
|
||||
await dev.fetch("/").expect('value: 2');
|
||||
await dev.fetch("/").expect('value: 2');
|
||||
await dev.fetch("/").expect('value: 1');
|
||||
},
|
||||
});
|
||||
// devTest("onLoad with watchFile", {
|
||||
// framework: minimalFramework,
|
||||
// pluginFile: `
|
||||
// import * as path from 'path';
|
||||
// export default [
|
||||
// {
|
||||
// name: 'a',
|
||||
// setup(build) {
|
||||
// let a = 0;
|
||||
// build.onLoad({ filter: /trigger/ }, (args) => {
|
||||
// a += 1;
|
||||
// return { contents: 'export const value = ' + a + ';', loader: 'ts' };
|
||||
// });
|
||||
// },
|
||||
// }
|
||||
// ];
|
||||
// `,
|
||||
// files: {
|
||||
// "trigger.ts": `
|
||||
// throw new Error('should not be loaded');
|
||||
// `,
|
||||
// "routes/index.ts": `
|
||||
// import { value } from '../trigger.ts';
|
||||
|
||||
// export default function (req, meta) {
|
||||
// return new Response('value: ' + value);
|
||||
// }
|
||||
// `,
|
||||
// },
|
||||
// async test(dev) {
|
||||
// await dev.fetch("/").expect('value: 1');
|
||||
// await dev.fetch("/").expect('value: 1');
|
||||
// await dev.write("trigger.ts", "throw new Error('should not be loaded 2');");
|
||||
// await dev.fetch("/").expect('value: 2');
|
||||
// await dev.fetch("/").expect('value: 2');
|
||||
// },
|
||||
// });
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Bundle tests are tests concerning bundling bugs that only occur in DevServer.
|
||||
import { devTest, minimalFramework, Step } from "../dev-server-harness";
|
||||
|
||||
devTest("live bindings with `var`", {
|
||||
const liveBindingTest = devTest("live bindings with `var`", {
|
||||
framework: minimalFramework,
|
||||
files: {
|
||||
"state.ts": `
|
||||
@@ -41,3 +41,73 @@ devTest("live bindings with `var`", {
|
||||
await dev.fetch("/").expect("Value: -2");
|
||||
},
|
||||
});
|
||||
devTest("live bindings through export clause", {
|
||||
framework: minimalFramework,
|
||||
files: {
|
||||
"state.ts": `
|
||||
export var value = 0;
|
||||
export function increment() {
|
||||
value++;
|
||||
}
|
||||
`,
|
||||
"proxy.ts": `
|
||||
import { value } from './state';
|
||||
export { value as live };
|
||||
`,
|
||||
"routes/index.ts": `
|
||||
import { increment } from '../state';
|
||||
import { live } from '../proxy';
|
||||
export default function(req, meta) {
|
||||
increment();
|
||||
return new Response('State: ' + live);
|
||||
}
|
||||
`,
|
||||
},
|
||||
test: liveBindingTest.test,
|
||||
});
|
||||
devTest("live bindings through export from", {
|
||||
framework: minimalFramework,
|
||||
files: {
|
||||
"state.ts": `
|
||||
export var value = 0;
|
||||
export function increment() {
|
||||
value++;
|
||||
}
|
||||
`,
|
||||
"proxy.ts": `
|
||||
export { value as live } from './state';
|
||||
`,
|
||||
"routes/index.ts": `
|
||||
import { increment } from '../state';
|
||||
import { live } from '../proxy';
|
||||
export default function(req, meta) {
|
||||
increment();
|
||||
return new Response('State: ' + live);
|
||||
}
|
||||
`,
|
||||
},
|
||||
test: liveBindingTest.test,
|
||||
});
|
||||
devTest("live bindings through export star", {
|
||||
framework: minimalFramework,
|
||||
files: {
|
||||
"state.ts": `
|
||||
export var value = 0;
|
||||
export function increment() {
|
||||
value++;
|
||||
}
|
||||
`,
|
||||
"proxy.ts": `
|
||||
export * from './state';
|
||||
`,
|
||||
"routes/index.ts": `
|
||||
import { increment } from '../state';
|
||||
import { live } from '../proxy';
|
||||
export default function(req, meta) {
|
||||
increment();
|
||||
return new Response('State: ' + live);
|
||||
}
|
||||
`,
|
||||
},
|
||||
test: liveBindingTest.test,
|
||||
});
|
||||
Reference in New Issue
Block a user