aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-26 12:23:09 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-26 12:23:09 -0700
commite4b054060e77a00bbcb067d17bda421294a2dc9b (patch)
tree03e935eafd2aa7e7d80389a6cf41c059cce85341
parent651069762786066c300b4a873bc131c1ce3edc3a (diff)
downloadbun-e4b054060e77a00bbcb067d17bda421294a2dc9b.tar.gz
bun-e4b054060e77a00bbcb067d17bda421294a2dc9b.tar.zst
bun-e4b054060e77a00bbcb067d17bda421294a2dc9b.zip
namespace/enum? is that it?
Former-commit-id: 1e0eb4012a5b40f32d8e6f40fa3edd9f27d0a8ec
-rw-r--r--src/js_ast.zig6
-rw-r--r--src/js_parser/js_parser.zig147
-rw-r--r--src/js_printer.zig6
3 files changed, 101 insertions, 58 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 95260c96f..7c92a9f74 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -83,6 +83,8 @@ pub const Flags = struct {
has_rest_arg: bool = false,
has_if_scope: bool = false,
+ is_forward_declaration: bool = false,
+
// This is true if the function is a method
is_unique_formal_parameters: bool = false,
@@ -355,7 +357,9 @@ pub const G = struct {
name: ?LocRef,
open_parens_loc: logger.Loc,
args: []Arg = &([_]Arg{}),
- body: ?FnBody = null,
+ // This was originally nullable, but doing so I believe caused a miscompilation
+ // Specifically, the body was always null.
+ body: FnBody = FnBody{ .loc = logger.Loc.Empty, .stmts = &([_]StmtNodeIndex{}) },
arguments_ref: ?Ref = null,
flags: Flags.Function = Flags.Function.None,
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index d27d0dbce..456130d8a 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -2796,7 +2796,7 @@ pub const P = struct {
});
// Don't output anything if it's just a forward declaration of a function
- if (opts.is_typescript_declare or func.body == null) {
+ if (opts.is_typescript_declare or func.flags.is_forward_declaration) {
p.popAndDiscardScope(scopeIndex);
// Balance the fake block scope introduced above
@@ -2865,6 +2865,7 @@ pub const P = struct {
var func = G.Fn{
.name = name,
+
.flags = Flags.Function{
.has_rest_arg = false,
.is_async = opts.allow_await == .allow_expr,
@@ -3020,6 +3021,7 @@ pub const P = struct {
// "function foo(): any;"
if (opts.allow_missing_body_for_type_script and p.lexer.token != .t_open_brace) {
try p.lexer.expectOrInsertSemicolon();
+ func.flags.is_forward_declaration = true;
return func;
}
var tempOpts = opts;
@@ -5076,11 +5078,11 @@ pub const P = struct {
const name_loc = p.lexer.loc();
const name_text = p.lexer.identifier;
try p.lexer.next();
- var name = LocRef{ .loc = name_loc, .ref = null };
+ var name = LocRef{ .loc = name_loc, .ref = null };
const scope_index = try p.pushScopeForParsePass(.entry, loc);
- const old_has_non_local_export_declare_inside_namespace = p.has_non_local_export_declare_inside_namespace;
+ const old_has_non_local_export_declare_inside_namespace = p.has_non_local_export_declare_inside_namespace;
p.has_non_local_export_declare_inside_namespace = false;
var stmts: List(Stmt) = List(Stmt).init(p.allocator);
@@ -5136,7 +5138,7 @@ pub const P = struct {
// "export declare" statements as non-empty even though "declare"
// statements are only type annotations. We cannot omit the namespace
// in that case. See https://github.com/evanw/esbuild/issues/1158.
- if (stmts.items.len == import_equal_count and !has_non_local_export_declare_inside_namespace or opts.is_typescript_declare) {
+ if ((stmts.items.len == import_equal_count and !has_non_local_export_declare_inside_namespace) or opts.is_typescript_declare) {
p.popAndDiscardScope(scope_index);
if (opts.is_module_scope) {
p.local_type_names.put(name_text, true) catch unreachable;
@@ -6976,7 +6978,7 @@ pub const P = struct {
});
// "class Foo { foo(): void; foo(): void {} }"
- if (func.body == null) {
+ if (func.flags.is_forward_declaration) {
// Skip this property entirely
p.popAndDiscardScope(scope_index);
return null;
@@ -9142,7 +9144,11 @@ pub const P = struct {
}
},
.s_expr => |st| {
- if (st.does_not_affect_tree_shaking) {} else if (!p.exprCanBeRemovedIfUnused(st.value)) {
+ if (st.does_not_affect_tree_shaking) {
+ // Expressions marked with this are automatically generated and have
+ // no side effects by construction.
+ break;
+ } else if (!p.exprCanBeRemovedIfUnused(st.value)) {
return false;
}
},
@@ -9227,7 +9233,8 @@ pub const P = struct {
return p.visitExprInOut(expr, ExprIn{});
}
- pub fn visitFunc(p: *P, func: *G.Fn, open_parens_loc: logger.Loc) void {
+ pub fn visitFunc(p: *P, _func: G.Fn, open_parens_loc: logger.Loc) G.Fn {
+ var func = _func;
const old_fn_or_arrow_data = p.fn_or_arrow_data_visit;
const old_fn_only_data = p.fn_only_data_visit;
p.fn_or_arrow_data_visit = FnOrArrowDataVisit{ .is_async = func.flags.is_async };
@@ -9243,28 +9250,30 @@ pub const P = struct {
}
}
+ const body = func.body;
+
p.pushScopeForVisitPass(.function_args, open_parens_loc) catch unreachable;
p.visitArgs(
func.args,
VisitArgsOpts{
.has_rest_arg = func.flags.has_rest_arg,
- .body = func.body.?.stmts,
+ .body = body.stmts,
.is_unique_formal_parameters = true,
},
);
- assert(func.body != null);
- p.pushScopeForVisitPass(.function_body, func.body.?.loc) catch unreachable;
- var stmts = List(Stmt).fromOwnedSlice(p.allocator, func.body.?.stmts);
- var temp_opts = PrependTempRefsOpts{ .kind = StmtsKind.fn_body, .fn_body_loc = func.body.?.loc };
+ p.pushScopeForVisitPass(.function_body, body.loc) catch unreachable;
+ var stmts = List(Stmt).fromOwnedSlice(p.allocator, body.stmts);
+ var temp_opts = PrependTempRefsOpts{ .kind = StmtsKind.fn_body, .fn_body_loc = body.loc };
p.visitStmtsAndPrependTempRefs(&stmts, &temp_opts) catch unreachable;
- func.body.?.stmts = stmts.toOwnedSlice();
+ func.body = G.FnBody{ .stmts = stmts.toOwnedSlice(), .loc = body.loc };
p.popScope();
p.popScope();
p.fn_or_arrow_data_visit = old_fn_or_arrow_data;
p.fn_only_data_visit = old_fn_only_data;
+ return func;
}
pub fn maybeKeepExprSymbolName(p: *P, expr: Expr, original_name: string, was_anonymous_named_expr: bool) Expr {
@@ -10266,7 +10275,7 @@ pub const P = struct {
p.fn_or_arrow_data_visit = old_fn_or_arrow_data;
},
.e_function => |e_| {
- p.visitFunc(&e_.func, expr.loc);
+ e_.func = p.visitFunc(e_.func, expr.loc);
if (e_.func.name) |name| {
return p.keepExprSymbolName(expr, p.symbols.items[name.ref.?.inner_index].original_name);
}
@@ -10796,7 +10805,7 @@ pub const P = struct {
name = "default";
}
- p.visitFunc(&func.func, func.func.open_parens_loc);
+ func.func = p.visitFunc(func.func, func.func.open_parens_loc);
stmts.append(stmt.*) catch unreachable;
// if (func.func.name != null and func.func.name.?.ref != null) {
@@ -11161,10 +11170,12 @@ pub const P = struct {
},
.s_function => |data| {
- p.visitFunc(&data.func, data.func.open_parens_loc);
+ data.func = p.visitFunc(data.func, data.func.open_parens_loc);
// Handle exporting this function from a namespace
if (data.func.flags.is_export and p.enclosing_namespace_arg_ref != null) {
+ data.func.flags.is_export = false;
+
const enclosing_namespace_arg_ref = p.enclosing_namespace_arg_ref orelse unreachable;
stmts.ensureUnusedCapacity(3) catch unreachable;
stmts.appendAssumeCapacity(stmt.*);
@@ -11320,6 +11331,7 @@ pub const P = struct {
data.arg,
value_stmts.toOwnedSlice(),
);
+ return;
},
.s_namespace => |data| {
p.recordDeclaredSymbol(data.name.ref.?) catch unreachable;
@@ -11342,15 +11354,13 @@ pub const P = struct {
var prepend_temp_refs = PrependTempRefsOpts{ .kind = StmtsKind.fn_body };
var prepend_list = List(Stmt).fromOwnedSlice(p.allocator, data.stmts);
- {
- const old_enclosing_namespace_arg_ref = p.enclosing_namespace_arg_ref;
- p.enclosing_namespace_arg_ref = data.arg;
- defer p.enclosing_namespace_arg_ref = old_enclosing_namespace_arg_ref;
- p.pushScopeForVisitPass(.entry, stmt.loc) catch unreachable;
- defer p.popScope();
- p.recordDeclaredSymbol(data.arg) catch unreachable;
- p.visitStmtsAndPrependTempRefs(&prepend_list, &prepend_temp_refs) catch unreachable;
- }
+ const old_enclosing_namespace_arg_ref = p.enclosing_namespace_arg_ref;
+ p.enclosing_namespace_arg_ref = data.arg;
+ p.pushScopeForVisitPass(.entry, stmt.loc) catch unreachable;
+ p.recordDeclaredSymbol(data.arg) catch unreachable;
+ p.visitStmtsAndPrependTempRefs(&prepend_list, &prepend_temp_refs) catch unreachable;
+ p.popScope();
+ p.enclosing_namespace_arg_ref = old_enclosing_namespace_arg_ref;
try p.generateClosureForTypeScriptNamespaceOrEnum(
stmts,
@@ -11359,7 +11369,7 @@ pub const P = struct {
data.name.loc,
data.name.ref.?,
data.arg,
- prepend_list.toOwnedSlice(),
+ prepend_list.items,
);
return;
},
@@ -11373,7 +11383,31 @@ pub const P = struct {
}
pub fn markExportedDeclsInsideNamespace(p: *P, ns_ref: Ref, decls: []G.Decl) void {
- notimpl();
+ for (decls) |decl| {
+ p.markExportedBindingInsideNamespace(ns_ref, decl.binding);
+ }
+ }
+
+ pub fn markExportedBindingInsideNamespace(p: *P, ref: Ref, binding: BindingNodeIndex) void {
+ switch (binding.data) {
+ .b_missing => {},
+ .b_identifier => |ident| {
+ p.is_exported_inside_namespace.put(ident.ref, ref) catch unreachable;
+ },
+ .b_array => |array| {
+ for (array.items) |item| {
+ p.markExportedBindingInsideNamespace(ref, item.binding);
+ }
+ },
+ .b_object => |obj| {
+ for (obj.properties) |item| {
+ p.markExportedBindingInsideNamespace(ref, item.value);
+ }
+ },
+ else => {
+ Global.panic("Unexpected binding type in namespace. This is a bug. {s}", .{binding});
+ },
+ }
}
pub fn generateClosureForTypeScriptNamespaceOrEnum(
@@ -11501,33 +11535,38 @@ pub const P = struct {
func_args[0] = .{ .binding = p.b(B.Identifier{ .ref = arg_ref }, name_loc) };
var args_list = p.allocator.alloc(ExprNodeIndex, 1) catch unreachable;
args_list[0] = arg_expr;
- stmts.append(
- p.s(
- S.SExpr{
- .value = p.e(
- E.Call{
- .target = p.e(
- E.Function{
- .func = G.Fn{
- .args = func_args,
- .name = null,
- .open_parens_loc = logger.Loc.Empty,
- .body = G.FnBody{
- .loc = stmt_loc,
- .stmts = stmts_inside_closure,
- },
- },
- },
- stmt_loc,
- ),
- .args = args_list,
- },
- stmt_loc,
- ),
- },
- stmt_loc,
- ),
- ) catch unreachable;
+ const func = G.Fn{
+ .args = func_args,
+ .name = null,
+ .open_parens_loc = stmt_loc,
+ .body = G.FnBody{
+ .loc = stmt_loc,
+ .stmts = try p.allocator.dupe(StmtNodeIndex, stmts_inside_closure),
+ },
+ };
+ const target = p.e(
+ E.Function{
+ .func = func,
+ },
+ stmt_loc,
+ );
+
+ const call = p.e(
+ E.Call{
+ .target = target,
+ .args = args_list,
+ },
+ stmt_loc,
+ );
+
+ const closure = p.s(
+ S.SExpr{
+ .value = call,
+ },
+ stmt_loc,
+ );
+
+ stmts.append(closure) catch unreachable;
}
pub fn lowerClass(p: *P, stmtorexpr: js_ast.StmtOrExpr, ref: Ref) []Stmt {
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 8170ff9ad..f1999f1e3 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -426,7 +426,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
pub fn printFunc(p: *Printer, func: G.Fn) void {
p.printFnArgs(func.args, func.flags.has_rest_arg, false);
p.printSpace();
- p.printBlock(func.body.?.loc, func.body.?.stmts);
+ p.printBlock(func.body.loc, func.body.stmts);
}
pub fn printClass(p: *Printer, class: G.Class) void {
if (class.extends) |extends| {
@@ -1648,9 +1648,9 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
}
- pub fn printDotThenSuffix(
+ pub inline fn printDotThenSuffix(
p: *Printer,
- ) callconv(.Inline) void {
+ ) void {
p.print(")");
}