Skip to content

Commit

Permalink
macro
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Sep 24, 2021
1 parent 29b9866 commit bdfb5a9
Show file tree
Hide file tree
Showing 3 changed files with 681 additions and 4 deletions.
106 changes: 106 additions & 0 deletions src/ast/ast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
globalThis.BunASTNode ??= class BunASTNode {
position = -1;
};

if (!globalThis.BunAST) {
globalThis.BunAST = {
EArray: class EArray extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EUnary: class EUnary extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EBinary: class EBinary extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EClass: class EClass extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ENew: class ENew extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EFunction: class EFunction extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ECall: class ECall extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EDot: class EDot extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EIndex: class EIndex extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EArrow: class EArrow extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EIdentifier: class EIdentifier extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EImportIdentifier: class EImportIdentifier extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EPrivateIdentifier: class EPrivateIdentifier extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EJsxElement: class EJsxElement extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EObject: class EObject extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ESpread: class ESpread extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ETemplatePart: class ETemplatePart extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ETemplate: class ETemplate extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ERegExp: class ERegExp extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EAwait: class EAwait extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EYield: class EYield extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EIf: class EIf extends BunASTNode {
no = Number.MAX_SAFE_INTEGER;
yes = Number.MAX_SAFE_INTEGER;
},
ERequire: class ERequire extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EImport: class EImport extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EBoolean: class EBoolean extends BunASTNode {
val = false;
},
ENumber: class ENumber extends BunASTNode {
val = 0;
},
EBigInt: class EBigInt extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EString: class EString extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EMissing: class EMissing extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EThis: class EThis extends BunASTNode {},
ESuper: class ESuper extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
ENull: class ENull extends BunASTNode {},
EUndefined: class EUndefined extends BunASTNode {},
ENewTarget: class ENewTarget extends BunASTNode {
#ptr = Number.MAX_SAFE_INTEGER;
},
EImportMeta: class EImportMeta extends BunASTNode {},
};
}
78 changes: 78 additions & 0 deletions src/bundler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ pub const Bundler = struct {
// must be pointer array because we can't we don't want the source to point to invalid memory if the array size is reallocated
virtual_modules: std.ArrayList(*ClientEntryPoint),

macro_context: ?*js_ast.Macro.MacroContext = null,

pub const isCacheEnabled = cache_files;

pub fn clone(this: *ThisBundler, allocator: *std.mem.Allocator, to: *ThisBundler) !void {
Expand Down Expand Up @@ -2412,6 +2414,13 @@ pub const Bundler = struct {
bundler.options.jsx.supports_fast_refresh;
opts.filepath_hash_for_hmr = file_hash orelse 0;
opts.warn_about_unbundled_modules = bundler.options.platform != .bun;

if (bundler.macro_context == null) {
bundler.macro_context = js_ast.Macro.MacroContext.init(bundler);
}

opts.macro_context = &bundler.macro_context.?;

const value = (bundler.resolver.caches.js.parse(
allocator,
opts,
Expand Down Expand Up @@ -3317,3 +3326,72 @@ pub const ResolveQueue = std.fifo.LinearFifo(
_resolver.Result,
std.fifo.LinearFifoBufferType.Dynamic,
);

// This is not very fast.
// The idea is: we want to generate a unique entry point per macro function export that registers the macro
// Registering the macro happens in VirtualMachine
// We "register" it which just marks the JSValue as protected.
// This is mostly a workaround for being unable to call ESM exported functions from C++.
// When that is resolved, we should remove this.
pub const MacroEntryPoint = struct {
code_buffer: [std.fs.MAX_PATH_BYTES * 2 + 500]u8 = undefined,
output_code_buffer: [std.fs.MAX_PATH_BYTES * 8 + 500]u8 = undefined,
source: logger.Source = undefined,

pub fn generateID(entry_path: string, function_name: string, buf: []u8, len: *u32) i32 {
var hasher = std.hash.Wyhash.init(0);
hasher.update(js_ast.Macro.namespaceWithColon);
hasher.update(entry_path);
hasher.update(function_name);
const truncated_u32 = @truncate(u32, hasher.final());

const specifier = std.fmt.bufPrint(buf, js_ast.Macro.namespaceWithColon ++ "//{x}.js", .{truncated_u32}) catch unreachable;
len.* = @truncate(u32, specifier.len);

return generateIDFromSpecifier(specifier);
}

pub fn generateIDFromSpecifier(specifier: string) i32 {
return @bitCast(i32, @truncate(u32, std.hash.Wyhash.hash(0, specifier)));
}

pub fn generate(
entry: *MacroEntryPoint,
bundler: *Bundler,
import_path: Fs.PathName,
function_name: string,
macro_id: i32,
macro_label_: string,
) !void {
const dir_to_use: string = import_path.dirWithTrailingSlash();
std.mem.copy(u8, entry.code_buffer[0..macro_label_.len], macro_label_);
const macro_label = entry.code_buffer[0..macro_label_.len];

const code = try std.fmt.bufPrint(
entry.code_buffer[macro_label.len..],
\\//Auto-generated file
\\import * as Macros from '{s}{s}';
\\
\\if (!('{s}' in Macros)) {{
\\ throw new Error("Macro '{s}' not found in '{s}{s}'");
\\}}
\\
\\Bun.registerMacro({d}, Macros['{s}']);
,
.{
dir_to_use,
import_path.filename,
function_name,
function_name,
dir_to_use,
import_path.filename,
macro_id,
function_name,
},
);

entry.source = logger.Source.initPathString(macro_label, code);
entry.source.path.text = macro_label;
entry.source.path.namespace = js_ast.Macro.namespace;
}
};
Loading

0 comments on commit bdfb5a9

Please sign in to comment.