From cd425afcbd7d3d51c85e8d68cdfd2bf29e7c1b1d Mon Sep 17 00:00:00 2001 From: chloe caruso Date: Thu, 12 Sep 2024 00:26:23 -0700 Subject: [PATCH] fix: do not emit direct eval --- CHANGELOG.md | 1 + src/core/Air.Dump.zig | 12 ++++++++++++ src/core/InternPool.zig | 11 ++++++++++- src/core/Report.zig | 18 +++++------------- src/core/Sema.zig | 2 +- src/core/Transform.zig | 1 + src/core/js/Link.zig | 13 ++++++++++++- src/core/js/NodeGen.zig | 17 ++++++++--------- test/behavior/direct_eval | 6 ++++++ 9 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 test/behavior/direct_eval diff --git a/CHANGELOG.md b/CHANGELOG.md index ec34334b327c2f3843912bf934f5d4044d596d34..e4d92933b3ffc2773110675cbe61c502e2359734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - fix: crash when analyzing an empty array without a result type - fix: binary operands with float and float would not resolve - fix: assertion false-positive when using an extern global more than once +- fix: do not emit direct eval ## 0.1.5 diff --git a/src/core/Air.Dump.zig b/src/core/Air.Dump.zig index 8652f6e6e95d2d39a336de33eba4a9aeb437240c..79eb0df165eace069097f479434403224e853b77 100644 --- a/src/core/Air.Dump.zig +++ b/src/core/Air.Dump.zig @@ -249,6 +249,18 @@ pub const State = struct { try w.writeAll(">"); try tty.setColor(w, .reset); }, + .opaque_value => |inner| { + try tty.setColor(w, .bright_black); + try w.writeAll("<"); + try tty.setColor(w, .blue); + try w.writeAll("opaque"); + try tty.setColor(w, .reset); + try tty.setColor(w, .bright_black); + try w.writeAll(", "); + try s.dumpValue(w, inner); + try w.writeAll(">"); + try tty.setColor(w, .reset); + }, .string => |data| { try w.writeAll("<"); try tty.setColor(w, .blue); diff --git a/src/core/InternPool.zig b/src/core/InternPool.zig index 2e6a50261cf6e54944cb88fb813ef776047c0855..679e01f3ad3122666d05b6eedda99389fd0b6f6c 100644 --- a/src/core/InternPool.zig +++ b/src/core/InternPool.zig @@ -127,6 +127,8 @@ pub const Tag = enum(u8) { array_value, /// An extern reference. For JS, this can be a property access external_value, + /// A value masked as "opaque" type + opaque_value, pub fn Data(comptime tag: Tag) type { return switch (tag) { @@ -135,6 +137,7 @@ pub const Tag = enum(u8) { .simple_type => SimpleType, .simple_value => SimpleValue, .int32 => i32, + .opaque_value => Value, else => ExtraIndex(tag.Payload()), }; @@ -147,6 +150,7 @@ pub const Tag = enum(u8) { .simple_type, .simple_value, .int32, + .opaque_value, => unreachable, // does not have a payload .float, .comptime_float => Float, .func => FuncDecl, @@ -327,7 +331,7 @@ pub const Value = enum(u32) { .func => value.toKey(ip).func.ty, .struct_value => value.toKey(ip).struct_value.ty, .array_value => value.toKey(ip).array_value.type, - .external_value => .@"opaque", + .external_value, .opaque_value => .@"opaque", }; } @@ -871,6 +875,7 @@ pub const Key = union(enum) { struct_value: StructValue, func: Func, array_value: ArrayValue, + opaque_value: Value, // Types simple_type: SimpleType, function_type: FunctionType, @@ -991,6 +996,7 @@ pub const Key = union(enum) { inline .int32, .simple_value, .simple_type, + .opaque_value, => |x| Hash.hash(seed, asBytes(&x)), .string, => |x| Hash.hash(seed, x), @@ -1023,6 +1029,7 @@ pub const Key = union(enum) { inline .int32, .simple_value, .simple_type, + .opaque_value, => |x, tag| x == @field(b, @tagName(tag)), .string, => |x| std.mem.eql(u8, x, b.string), @@ -1272,6 +1279,7 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { .simple_type => .{ .simple_type = data.decode(.simple_type, item.tag) }, .simple_value => .{ .simple_value = data.decode(.simple_value, item.tag) }, + .opaque_value => .{ .opaque_value = data.decode(.opaque_value, item.tag) }, .int32 => .{ .int32 = data.decode(.int32, item.tag) }, .float => .{ .float = data.decode(.float, item.tag).get(ip).decode() }, .comptime_float => .{ @@ -1350,6 +1358,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { inline .int32, .simple_type, .simple_value, + .opaque_value, => |s, tag| Item.encode(@field(Tag, @tagName(tag)), s), .string => |s| Item.encode( .string, diff --git a/src/core/Report.zig b/src/core/Report.zig index f752227c75a6a04925a44c71ace4a0c54c467d32..58e59120d6ad9c8fd48cc6b270271b6c01dfc523 100644 --- a/src/core/Report.zig +++ b/src/core/Report.zig @@ -1202,19 +1202,11 @@ pub const LazyNode = struct { else => {}, } - if (builtin.mode == .Debug) { - std.debug.panic("TODO: operand lookup: .{s} + .{s} + {}", .{ - @tagName(teg.instTag(lazy.inst)), - @tagName(ctx.ast.nodeTag(base_node)), - lazy.operand, - }); - } else { - std.debug.print("TODO: operand lookup: .{s} + .{s} + {}", .{ - @tagName(teg.instTag(lazy.inst)), - @tagName(ctx.ast.nodeTag(base_node)), - lazy.operand, - }); - } + std.debug.print("TODO: operand lookup: .{s} + .{s} + {}\n", .{ + @tagName(teg.instTag(lazy.inst)), + @tagName(ctx.ast.nodeTag(base_node)), + lazy.operand, + }); return base_node; } diff --git a/src/core/Sema.zig b/src/core/Sema.zig index 36b7ae588ecfdb1e7adc1221ec6184aafc49ba1a..cd5881ac5810b77ffc6fb5b0da7d2f552fd074e0 100644 --- a/src/core/Sema.zig +++ b/src/core/Sema.zig @@ -1548,7 +1548,7 @@ fn coerceValue(s: *Sema, src: LazyNode, value: Value, to: Type) Error!Value { } switch (to) { .@"opaque" => { - // TODO: + return try s.makeValue(.{ .opaque_value = value }); }, .bool => { // TODO: diff --git a/src/core/Transform.zig b/src/core/Transform.zig index 912a57acd84f341f08e433740ddd9c7d72f03460..32509ffc2eba9d367bf18111af3fbe6ec57ee987 100644 --- a/src/core/Transform.zig +++ b/src/core/Transform.zig @@ -366,6 +366,7 @@ const built_in_ids = std.StaticStringMap(Inst.Ref).initComptime(.{ .{ "int", .int32_type }, .{ "float", .float_type }, .{ "string", .string_type }, + .{ "opaque", .opaque_type }, // .{ "bigint", .bigint_type }, .{ "bool", .bool_type }, .{ "never", .never_type }, diff --git a/src/core/js/Link.zig b/src/core/js/Link.zig index 632ac0ad3e7ca9237e463ec9060bee64e80d292b..1fbb16b6fb7618dd551f650de75c2c7eeabd5d59 100644 --- a/src/core/js/Link.zig +++ b/src/core/js/Link.zig @@ -482,7 +482,18 @@ fn printExprLevel( const call: Tree.Call = tree.nodeData(.call, node); const args = call.args.get(tree); - try link.printExpr(tree, call.base, writer); + if (tree.nodeTag(call.base) == .plain_value and brk: { + const k = tree.nodeData(.plain_value, call.base).value.toKey(&link.comp.intern_pool); + break :brk k == .external_value and + k.external_value.key.len == 1 and + std.mem.eql(u8, k.external_value.key[0].toSlice(&link.comp.intern_pool), "eval"); + }) { + @branchHint(.unlikely); + try writer.writeAll("(0, eval)"); + } else { + try link.printExpr(tree, call.base, writer); + } + try writer.writeAll("("); for (args.slice(tree), 0..) |arg, i| { diff --git a/src/core/js/NodeGen.zig b/src/core/js/NodeGen.zig index d5765e841097753b3b56d9bd992a7f011d821bbd..5ed8f7017f896b336b79b901ef3c3c3b721e508f 100644 --- a/src/core/js/NodeGen.zig +++ b/src/core/js/NodeGen.zig @@ -137,14 +137,6 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void { .block => try c.codeGenBlock(inst), - // .js_global_ref => { - // const data: InternPool.String.WithLen = c.air.instData(.js_global_ref, inst); - // try c.extern_symbols.put(c.gpa, data, {}); - // c.air_node_map[@intFromEnum(inst)] = .{ - // .node = try c.add(.global, .{ .name = data }), - // }; - // }, - .memory => { const i = @intFromEnum(inst); const data: Air.Memory = c.air.instData(.memory, inst); @@ -574,9 +566,16 @@ fn valueToExpression(c: *NodeGen, v: Value) !Node.Index { .simple_value, .struct_value, .array_value, - .external_value, => return try c.add(.plain_value, .{ .value = v }), + .external_value => { + const external = v.toKey(c.ip).external_value; + try c.extern_symbols.put(c.gpa, external.key[0].toString().withLen(external.key[0].length(c.ip)), {}); + return try c.add(.plain_value, .{ .value = v }); + }, + + .opaque_value => return c.valueToExpression(v.toKey(c.ip).opaque_value), + // Hoist functions as top level values // TODO: Consider hoisting large values too .func => { diff --git a/test/behavior/direct_eval b/test/behavior/direct_eval new file mode 100644 index 0000000000000000000000000000000000000000..8c04734da978e8280ecd3000b78b0cdfc5f91698 --- /dev/null +++ b/test/behavior/direct_eval @@ -0,0 +1,6 @@ +let eval = @extern("eval"); + +fn main { + eval("var x = 1"); + eval("if (globalThis.x != 1) throw new Error('Emitted as direct eval');"); +} -- 2.54.0