From b5b8f5b7d98ee7c823a28a29b8ac9a370b26de36 Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Sat, 29 Jul 2023 12:04:52 +0400 Subject: [PATCH] Move Object.UnknownKeys from metadata to tagged type --- CHANGELOG_NEXT.md | 1 + IDEAS.md | 1 - src/S.bs.mjs | 144 +++++++++++++++++++++++++++------------------- src/S.res | 122 ++++++++++++++------------------------- src/S.resi | 9 +-- 5 files changed, 131 insertions(+), 146 deletions(-) diff --git a/CHANGELOG_NEXT.md b/CHANGELOG_NEXT.md index 263c0fee..60f8454a 100644 --- a/CHANGELOG_NEXT.md +++ b/CHANGELOG_NEXT.md @@ -45,6 +45,7 @@ - Updated API for `S.Tuple.factory`. There are plans to change it once more before the actual release - `S.variant` used to fail when using value multiple times. Now it allows to create a struct and fails only on serializing with `InvalidOperation` code. - Added `fail` and `failWithError` methods to the `catchCtx` +- `Object.UnknownKeys` moved from metadata to `tagged` type ## TS API changes diff --git a/IDEAS.md b/IDEAS.md index 2efa0521..2c098149 100644 --- a/IDEAS.md +++ b/IDEAS.md @@ -51,7 +51,6 @@ let struct = S.tuple(s => (s.tag(0, "A"), s.item(1, S.int))) - Add built-in refinements to TS API // TODO: Update gen.ts - Update S_Js.res to create new structs instead of mixin in the methods -- Use isObject check for S.object (???) ## v5.1 diff --git a/src/S.bs.mjs b/src/S.bs.mjs index 91e46bd0..8633dd9b 100644 --- a/src/S.bs.mjs +++ b/src/S.bs.mjs @@ -1338,17 +1338,6 @@ function factory(struct, definer) { }; } -var metadataId = "rescript-struct:Object.UnknownKeys"; - -function classify$2(struct) { - var t = struct.m[metadataId]; - if (t !== undefined) { - return t; - } else { - return "Strip"; - } -} - function factory$1(definer) { var fields = {}; var fieldNames = []; @@ -1386,7 +1375,8 @@ function factory$1(definer) { t: { TAG: "Object", fields: fields, - fieldNames: fieldNames + fieldNames: fieldNames, + unknownKeys: "Strip" }, pb: (function (b, selfStruct, inputVar, pathVar) { var asyncOutputVars = []; @@ -1399,7 +1389,7 @@ function factory$1(definer) { received: input }; }), inputVar) + "}"; - var withUnknownKeysRefinement = classify$2(selfStruct) === "Strict"; + var withUnknownKeysRefinement = selfStruct.t._0.unknownKeys === "Strict"; if (withUnknownKeysRefinement) { if (fieldDefinitions.length !== 0) { var keyVar = $$var(b); @@ -1577,11 +1567,51 @@ function factory$1(definer) { } function strip(struct) { - return set(struct, metadataId, "Strip"); + var match = struct.t; + if (typeof match !== "object" || !(match.TAG === "Object" && match.unknownKeys !== "Strip")) { + return struct; + } else { + return { + t: { + TAG: "Object", + fields: match.fields, + fieldNames: match.fieldNames, + unknownKeys: "Strip" + }, + pb: struct.pb, + sb: struct.sb, + i: 0, + s: initialSerialize, + j: initialSerializeToJson, + p: intitialParse, + a: intitialParseAsync, + m: struct.m + }; + } } function strict(struct) { - return set(struct, metadataId, "Strict"); + var match = struct.t; + if (typeof match !== "object" || !(match.TAG === "Object" && match.unknownKeys === "Strip")) { + return struct; + } else { + return { + t: { + TAG: "Object", + fields: match.fields, + fieldNames: match.fieldNames, + unknownKeys: "Strict" + }, + pb: struct.pb, + sb: struct.sb, + i: 0, + s: initialSerialize, + j: initialSerializeToJson, + p: intitialParse, + a: intitialParseAsync, + m: struct.m + }; + } } function builder(b, selfStruct, inputVar, pathVar) { @@ -1618,10 +1648,10 @@ var struct$1 = { m: emptyMetadataMap }; -var metadataId$1 = "rescript-struct:String.refinements"; +var metadataId = "rescript-struct:String.refinements"; function refinements(struct) { - var m = struct.m[metadataId$1]; + var m = struct.m[metadataId]; if (m !== undefined) { return m; } else { @@ -1670,7 +1700,7 @@ function min(struct, maybeMessage, length) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: { TAG: "Min", length: length @@ -1689,7 +1719,7 @@ function max(struct, maybeMessage, length) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: { TAG: "Max", length: length @@ -1708,7 +1738,7 @@ function length(struct, maybeMessage, length$1) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: { TAG: "Length", length: length$1 @@ -1727,7 +1757,7 @@ function email(struct, messageOpt, param) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: "Email", message: message }, refiner); @@ -1743,7 +1773,7 @@ function uuid(struct, messageOpt, param) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: "Uuid", message: message }, refiner); @@ -1759,7 +1789,7 @@ function cuid(struct, messageOpt, param) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: "Cuid", message: message }, refiner); @@ -1783,7 +1813,7 @@ function url(struct, messageOpt, param) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: "Url", message: message }, refiner); @@ -1800,7 +1830,7 @@ function pattern(struct, messageOpt, re) { }; }; - return addRefinement(struct, metadataId$1, { + return addRefinement(struct, metadataId, { kind: { TAG: "Pattern", re: re @@ -1815,8 +1845,8 @@ function datetime(struct, messageOpt, param) { kind: "Datetime", message: message }; - var refinements = struct.m[metadataId$1]; - return transform(set(struct, metadataId$1, refinements !== undefined ? refinements.concat(refinement) : [refinement]), (function (s) { + var refinements = struct.m[metadataId]; + return transform(set(struct, metadataId, refinements !== undefined ? refinements.concat(refinement) : [refinement]), (function (s) { return { p: (function (string) { if (!datetimeRe.test(string)) { @@ -1902,10 +1932,10 @@ var struct$3 = { m: emptyMetadataMap }; -var metadataId$2 = "rescript-struct:Int.refinements"; +var metadataId$1 = "rescript-struct:Int.refinements"; function refinements$1(struct) { - var m = struct.m[metadataId$2]; + var m = struct.m[metadataId$1]; if (m !== undefined) { return m; } else { @@ -1944,7 +1974,7 @@ function min$1(struct, maybeMessage, minValue) { }; }; - return addRefinement(struct, metadataId$2, { + return addRefinement(struct, metadataId$1, { kind: { TAG: "Min", value: minValue @@ -1963,7 +1993,7 @@ function max$1(struct, maybeMessage, maxValue) { }; }; - return addRefinement(struct, metadataId$2, { + return addRefinement(struct, metadataId$1, { kind: { TAG: "Max", value: maxValue @@ -1982,16 +2012,16 @@ function port(struct, messageOpt, param) { }; }; - return addRefinement(struct, metadataId$2, { + return addRefinement(struct, metadataId$1, { kind: "Port", message: message }, refiner); } -var metadataId$3 = "rescript-struct:Float.refinements"; +var metadataId$2 = "rescript-struct:Float.refinements"; function refinements$2(struct) { - var m = struct.m[metadataId$3]; + var m = struct.m[metadataId$2]; if (m !== undefined) { return m; } else { @@ -2030,7 +2060,7 @@ function min$2(struct, maybeMessage, minValue) { }; }; - return addRefinement(struct, metadataId$3, { + return addRefinement(struct, metadataId$2, { kind: { TAG: "Min", value: minValue @@ -2049,7 +2079,7 @@ function max$2(struct, maybeMessage, maxValue) { }; }; - return addRefinement(struct, metadataId$3, { + return addRefinement(struct, metadataId$2, { kind: { TAG: "Max", value: maxValue @@ -2127,10 +2157,10 @@ function factory$4(struct) { }; } -var metadataId$4 = "rescript-struct:Array.refinements"; +var metadataId$3 = "rescript-struct:Array.refinements"; function refinements$3(struct) { - var m = struct.m[metadataId$4]; + var m = struct.m[metadataId$3]; if (m !== undefined) { return m; } else { @@ -2197,7 +2227,7 @@ function min$3(struct, maybeMessage, length) { }; }; - return addRefinement(struct, metadataId$4, { + return addRefinement(struct, metadataId$3, { kind: { TAG: "Min", length: length @@ -2216,7 +2246,7 @@ function max$3(struct, maybeMessage, length) { }; }; - return addRefinement(struct, metadataId$4, { + return addRefinement(struct, metadataId$3, { kind: { TAG: "Max", length: length @@ -2235,7 +2265,7 @@ function length$1(struct, maybeMessage, length$2) { }; }; - return addRefinement(struct, metadataId$4, { + return addRefinement(struct, metadataId$3, { kind: { TAG: "Length", length: length$2 @@ -2297,7 +2327,7 @@ function factory$6(struct) { }; } -var metadataId$5 = "rescript-struct:Default"; +var metadataId$4 = "rescript-struct:Default"; function factory$7(struct, getDefaultValue) { var struct$1 = factory$4(struct); @@ -2322,11 +2352,11 @@ function factory$7(struct, getDefaultValue) { p: intitialParse, a: intitialParseAsync, m: emptyMetadataMap - }, metadataId$5, getDefaultValue); + }, metadataId$4, getDefaultValue); } -function classify$3(struct) { - var getDefaultValue = struct.m[metadataId$5]; +function classify$2(struct) { + var getDefaultValue = struct.m[metadataId$4]; if (getDefaultValue !== undefined) { return Caml_option.some(getDefaultValue(undefined)); } @@ -2787,10 +2817,10 @@ function internalInline(struct, maybeVariant, param) { case "Option" : var struct$1 = taggedLiteral._0; var internalInlinedStruct = internalInline(struct$1, undefined, undefined); - var defaultValue = classify$3(struct$1); + var defaultValue = classify$2(struct$1); if (defaultValue !== undefined) { var defaultValue$1 = Caml_option.valFromOption(defaultValue); - Js_dict.unsafeDeleteKey(metadataMap, metadataId$5); + Js_dict.unsafeDeleteKey(metadataMap, metadataId$4); inlinedStruct = internalInlinedStruct + ("->S.default(() => %raw(\`" + ( defaultValue$1 === (void 0) ? "undefined" : JSON.stringify(defaultValue$1) ) + "\`))"); @@ -2849,10 +2879,9 @@ function internalInline(struct, maybeVariant, param) { var inlinedStruct$2 = message$1 !== undefined ? (Js_dict.unsafeDeleteKey(metadataMap, descriptionMetadataId), inlinedStruct$1 + ("->S.describe(" + ( message$1 === (void 0) ? "undefined" : JSON.stringify(message$1) ) + ")")) : inlinedStruct$1; - var match = classify$2(struct); + var match = struct.t; var inlinedStruct$3; - inlinedStruct$3 = match === "Strict" ? inlinedStruct$2 + "->S.Object.strict" : inlinedStruct$2; - Js_dict.unsafeDeleteKey(metadataMap, metadataId); + inlinedStruct$3 = typeof match !== "object" || !(match.TAG === "Object" && match.unknownKeys !== "Strip") ? inlinedStruct$2 : inlinedStruct$2 + "->S.Object.strict"; var match$1 = struct.t; var inlinedStruct$4; var exit = 0; @@ -2864,7 +2893,7 @@ function internalInline(struct, maybeVariant, param) { case "Int" : var refinements$4 = refinements$1(struct); if (refinements$4.length !== 0) { - Js_dict.unsafeDeleteKey(metadataMap, metadataId$2); + Js_dict.unsafeDeleteKey(metadataMap, metadataId$1); inlinedStruct$4 = inlinedStruct$3 + refinements$4.map(function (refinement) { var match = refinement.kind; if (typeof match !== "object") { @@ -2882,7 +2911,7 @@ function internalInline(struct, maybeVariant, param) { case "Float" : var refinements$5 = refinements$2(struct); if (refinements$5.length !== 0) { - Js_dict.unsafeDeleteKey(metadataMap, metadataId$3); + Js_dict.unsafeDeleteKey(metadataMap, metadataId$2); inlinedStruct$4 = inlinedStruct$3 + refinements$5.map(function (refinement) { var match = refinement.kind; if (match.TAG === "Min") { @@ -2916,7 +2945,7 @@ function internalInline(struct, maybeVariant, param) { case "Array" : var refinements$6 = refinements$3(struct); if (refinements$6.length !== 0) { - Js_dict.unsafeDeleteKey(metadataMap, metadataId$4); + Js_dict.unsafeDeleteKey(metadataMap, metadataId$3); inlinedStruct$4 = inlinedStruct$3 + refinements$6.map(function (refinement) { var match = refinement.kind; switch (match.TAG) { @@ -2940,7 +2969,7 @@ function internalInline(struct, maybeVariant, param) { if (exit === 1) { var refinements$7 = refinements(struct); if (refinements$7.length !== 0) { - Js_dict.unsafeDeleteKey(metadataMap, metadataId$1); + Js_dict.unsafeDeleteKey(metadataMap, metadataId); inlinedStruct$4 = inlinedStruct$3 + refinements$7.map(function (refinement) { var match = refinement.kind; if (typeof match !== "object") { @@ -3064,12 +3093,7 @@ var parseAsyncWith = parseAnyAsyncWith; var parseAsyncInStepsWith = parseAnyAsyncInStepsWith; -var Object_UnknownKeys = { - classify: classify$2 -}; - var $$Object = { - UnknownKeys: Object_UnknownKeys, factory: factory$1, strip: strip, strict: strict @@ -3138,7 +3162,7 @@ var $$Array = { }; var Default = { - classify: classify$3 + classify: classify$2 }; var Metadata = { diff --git a/src/S.res b/src/S.res index 9ff75586..7b45ff8c 100644 --- a/src/S.res +++ b/src/S.res @@ -353,6 +353,7 @@ let symbol = Stdlib.Symbol.make("rescript-struct") @unboxed type isAsyncParse = | @as(0) Unknown | Value(bool) +type unknownKeys = Strip | Strict type rec t<'value> = { @as("t") @@ -385,7 +386,7 @@ and tagged = | Option(t) | Null(t) | Array(t) - | Object({fields: Js.Dict.t>, fieldNames: array}) + | Object({fields: Js.Dict.t>, fieldNames: array, unknownKeys: unknownKeys}) | Tuple(array>) | Union(array>) | Dict(t) @@ -851,7 +852,7 @@ let intitialParseAsync = input => { } @inline -let make = (~tagged, ~metadataMap, ~parseOperationBuilder, ~serializeOperationBuilder, ()) => { +let make = (~tagged, ~metadataMap, ~parseOperationBuilder, ~serializeOperationBuilder) => { tagged, parseOperationBuilder, serializeOperationBuilder, @@ -1088,7 +1089,6 @@ module Metadata = { ~serializeOperationBuilder=struct.serializeOperationBuilder, ~tagged=struct.tagged, ~metadataMap, - (), ) } } @@ -1176,7 +1176,6 @@ let refine: (t<'value>, effectCtx<'value> => 'value => unit) => t<'value> = (str ) }), ~metadataMap=struct.metadataMap, - (), ) } @@ -1200,7 +1199,6 @@ let asyncParserRefine = (struct, refiner) => { }), ~serializeOperationBuilder=struct.serializeOperationBuilder, ~metadataMap=struct.metadataMap, - (), ) } @@ -1272,7 +1270,6 @@ let transform: ( } }), ~metadataMap=struct.metadataMap, - (), ) } @@ -1297,7 +1294,6 @@ let rec preprocess = (struct, transformer) => { ~parseOperationBuilder=struct.parseOperationBuilder, ~serializeOperationBuilder=struct.serializeOperationBuilder, ~metadataMap=struct.metadataMap, - (), ) | _ => make( @@ -1358,7 +1354,6 @@ let rec preprocess = (struct, transformer) => { } }), ~metadataMap=struct.metadataMap, - (), ) } } @@ -1407,7 +1402,6 @@ let custom = (name, definer) => { b->B.missingOperation(~pathVar, ~description=`The S.custom serializer is missing`) } }), - (), ) } @@ -1475,7 +1469,6 @@ let literal = value => { ~tagged=Literal(literal), ~parseOperationBuilder=operationBuilder, ~serializeOperationBuilder=operationBuilder, - (), ) } @@ -1619,7 +1612,6 @@ module Variant = { } }), ~metadataMap=struct.metadataMap, - (), ) } } @@ -1631,36 +1623,15 @@ module Object = { @as("t") tag: 'value. (string, 'value) => unit, } type registered = | @as(0) Unregistered | @as(1) ByParsing | @as(2) BySerializing - - module UnknownKeys = { - type tagged = - | Strict - | Strip - - let metadataId: Metadata.Id.t = Metadata.Id.make( - ~namespace="rescript-struct", - ~name="Object.UnknownKeys", - ) - - let classify = struct => { - switch struct->Metadata.get(~id=metadataId) { - | Some(t) => t - | None => Strip - } - } - } - - module FieldDefinition = { - type t = { - @as("s") - struct: struct, - @as("l") - inlinedInputLocation: string, - @as("p") - inputPath: Path.t, - @as("r") - mutable registered: registered, - } + type fieldDefinition = { + @as("s") + struct: struct, + @as("l") + inlinedInputLocation: string, + @as("p") + inputPath: Path.t, + @as("r") + mutable registered: registered, } module Ctx = { @@ -1670,7 +1641,7 @@ module Object = { @as("h") fields: Js.Dict.t>, @as("d") - fieldDefinitionsSet: Stdlib.Set.t, + fieldDefinitionsSet: Stdlib.Set.t, ...ctx, } @@ -1691,7 +1662,7 @@ module Object = { ) | false => { let inlinedInputLocation = fieldName->Stdlib.Inlined.Value.fromString - let fieldDefinition: FieldDefinition.t = { + let fieldDefinition: fieldDefinition = { struct, inlinedInputLocation, inputPath: inlinedInputLocation->Path.fromInlinedLocation, @@ -1700,7 +1671,7 @@ module Object = { fields->Js.Dict.set(fieldName, struct) fieldNames->Js.Array2.push(fieldName)->ignore fieldDefinitionsSet->Stdlib.Set.add(fieldDefinition)->ignore - fieldDefinition->(Obj.magic: FieldDefinition.t => value) + fieldDefinition->(Obj.magic: fieldDefinition => value) } } } @@ -1722,7 +1693,7 @@ module Object = { let factory = definer => { let ctx = Ctx.make() - let definition = definer((ctx :> ctx))->(Obj.magic: 'any => Definition.t) + let definition = definer((ctx :> ctx))->(Obj.magic: 'any => Definition.t) let {fieldDefinitionsSet, fields, fieldNames} = ctx let fieldDefinitions = fieldDefinitionsSet->Stdlib.Set.toArray @@ -1731,6 +1702,7 @@ module Object = { ~tagged=Object({ fields, fieldNames, + unknownKeys: Strip, }), ~parseOperationBuilder=Builder.make((b, ~selfStruct, ~inputVar, ~pathVar) => { let asyncOutputVars = [] @@ -1747,7 +1719,8 @@ module Object = { inputVar, )}}` - let withUnknownKeysRefinement = selfStruct->UnknownKeys.classify === UnknownKeys.Strict + let withUnknownKeysRefinement = + (selfStruct->classify->unsafeGetVariantPayload)["unknownKeys"] === Strict switch (withUnknownKeysRefinement, fieldDefinitions) { | (true, []) => { let keyVar = b->B.var @@ -1783,10 +1756,7 @@ module Object = { b.code = "" let syncOutput = { - let rec definitionToOutput = ( - definition: Definition.t, - ~outputPath, - ) => { + let rec definitionToOutput = (definition: Definition.t, ~outputPath) => { let kind = definition->Definition.toKindWithSet(~embededSet=fieldDefinitionsSet) switch kind { | Embeded => { @@ -1889,10 +1859,7 @@ module Object = { { let parentCode = b.code b.code = "" - let rec definitionToOutput = ( - definition: Definition.t, - ~outputPath, - ) => { + let rec definitionToOutput = (definition: Definition.t, ~outputPath) => { let kind = definition->Definition.toKindWithSet(~embededSet=fieldDefinitionsSet) switch kind { | Embeded => @@ -1977,16 +1944,33 @@ module Object = { `{${fieldsCodeRef.contents}}` }), - (), ) } let strip = struct => { - struct->Metadata.set(~id=UnknownKeys.metadataId, UnknownKeys.Strip) + switch struct->classify { + | Object({unknownKeys: Strict, fieldNames, fields}) => + make( + ~tagged=Object({unknownKeys: Strip, fieldNames, fields}), + ~parseOperationBuilder=struct.parseOperationBuilder, + ~serializeOperationBuilder=struct.serializeOperationBuilder, + ~metadataMap=struct.metadataMap, + ) + | _ => struct + } } let strict = struct => { - struct->Metadata.set(~id=UnknownKeys.metadataId, UnknownKeys.Strict) + switch struct->classify { + | Object({unknownKeys: Strip, fieldNames, fields}) => + make( + ~tagged=Object({unknownKeys: Strict, fieldNames, fields}), + ~parseOperationBuilder=struct.parseOperationBuilder, + ~serializeOperationBuilder=struct.serializeOperationBuilder, + ~metadataMap=struct.metadataMap, + ) + | _ => struct + } } } @@ -2007,7 +1991,6 @@ module Never = { ~tagged=Never, ~parseOperationBuilder=builder, ~serializeOperationBuilder=builder, - (), ) } @@ -2017,7 +2000,6 @@ module Unknown = { ~tagged=Unknown, ~parseOperationBuilder=Builder.noop, ~serializeOperationBuilder=Builder.noop, - (), ) } @@ -2077,7 +2059,6 @@ module String = { ~tagged=String, ~parseOperationBuilder, ~serializeOperationBuilder=Builder.noop, - (), ) let min = (struct, ~message as maybeMessage=?, length) => { @@ -2288,7 +2269,6 @@ module JsonString = { ~pathVar, )})` }), - (), ) } } @@ -2311,7 +2291,6 @@ module Bool = { inputVar }), ~serializeOperationBuilder=Builder.noop, - (), ) } @@ -2356,7 +2335,6 @@ module Int = { inputVar }), ~serializeOperationBuilder=Builder.noop, - (), ) let min = (struct, ~message as maybeMessage=?, minValue) => { @@ -2456,7 +2434,6 @@ module Float = { inputVar }), ~serializeOperationBuilder=Builder.noop, - (), ) let min = (struct, ~message as maybeMessage=?, minValue) => { @@ -2545,7 +2522,6 @@ module Null = { })}}else{${outputVar}=null}` outputVar }), - (), ) } } @@ -2598,7 +2574,6 @@ module Option = { })}}else{${outputVar}=void 0}` outputVar }), - (), ) } } @@ -2693,7 +2668,6 @@ module Array = { outputVar }), - (), ) } @@ -2828,7 +2802,6 @@ module Dict = { outputVar }), - (), ) } } @@ -2873,7 +2846,6 @@ module Default = { outputVar }), ~serializeOperationBuilder=struct.serializeOperationBuilder, - (), )->Metadata.set(~id=metadataId, getDefaultValue) } @@ -2982,7 +2954,6 @@ module Tuple = { }) | _ => Builder.noop }, - (), ) } @@ -3131,7 +3102,6 @@ module Union = { outputVar }), - (), ) } } @@ -3199,7 +3169,6 @@ let json = make( `${b->B.embed(parse)}(${inputVar},${pathVar})` }), ~serializeOperationBuilder=Builder.noop, - (), ) type catchCtx<'value> = { @@ -3259,7 +3228,6 @@ let catch = (struct, getFallbackValue) => { ~serializeOperationBuilder=struct.serializeOperationBuilder, ~tagged=struct.tagged, ~metadataMap=struct.metadataMap, - (), ) } @@ -3449,12 +3417,10 @@ let inline = { | None => inlinedStruct } - let inlinedStruct = switch struct->Object.UnknownKeys.classify { - | Strict => inlinedStruct ++ `->S.Object.strict` - - | Strip => inlinedStruct + let inlinedStruct = switch struct->classify { + | Object({unknownKeys: Strict}) => inlinedStruct ++ `->S.Object.strict` + | _ => inlinedStruct } - metadataMap->Stdlib.Dict.deleteInPlace(Object.UnknownKeys.metadataId->Metadata.Id.toKey) let inlinedStruct = switch struct->classify { | String diff --git a/src/S.resi b/src/S.resi index 3d9d3286..77e44fac 100644 --- a/src/S.resi +++ b/src/S.resi @@ -54,7 +54,7 @@ and tagged = | Option(t) | Null(t) | Array(t) - | Object({fields: Js.Dict.t>, fieldNames: array}) + | Object({fields: Js.Dict.t>, fieldNames: array, unknownKeys: unknownKeys}) | Tuple(array>) | Union(array>) | Dict(t) @@ -74,6 +74,7 @@ and errorCode = and operation = | Serializing | Parsing +and unknownKeys = Strip | Strict type effectCtx<'value> = { @as("s") struct: t<'value>, @@ -208,12 +209,6 @@ module Object: { @as("t") tag: 'value. (string, 'value) => unit, } - module UnknownKeys: { - type tagged = Strict | Strip - - let classify: t<'value> => tagged - } - /* The same as S.object. Expose only for PPX since the object is a reserved name in OCaml */ let factory: (ctx => 'value) => t<'value>