diff --git a/src/engines/v8/types_primitives.zig b/src/engines/v8/types_primitives.zig index e4d6716..74228b9 100644 --- a/src/engines/v8/types_primitives.zig +++ b/src/engines/v8/types_primitives.zig @@ -166,19 +166,29 @@ pub fn jsToObject( isolate: v8.Isolate, ctx: v8.Context, ) !T { + const info = @typeInfo(T); + + // JS Null or Undefined value + if (js_val.isNull() or js_val.isUndefined()) { + // if Native optional type return null + if (comptime info == .Optional) { + return null; + } + } + + // check it's a JS object if (!js_val.isObject()) { return error.JSNotObject; } // unwrap Optional - const info = @typeInfo(T); if (comptime info == .Optional) { return try jsToObject(alloc, nested_T, info.Optional.child, js_val, isolate, ctx); } const js_obj = js_val.castTo(v8.Object); var obj: T = undefined; - inline for (nested_T.fields) |field| { + inline for (nested_T.fields, 0..) |field, i| { const name = field.name.?; const key = v8.String.initUtf8(isolate, name); if (js_obj.has(ctx, key.toValue())) { @@ -188,7 +198,7 @@ pub fn jsToObject( } else { if (comptime field.underOpt() != null) { @field(obj, name) = null; - } else { + } else if (comptime !refl.hasDefaultValue(nested_T.T, i)) { return error.JSWrongObject; } } diff --git a/src/reflect.zig b/src/reflect.zig index f78a04d..7ba2884 100644 --- a/src/reflect.zig +++ b/src/reflect.zig @@ -1656,6 +1656,11 @@ pub fn postAttachFunc(comptime T: type) !?type { return argsT(func); } +pub fn hasDefaultValue(comptime T: type, comptime index: usize) bool { + std.debug.assert(@inComptime()); + return @typeInfo(T).Struct.fields[index].default_value != null; +} + // Utils funcs // -----------