diff --git a/packages/tests/src/core/Example_test.res b/packages/tests/src/core/Example_test.res index a408ae17..8580c378 100644 --- a/packages/tests/src/core/Example_test.res +++ b/packages/tests/src/core/Example_test.res @@ -69,7 +69,7 @@ test("Compiled parse code snapshot", t => { t->U.assertCompiledCode( ~schema=filmSchema, ~op=#parse, - `i=>{if(!i||i.constructor!==Object){e[11](i)}let v0=i["Id"],v1=i["Title"],v2=i["Tags"],v7,v8=i["Rating"],v9,v14=i["Age"],v15;if(typeof v0!=="number"||Number.isNaN(v0)){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}if(v2!==void 0&&(!Array.isArray(v2))){e[2](v2)}if(v2!==void 0){let v6=[];for(let v3=0;v32147483647||v14<-2147483648||v14%1!==0)){e[10](v14)}if(v14!==void 0){v15=v14}return {"id":v0,"title":v1,"tags":v7===void 0?e[4]:v7,"rating":v9,"deprecatedAgeRestriction":v15,}}`, + `i=>{if(!i||i.constructor!==Object){e[11](i)}let v0=i["Id"],v1=i["Title"],v2=i["Tags"],v8,v9=i["Rating"],v10,v15=i["Age"],v16;if(typeof v0!=="number"||Number.isNaN(v0)){e[0](v0)}if(typeof v1!=="string"){e[1](v1)}if(v2!==void 0&&(!Array.isArray(v2))){e[2](v2)}if(v2!==void 0){let v7=[];for(let v3=0;v32147483647||v15<-2147483648||v15%1!==0)){e[10](v15)}if(v15!==void 0){v16=v15}return {"id":v0,"title":v1,"tags":v8===void 0?e[4]:v8,"rating":v10,"deprecatedAgeRestriction":v16,}}`, ) }) diff --git a/packages/tests/src/core/S_Option_getOrWith_test.res b/packages/tests/src/core/S_Option_getOrWith_test.res index bbbe0a30..715c0123 100644 --- a/packages/tests/src/core/S_Option_getOrWith_test.res +++ b/packages/tests/src/core/S_Option_getOrWith_test.res @@ -76,7 +76,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(i!==void 0&&(typeof i!=="boolean")){e[2](i)}let v1,v3;if(i!==void 0){let v0;v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}v3=()=>v1().then(v2=>{return v2===void 0?e[1]():v2});return v3}`, + `i=>{if(i!==void 0&&(typeof i!=="boolean")){e[2](i)}let v1,v3=()=>v1().then(v2=>{return v2===void 0?e[1]():v2});if(i!==void 0){let v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}return v3}`, ) }) diff --git a/packages/tests/src/core/S_Option_getOr_test.res b/packages/tests/src/core/S_Option_getOr_test.res index e4c85f6c..dd2ef1fe 100644 --- a/packages/tests/src/core/S_Option_getOr_test.res +++ b/packages/tests/src/core/S_Option_getOr_test.res @@ -100,7 +100,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(i!==void 0&&(typeof i!=="boolean")){e[2](i)}let v1,v3;if(i!==void 0){let v0;v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}v3=()=>v1().then(v2=>{return v2===void 0?e[1]:v2});return v3}`, + `i=>{if(i!==void 0&&(typeof i!=="boolean")){e[2](i)}let v1,v3=()=>v1().then(v2=>{return v2===void 0?e[1]:v2});if(i!==void 0){let v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}return v3}`, ) }) diff --git a/packages/tests/src/core/S_array_test.res b/packages/tests/src/core/S_array_test.res index 22767616..ac501295 100644 --- a/packages/tests/src/core/S_array_test.res +++ b/packages/tests/src/core/S_array_test.res @@ -52,7 +52,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(!Array.isArray(i)){e[1](i)}let v3=[];for(let v0=0;v0{if(!Array.isArray(i)){e[1](i)}let v4=[];for(let v0=0;v0U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(!Array.isArray(i)){e[1](i)}let v4=[],v5=()=>Promise.all(v4.map(t=>t()));for(let v0=0;v0{try{return v2().catch(v1=>{if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1})}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}};}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}v4.push(v3)}return v5}`, + `i=>{if(!Array.isArray(i)){e[1](i)}let v4=[],v5=()=>Promise.all(v4.map(t=>t()));for(let v0=0;v0{try{return v2().catch(v1=>{if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1})}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}}}catch(v1){if(v1&&v1.s===s){v1.path=""+\'["\'+v0+\'"]\'+v1.path}throw v1}v4.push(v3)}return v5}`, ) }) @@ -79,7 +79,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#serialize, - `i=>{let v4=[];for(let v0=0;v0{let v5=[];for(let v0=0;v0 { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{try{if(typeof i!=="boolean"){e[1](i)}}catch(v0){if(v0&&v0.s===s){i=e[0](i,v0)}else{throw v0}}return i}`, + // TODO: Improve to return i without reassigning + `i=>{let v1;try{if(typeof i!=="boolean"){e[1](i)}v1=i}catch(v0){if(v0&&v0.s===s){v1=e[0](i,v0)}else{throw v0}}return v1}`, ) }) @@ -127,7 +128,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{let v1,v2;try{if(typeof i!=="boolean"){e[1](i)}v1=e[2](i);v2=()=>{try{return v1().catch(v0=>{if(v0&&v0.s===s){return e[0](i,v0)}else{throw v0}})}catch(v0){if(v0&&v0.s===s){return Promise.resolve(e[0](i,v0))}else{throw v0}}};}catch(v0){if(v0&&v0.s===s){v2=()=>Promise.resolve(e[0](i,v0))}else{throw v0}}return v2}`, + `i=>{let v2;try{let v1=e[2](i);if(typeof i!=="boolean"){e[1](i)}v2=()=>{try{return v1().catch(v0=>{if(v0&&v0.s===s){return e[0](i,v0)}else{throw v0}})}catch(v0){if(v0&&v0.s===s){return Promise.resolve(e[0](i,v0))}else{throw v0}}}}catch(v0){if(v0&&v0.s===s){v2=()=>Promise.resolve(e[0](i,v0))}else{throw v0}}return v2}`, ) }) diff --git a/packages/tests/src/core/S_dict_test.res b/packages/tests/src/core/S_dict_test.res index 9a1d4095..60173c86 100644 --- a/packages/tests/src/core/S_dict_test.res +++ b/packages/tests/src/core/S_dict_test.res @@ -52,7 +52,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v1;v1={};for(let v0 in i){let v3=i[v0];try{if(typeof v3!=="string"){e[0](v3)}}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}v1[v0]=v3}return v1}`, + `i=>{if(!i||i.constructor!==Object){e[1](i)}let v1;v1={};for(let v0 in i){let v4;try{let v3=i[v0];if(typeof v3!=="string"){e[0](v3)}v4=v3}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}v1[v0]=v4}return v1}`, ) }) @@ -62,7 +62,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(!i||i.constructor!==Object){e[1](i)}let v1,v9;v1={};for(let v0 in i){let v3,v4;try{v3=e[0](i[v0]);v4=()=>{try{return v3().catch(v2=>{if(v2&&v2.s===s){v2.path=""+'["'+v0+'"]'+v2.path}throw v2})}catch(v2){if(v2&&v2.s===s){v2.path=""+'["'+v0+'"]'+v2.path}throw v2}};}catch(v2){if(v2&&v2.s===s){v2.path=""+'["'+v0+'"]'+v2.path}throw v2}v1[v0]=v4}v9=()=>new Promise((v5,v6)=>{let v8=Object.keys(v1).length;for(let v0 in v1){v1[v0]().then(v7=>{v1[v0]=v7;if(v8--===1){v5(v1)}},v6)}});return v9}`, + `i=>{if(!i||i.constructor!==Object){e[1](i)}let v1,v9;v1={};for(let v0 in i){let v4;try{let v3=e[0](i[v0]);v4=()=>{try{return v3().catch(v2=>{if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2})}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}}}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}v1[v0]=v4}v9=()=>new Promise((v5,v6)=>{let v8=Object.keys(v1).length;for(let v0 in v1){v1[v0]().then(v7=>{v1[v0]=v7;if(v8--===1){v5(v1)}},v6)}});return v9}`, ) }) @@ -78,7 +78,7 @@ module CommonWithNested = { t->U.assertCompiledCode( ~schema, ~op=#serialize, - `i=>{let v1;v1={};for(let v0 in i){let v3=i[v0],v4;try{if(v3!==void 0){v4=e[0](v3)}}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}v1[v0]=v4}return v1}`, + `i=>{let v1;v1={};for(let v0 in i){let v5;try{let v3=i[v0],v4;if(v3!==void 0){v4=e[0](v3)}v5=v4}catch(v2){if(v2&&v2.s===s){v2.path=""+\'["\'+v0+\'"]\'+v2.path}throw v2}v1[v0]=v5}return v1}`, ) }) } diff --git a/packages/tests/src/core/S_jsonString_test.res b/packages/tests/src/core/S_jsonString_test.res index f36979d4..d4638da5 100644 --- a/packages/tests/src/core/S_jsonString_test.res +++ b/packages/tests/src/core/S_jsonString_test.res @@ -81,7 +81,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(typeof i!=="string"){e[3](i)}let v0,v1;try{v0=JSON.parse(i)}catch(t){e[0](t.message)}if(typeof v0!=="boolean"){e[1](v0)}v1=e[2](v0);return v1}`, + `i=>{if(typeof i!=="string"){e[3](i)}let v0;try{v0=JSON.parse(i)}catch(t){e[0](t.message)}let v1=e[2](v0);if(typeof v0!=="boolean"){e[1](v0)}return v1}`, ) }) diff --git a/packages/tests/src/core/S_null_test.res b/packages/tests/src/core/S_null_test.res index 31cc4a59..3568cf82 100644 --- a/packages/tests/src/core/S_null_test.res +++ b/packages/tests/src/core/S_null_test.res @@ -48,7 +48,7 @@ module Common = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{let v1;if(i!==null){let v0;v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}return v1}`, + `i=>{let v1;if(i!==null){let v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}return v1}`, ) }) diff --git a/packages/tests/src/core/S_nullable_test.res b/packages/tests/src/core/S_nullable_test.res index 581c6c0f..d98ca8e5 100644 --- a/packages/tests/src/core/S_nullable_test.res +++ b/packages/tests/src/core/S_nullable_test.res @@ -50,7 +50,7 @@ module NullCommon = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{let v2;if(i!==void 0){let v1;if(i!==null){let v0;v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}v2=v1}else{v2=()=>Promise.resolve(void 0)}return v2}`, + `i=>{let v2;if(i!==void 0){let v1;if(i!==null){let v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}v2=v1}else{v2=()=>Promise.resolve(void 0)}return v2}`, ) }) diff --git a/packages/tests/src/core/S_object_test.res b/packages/tests/src/core/S_object_test.res index bd369ee0..d40ff86f 100644 --- a/packages/tests/src/core/S_object_test.res +++ b/packages/tests/src/core/S_object_test.res @@ -1004,7 +1004,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0,v1=i["bar"],v2=()=>Promise.all([v0()]).then(([v0])=>({"foo":v0,"bar":v1,}));v0=e[0](i["foo"]);if(typeof v1!=="boolean"){e[1](v1)}return v2}`, + `i=>{if(!i||i.constructor!==Object){e[2](i)}let v0=e[0](i["foo"]),v1=i["bar"],v2=()=>Promise.all([v0()]).then(([v0])=>({"foo":v0,"bar":v1,}));if(typeof v1!=="boolean"){e[1](v1)}return v2}`, ) }) diff --git a/packages/tests/src/core/S_option_test.res b/packages/tests/src/core/S_option_test.res index da0617c9..e0ca4d94 100644 --- a/packages/tests/src/core/S_option_test.res +++ b/packages/tests/src/core/S_option_test.res @@ -48,7 +48,7 @@ module Common = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{let v1;if(i!==void 0){let v0;v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}return v1}`, + `i=>{let v1;if(i!==void 0){let v0=e[0](i);v1=v0}else{v1=()=>Promise.resolve(void 0)}return v1}`, ) }) diff --git a/packages/tests/src/core/S_parseAnyAsyncInStepsWith_test.res b/packages/tests/src/core/S_parseAnyAsyncInStepsWith_test.res index 715d308b..b8756e3d 100644 --- a/packages/tests/src/core/S_parseAnyAsyncInStepsWith_test.res +++ b/packages/tests/src/core/S_parseAnyAsyncInStepsWith_test.res @@ -850,6 +850,12 @@ module Json = { asyncTest("[JsonString] Successfully parses", t => { let schema = S.jsonString(S.int->validAsyncRefine) + t->U.assertCompiledCode( + ~schema, + ~op=#parse, + `i=>{if(typeof i!=="string"){e[3](i)}let v0;try{v0=JSON.parse(i)}catch(t){e[0](t.message)}let v1=e[2](v0);if(typeof v0!=="number"||v0>2147483647||v0<-2147483648||v0%1!==0){e[1](v0)}return v1}`, + ) + ("1"->S.parseAnyAsyncInStepsWith(schema)->Result.getExn)()->Promise.thenResolve(result => { t->Assert.deepEqual(result, Ok(1), ()) }) diff --git a/packages/tests/src/core/S_preprocess_test.res b/packages/tests/src/core/S_preprocess_test.res index 31b6e616..0b21340f 100644 --- a/packages/tests/src/core/S_preprocess_test.res +++ b/packages/tests/src/core/S_preprocess_test.res @@ -270,7 +270,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{let v0,v1;v0=e[0](i);v1=()=>v0().then(v2=>{if(typeof v2!=="number"||v2>2147483647||v2<-2147483648||v2%1!==0){e[1](v2)}return v2});return v1}`, + `i=>{let v0=e[0](i),v1;v1=()=>v0().then(v2=>{if(typeof v2!=="number"||v2>2147483647||v2<-2147483648||v2%1!==0){e[1](v2)}return v2});return v1}`, ) }) diff --git a/packages/tests/src/core/S_refine_test.res b/packages/tests/src/core/S_refine_test.res index 37ed12c1..2f4c1c0e 100644 --- a/packages/tests/src/core/S_refine_test.res +++ b/packages/tests/src/core/S_refine_test.res @@ -50,6 +50,27 @@ test("Successfully refines on serializing", t => { ) }) +test("Successfully parses simple object with empty refine", t => { + let schema = S.object(s => + { + "foo": s.field("foo", S.string), + "bar": s.field("bar", S.bool), + } + )->S.refine(_ => _ => ()) + + t->Assert.deepEqual( + %raw(`{ + "foo": "string", + "bar": true, + }`)->S.parseAnyWith(schema), + Ok({ + "foo": "string", + "bar": true, + }), + (), + ) +}) + test("Compiled parse code snapshot for simple object with refine", t => { let schema = S.object(s => { @@ -62,6 +83,6 @@ test("Compiled parse code snapshot for simple object with refine", t => { ~schema, ~op=#parse, // FIXME: Double "let" looks wrong - `i=>{if(!i||i.constructor!==Object){e[3](i)}let v2={"foo":v0,"bar":v1,};let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}e[2](v2);return v2}`, + `i=>{if(!i||i.constructor!==Object){e[3](i)}let v2;let v0=i["foo"],v1=i["bar"];if(typeof v0!=="string"){e[0](v0)}if(typeof v1!=="boolean"){e[1](v1)}v2={"foo":v0,"bar":v1,};e[2](v2);return v2}`, ) }) diff --git a/packages/tests/src/core/S_transform_test.res b/packages/tests/src/core/S_transform_test.res index 675cf6d5..d4579462 100644 --- a/packages/tests/src/core/S_transform_test.res +++ b/packages/tests/src/core/S_transform_test.res @@ -322,7 +322,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(typeof i!=="number"||i>2147483647||i<-2147483648||i%1!==0){e[1](i)}let v0;v0=e[0](i);return v0}`, + `i=>{if(typeof i!=="number"||i>2147483647||i<-2147483648||i%1!==0){e[1](i)}let v0=e[0](i);return v0}`, ) }) diff --git a/packages/tests/src/core/S_tuple_test.res b/packages/tests/src/core/S_tuple_test.res index b3ca0c93..d4f550b9 100644 --- a/packages/tests/src/core/S_tuple_test.res +++ b/packages/tests/src/core/S_tuple_test.res @@ -247,7 +247,7 @@ module Compiled = { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{if(!Array.isArray(i)){e[3](i)}if(i.length!==2){e[0](i.length)}let v0,v1=i["1"],v2=()=>Promise.all([v0()]).then(([v0])=>([v0,v1,]));v0=e[1](i["0"]);if(typeof v1!=="boolean"){e[2](v1)}return v2}`, + `i=>{if(!Array.isArray(i)){e[3](i)}if(i.length!==2){e[0](i.length)}let v0=e[1](i["0"]),v1=i["1"],v2=()=>Promise.all([v0()]).then(([v0])=>([v0,v1,]));if(typeof v1!=="boolean"){e[2](v1)}return v2}`, ) }) diff --git a/packages/tests/src/core/S_union_test.res b/packages/tests/src/core/S_union_test.res index 281f2281..50263e14 100644 --- a/packages/tests/src/core/S_union_test.res +++ b/packages/tests/src/core/S_union_test.res @@ -360,7 +360,7 @@ test("Compiled async parse code snapshot", t => { t->U.assertCompiledCode( ~schema, ~op=#parse, - `i=>{let v0,v1;try{i===0||e[0](i);v0=e[1](i);throw v0}catch(v2){if(v2&&v2.s===s||v2===v0){try{i===1||e[2](i);v1=()=>Promise.resolve(i)}catch(v3){if(v3&&v3.s===s){v1=()=>Promise.any([v2===v0?v2():Promise.reject(v2),Promise.reject(v3)]).catch(t=>{e[3](t.errors)})}else{throw v3}}}else{throw v2}}return v1}`, + `i=>{let v0=e[1](i),v1;try{i===0||e[0](i);throw v0}catch(v2){if(v2&&v2.s===s||v2===v0){try{i===1||e[2](i);v1=()=>Promise.resolve(i)}catch(v3){if(v3&&v3.s===s){v1=()=>Promise.any([v2===v0?v2():Promise.reject(v2),Promise.reject(v3)]).catch(t=>{e[3](t.errors)})}else{throw v3}}}else{throw v2}}return v1}`, ) }) diff --git a/src/S_Core.bs.mjs b/src/S_Core.bs.mjs index b854347c..4fadaa67 100644 --- a/src/S_Core.bs.mjs +++ b/src/S_Core.bs.mjs @@ -104,20 +104,41 @@ function classify(schema) { } function scope(b, fn) { - var prevScope = b.x; var prevCode = b.c; - b.x = { - l: "" + var newScope = { + l: "", + a: false, + p: b.x }; + b.x = newScope; b.c = ""; var resultCode = fn(b); - var varsAllocation = b.x.l; + var varsAllocation = newScope.l; var code = varsAllocation === "" ? b.c : "let " + varsAllocation + ";" + b.c; - b.x = prevScope; + newScope.a = true; + b.x = newScope.p; b.c = prevCode; return code + resultCode; } +function valScope(b, fn) { + var prevCode = b.c; + var newScope = { + l: "", + a: false, + p: b.x + }; + b.x = newScope; + b.c = ""; + var val = fn(b); + var varsAllocation = newScope.l; + var code = varsAllocation === "" ? b.c : "let " + varsAllocation + ";" + b.c; + newScope.a = true; + b.x = newScope.p; + b.c = prevCode + code; + return val; +} + function varWithoutAllocation(b) { var newCounter = b.v + 1; b.v = newCounter; @@ -135,8 +156,7 @@ function $$var(b) { function allocateVal(b) { return { - x: b.x, - a: false + x: b.x }; } @@ -144,53 +164,67 @@ function val(b, initial) { if (b.s.has(initial)) { return { v: initial, - x: b.x, - a: false + x: b.x }; } else { return { i: initial, - x: b.x, - a: false + x: b.x }; } } function asyncVal(b, initial) { var $$var = varWithoutAllocation(b); - var allocation = $$var + "=()=>" + initial; + var allocation = $$var + "=" + initial; var varsAllocation = b.x.l; b.x.l = varsAllocation === "" ? allocation : varsAllocation + "," + allocation; return { v: $$var, - x: b.x, - a: true + x: b.x }; } -function inline(b, val) { - var $$var$1 = val.v; - if ($$var$1 !== undefined) { - return $$var$1; +function inline(_b, val) { + var $$var = val.v; + if ($$var !== undefined) { + return $$var; } var initial = val.i; if (initial !== undefined) { return initial; } else { - return $$var(b); + return Js_exn.raiseError("Can't inline undefined val"); } } +function getActiveScope(_scope) { + while(true) { + var scope = _scope; + if (!scope.a) { + return scope; + } + _scope = scope.p; + continue ; + }; +} + function $$var$1(b, val) { var _var = val.v; if (_var !== undefined) { return _var; } var $$var$2 = varWithoutAllocation(b); + var activeScope = getActiveScope(val.x); + var isVarScopeActive = val.x === activeScope; var i = val.i; - var allocation = i !== undefined ? $$var$2 + "=" + i : $$var$2; - var varsAllocation = val.x.l; - val.x.l = varsAllocation === "" ? allocation : varsAllocation + "," + allocation; + var allocation = i !== undefined && isVarScopeActive ? $$var$2 + "=" + i : $$var$2; + var varsAllocation = activeScope.l; + activeScope.l = varsAllocation === "" ? allocation : varsAllocation + "," + allocation; + var i$1 = val.i; + if (i$1 !== undefined && !isVarScopeActive) { + b.c = b.c + ($$var$2 + "=" + i$1 + ";"); + } val.v = $$var$2; return $$var$2; } @@ -206,35 +240,36 @@ function set(b, val, code) { } function transform(b, input, isAsync, operation) { - if (b.a === true) { - var prevCode = b.c; - b.c = ""; - var inputVar = varWithoutAllocation(b); - var operationOutputVal = operation(b, inputVar); - var outputVar = $$var(b); - b.c = prevCode + (outputVar + "=()=>" + input + "().then(" + inputVar + "=>{" + b.c + "return " + inline(b, operationOutputVal) + ( - isAsync ? "()" : "" - ) + "});"); - return outputVar; - } - if (!isAsync) { - return inline(b, operation(b, input)); - } - b.a = true; - var outputVar$1 = $$var(b); - b.c = b.c + (outputVar$1 + "=" + inline(b, operation(b, input)) + ";"); - return outputVar$1; + if (b.a !== true) { + if (isAsync) { + b.a = true; + return asyncVal(b, inline(b, operation(b, input))); + } else { + return operation(b, input); + } + } + var prevCode = b.c; + b.c = ""; + var operationInput = (function (__x) { + return val(b, __x); + })(varWithoutAllocation(b)); + var operationOutputVal = operation(b, operationInput); + var operationCode = b.c; + b.c = prevCode; + return asyncVal(b, "()=>" + $$var$1(b, input) + "().then(" + $$var$1(b, operationInput) + "=>{" + operationCode + "return " + inline(b, operationOutputVal) + ( + isAsync ? "()" : "" + ) + "})"); } function embedSyncOperation(b, input, fn) { return transform(b, input, false, (function (b, input) { - return val(b, "e[" + (b.e.push(fn) - 1) + "](" + input + ")"); + return val(b, "e[" + (b.e.push(fn) - 1) + "](" + inline(b, input) + ")"); })); } function embedAsyncOperation(b, input, fn) { return transform(b, input, true, (function (b, input) { - return val(b, "e[" + (b.e.push(fn) - 1) + "](" + input + ")"); + return val(b, "e[" + (b.e.push(fn) - 1) + "](" + inline(b, input) + ")"); })); } @@ -268,15 +303,14 @@ function withCatch(b, $$catch, fn) { var maybeResolveVar = $$catch(b, errorVar); var catchCode = "if(" + (errorVar + "&&" + errorVar + ".s===s") + "){" + b.c; b.c = ""; - var fnOutput = fn(b); + var fnOutput = valScope(b, fn); var isAsync = b.a; - var isInlined = !b.s.has(fnOutput); - var outputVar = isAsync || isInlined ? $$var(b) : fnOutput; + var outputVal = allocateVal(b); var catchCode$1 = maybeResolveVar !== undefined ? (function (catchLocation) { return catchCode + ( catchLocation === 1 ? "return Promise.resolve(" + maybeResolveVar + ")" : ( catchLocation === 2 ? "return " + maybeResolveVar : ( - isAsync ? outputVar + "=()=>Promise.resolve(" + maybeResolveVar + ")" : outputVar + "=" + maybeResolveVar + isAsync ? set(b, outputVal, "()=>Promise.resolve(" + maybeResolveVar + ")") : set(b, outputVal, maybeResolveVar) ) ) ) + ("}else{throw " + errorVar + "}"); @@ -284,11 +318,9 @@ function withCatch(b, $$catch, fn) { return catchCode + "}throw " + errorVar; }); b.c = prevCode + ("try{" + b.c + ( - isAsync ? outputVar + "=()=>{try{return " + fnOutput + "().catch(" + errorVar + "=>{" + catchCode$1(2) + "})}catch(" + errorVar + "){" + catchCode$1(1) + "}};" : ( - isInlined ? outputVar + "=" + fnOutput : "" - ) + isAsync ? set(b, outputVal, "()=>{try{return " + $$var$1(b, fnOutput) + "().catch(" + errorVar + "=>{" + catchCode$1(2) + "})}catch(" + errorVar + "){" + catchCode$1(1) + "}}") : set(b, outputVal, inline(b, fnOutput)) ) + "}catch(" + errorVar + "){" + catchCode$1(0) + "}"); - return outputVar; + return outputVal; } function withPathPrepend(b, path, maybeDynamicLocationVar, fn) { @@ -368,12 +400,13 @@ function noopOperation(i) { function build(builder, schema, operation) { var scope = { - l: "" + l: "", + a: false, + p: (void 0) }; var input = { v: "i", - x: scope, - a: false + x: scope }; var b = { a: false, @@ -1032,10 +1065,12 @@ function recursive(fn) { Object.assign(placeholder, schema); var builder = placeholder.p; placeholder.p = (function (b, selfSchema, path) { - var input = inline(b, b.i); + var input = b.i; selfSchema.p = noop; var scope = { - l: "" + l: "", + a: false, + p: (void 0) }; var ctx = { a: false, @@ -1046,20 +1081,23 @@ function recursive(fn) { x: scope, i: { v: "i", - x: scope, - a: false + x: scope }, e: [] }; builder(ctx, selfSchema, path); var isAsync = ctx.a; selfSchema.p = (function (b, selfSchema, param) { - var input = inline(b, b.i); - return val(b, isAsync ? embedAsyncOperation(b, input, (function (input) { - return internalParseAsyncWith(input, selfSchema); - })) : embedSyncOperation(b, input, (function (input) { - return parseAnyOrRaiseWith(input, selfSchema); - }))); + var input = b.i; + if (isAsync) { + return embedAsyncOperation(b, input, (function (input) { + return internalParseAsyncWith(input, selfSchema); + })); + } else { + return embedSyncOperation(b, input, (function (input) { + return parseAnyOrRaiseWith(input, selfSchema); + })); + } }); var operation = build(builder, selfSchema, "Parsing"); if (isAsync) { @@ -1068,29 +1106,29 @@ function recursive(fn) { selfSchema["op"] = operation; } selfSchema.p = builder; - return val(b, withPathPrepend(b, path, undefined, (function (b, param) { - if (isAsync) { - return embedAsyncOperation(b, input, operation); - } else { - return embedSyncOperation(b, input, operation); - } - }))); + return withPathPrepend(b, path, undefined, (function (b, param) { + if (isAsync) { + return embedAsyncOperation(b, input, operation); + } else { + return embedSyncOperation(b, input, operation); + } + })); }); var builder$1 = placeholder.s; placeholder.s = (function (b, selfSchema, path) { - var input = inline(b, b.i); + var input = b.i; selfSchema.s = (function (b, selfSchema, param) { - var input = inline(b, b.i); - return val(b, embedSyncOperation(b, input, (function (input) { - return serializeToUnknownOrRaiseWith(input, selfSchema); - }))); + var input = b.i; + return embedSyncOperation(b, input, (function (input) { + return serializeToUnknownOrRaiseWith(input, selfSchema); + })); }); var operation = build(builder$1, selfSchema, "Serializing"); selfSchema["os"] = operation; selfSchema.s = builder$1; - return val(b, withPathPrepend(b, path, undefined, (function (b, param) { - return embedSyncOperation(b, input, operation); - }))); + return withPathPrepend(b, path, undefined, (function (b, param) { + return embedSyncOperation(b, input, operation); + })); }); return placeholder; } @@ -1124,23 +1162,18 @@ function internalRefine(schema, refiner) { n: schema.n, p: (function (b, selfSchema, path) { var input = b.i; - return val(b, transform(b, (function (__x) { - return inline(b, __x); - })(use(b, schema, input, path)), false, (function (b, input) { - var input$1 = val(b, input); - b.c = b.c + refiner(b, input$1, selfSchema, path); - return input$1; - }))); + return transform(b, use(b, schema, input, path), false, (function (b, input) { + var rCode = refiner(b, input, selfSchema, path); + b.c = b.c + rCode; + return input; + })); }), s: (function (b, selfSchema, path) { - var input = inline(b, b.i); - return use(b, schema, (function (__x) { - return val(b, __x); - })(transform(b, input, false, (function (b, input) { - var input$1 = val(b, input); - b.c = b.c + refiner(b, input$1, selfSchema, path); - return input$1; - }))), path); + var input = b.i; + return use(b, schema, transform(b, input, false, (function (b, input) { + b.c = b.c + refiner(b, input, selfSchema, path); + return input; + })), path); }), f: schema.f, i: 0, @@ -1166,33 +1199,34 @@ function transform$1(schema, transformer) { n: schema.n, p: (function (b, selfSchema, path) { var input = b.i; - var input$1 = (function (__x) { - return inline(b, __x); - })(use(b, schema, input, path)); + var input$1 = use(b, schema, input, path); var match = transformer(make(selfSchema, path, b.o)); var parser = match.p; - var tmp; if (parser !== undefined) { - tmp = match.a !== undefined ? invalidOperation(b, path, "The S.transform doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser.") : embedSyncOperation(b, input$1, parser); + if (match.a !== undefined) { + return invalidOperation(b, path, "The S.transform doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser."); + } else { + return embedSyncOperation(b, input$1, parser); + } + } + var asyncParser = match.a; + if (asyncParser !== undefined) { + return embedAsyncOperation(b, input$1, asyncParser); + } else if (match.s !== undefined) { + return invalidOperation(b, path, "The S.transform parser is missing"); } else { - var asyncParser = match.a; - tmp = asyncParser !== undefined ? embedAsyncOperation(b, input$1, asyncParser) : ( - match.s !== undefined ? invalidOperation(b, path, "The S.transform parser is missing") : input$1 - ); + return input$1; } - return val(b, tmp); }), s: (function (b, selfSchema, path) { var match = transformer(make(selfSchema, path, b.o)); var serializer = match.s; var tmp; if (serializer !== undefined) { - var input = inline(b, b.i); + var input = b.i; tmp = (function (__x) { return inline(b, __x); - })(use(b, schema, (function (__x) { - return val(b, __x); - })(embedSyncOperation(b, input, serializer)), path)); + })(use(b, schema, embedSyncOperation(b, input, serializer), path)); } else if (match.a !== undefined || match.p !== undefined) { tmp = invalidOperation(b, path, "The S.transform serializer is missing"); } else { @@ -1231,7 +1265,7 @@ function preprocess(schema, transformer) { t: schema.t, n: schema.n, p: (function (b, selfSchema, path) { - var input = inline(b, b.i); + var input = b.i; var match = transformer(make(selfSchema, path, b.o)); var parser = match.p; var tmp; @@ -1240,7 +1274,9 @@ function preprocess(schema, transformer) { tmp = invalidOperation(b, path, "The S.preprocess doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser."); } else { var operationResultVar = $$var(b); - b.c = b.c + (operationResultVar + "=" + embedSyncOperation(b, input, parser) + ";"); + b.c = b.c + (operationResultVar + "=" + (function (__x) { + return inline(b, __x); + })(embedSyncOperation(b, input, parser)) + ";"); tmp = (function (__x) { return inline(b, __x); })(useWithTypeFilter(b, schema, (function (__x) { @@ -1250,7 +1286,9 @@ function preprocess(schema, transformer) { } else { var asyncParser = match.a; if (asyncParser !== undefined) { - var parseResultVar = embedAsyncOperation(b, input, asyncParser); + var parseResultVar = (function (__x) { + return $$var$1(b, __x); + })(embedAsyncOperation(b, input, asyncParser)); var outputVar = $$var(b); var asyncResultVar = varWithoutAllocation(b); b.c = b.c + (outputVar + "=()=>" + parseResultVar + "().then(" + asyncResultVar + "=>{" + scope(b, (function (b) { @@ -1268,21 +1306,21 @@ function preprocess(schema, transformer) { } else { tmp = (function (__x) { return inline(b, __x); - })(useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(input), path)); + })(useWithTypeFilter(b, schema, input, path)); } } return val(b, tmp); }), s: (function (b, selfSchema, path) { var input = b.i; - var input$1 = (function (__x) { - return inline(b, __x); - })(use(b, schema, input, path)); + var input$1 = use(b, schema, input, path); var match = transformer(make(selfSchema, path, b.o)); var serializer = match.s; - return val(b, serializer !== undefined ? embedSyncOperation(b, input$1, serializer) : input$1); + if (serializer !== undefined) { + return embedSyncOperation(b, input$1, serializer); + } else { + return input$1; + } }), f: undefined, i: 0, @@ -1297,27 +1335,36 @@ function custom(name, definer) { return name; }), p: (function (b, selfSchema, path) { - var input = inline(b, b.i); + var input = b.i; var match = definer(make(selfSchema, path, b.o)); var parser = match.p; - var tmp; if (parser !== undefined) { - tmp = match.a !== undefined ? invalidOperation(b, path, "The S.custom doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser.") : embedSyncOperation(b, input, parser); + if (match.a !== undefined) { + return invalidOperation(b, path, "The S.custom doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser."); + } else { + return embedSyncOperation(b, input, parser); + } + } + var asyncParser = match.a; + if (asyncParser !== undefined) { + return embedAsyncOperation(b, input, asyncParser); + } else if (match.s !== undefined) { + return invalidOperation(b, path, "The S.custom parser is missing"); } else { - var asyncParser = match.a; - tmp = asyncParser !== undefined ? embedAsyncOperation(b, input, asyncParser) : ( - match.s !== undefined ? invalidOperation(b, path, "The S.custom parser is missing") : input - ); + return input; } - return val(b, tmp); }), s: (function (b, selfSchema, path) { - var input = inline(b, b.i); + var input = b.i; var match = definer(make(selfSchema, path, b.o)); var serializer = match.s; - return val(b, serializer !== undefined ? embedSyncOperation(b, input, serializer) : ( - match.a !== undefined || match.p !== undefined ? invalidOperation(b, path, "The S.custom serializer is missing") : input - )); + if (serializer !== undefined) { + return embedSyncOperation(b, input, serializer); + } else if (match.a !== undefined || match.p !== undefined) { + return invalidOperation(b, path, "The S.custom serializer is missing"); + } else { + return input; + } }), f: undefined, i: 0, @@ -1372,9 +1419,7 @@ function factory(schema, definer) { n: schema.n, p: (function (b, param, path) { var input = b.i; - return val(b, embedSyncOperation(b, (function (__x) { - return inline(b, __x); - })(use(b, schema, input, path)), definer)); + return embedSyncOperation(b, use(b, schema, input, path), definer); }), s: (function (b, selfSchema, path) { var inputVar = $$var$1(b, b.i); @@ -1524,13 +1569,12 @@ function getWithDefault(schema, $$default) { n: schema.n, p: (function (b, param, path) { var input = b.i; - return val(b, transform(b, (function (__x) { - return inline(b, __x); - })(use(b, schema, input, path)), false, (function (b, input) { - var tmp; - tmp = $$default.TAG === "Value" ? "e[" + (b.e.push($$default._0) - 1) + "]" : "e[" + (b.e.push($$default._0) - 1) + "]()"; - return val(b, input + "===void 0?" + tmp + ":" + input); - }))); + return transform(b, use(b, schema, input, path), false, (function (b, input) { + var inputVar = $$var$1(b, input); + var tmp; + tmp = $$default.TAG === "Value" ? "e[" + (b.e.push($$default._0) - 1) + "]" : "e[" + (b.e.push($$default._0) - 1) + "]()"; + return val(b, inputVar + "===void 0?" + tmp + ":" + inputVar); + })); }), s: schema.s, f: schema.f, @@ -1585,95 +1629,83 @@ function makeParseOperationBuilder(itemDefinitions, itemDefinitionsSet, definiti if (inputRefinement !== undefined) { inputRefinement(b, selfSchema, path); } - var fn = function (b) { - var inputVar = $$var$1(b, b.i); - var registeredDefinitions = new Set(); - var asyncOutputVars = []; - var prevCode = b.c; - b.c = ""; - unknownKeysRefinement(b, selfSchema, inputVar, path); - var unknownKeysRefinementCode = b.c; - b.c = ""; - var definitionToOutput = function (definition, outputPath) { - var kind = toKindWithSet(definition, itemDefinitionsSet); - switch (kind) { - case 0 : - var isArray = Array.isArray(definition); - var keys = Object.keys(definition); - var codeRef = isArray ? "[" : "{"; - for(var idx = 0 ,idx_finish = keys.length; idx < idx_finish; ++idx){ - var key = keys[idx]; - var definition$1 = definition[key]; - var output = definitionToOutput(definition$1, outputPath + ("[" + JSON.stringify(key) + "]")); - codeRef = codeRef + ( - isArray ? output : JSON.stringify(key) + ":" + output - ) + ","; - } - return codeRef + ( - isArray ? "]" : "}" - ); - case 1 : - return "e[" + (b.e.push(definition) - 1) + "]"; - case 2 : - registeredDefinitions.add(definition); - var inputPath = definition.p; - var schema = definition.s; - var fieldOuputVar = (function (__x) { - return inline(b, __x); - })(useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(inputVar + inputPath), path + inputPath)); - var isAsyncField = schema.i; - if (isAsyncField) { - asyncOutputVars.push(fieldOuputVar); - } - return fieldOuputVar; - - } - }; - var syncOutput = definitionToOutput(definition, ""); - var registeredFieldsCode = b.c; - b.c = ""; - for(var idx = 0 ,idx_finish = itemDefinitions.length; idx < idx_finish; ++idx){ - var itemDefinition = itemDefinitions[idx]; - if (!registeredDefinitions.has(itemDefinition)) { - var inputPath = itemDefinition.p; - var schema = itemDefinition.s; - var fieldOuputVar = (function (__x) { - return inline(b, __x); - })(useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(inputVar + inputPath), path + inputPath)); - var isAsyncField = schema.i; - if (isAsyncField) { - asyncOutputVars.push(fieldOuputVar); - } - - } - - } - var unregisteredFieldsCode = b.c; - b.c = prevCode + unregisteredFieldsCode + registeredFieldsCode + unknownKeysRefinementCode; - if (asyncOutputVars.length === 0) { - return val(b, syncOutput); - } else { - return asyncVal(b, "Promise.all([" + asyncOutputVars.map(function (asyncOutputVar) { - return asyncOutputVar + "()"; - }).join(",") + "]).then(([" + asyncOutputVars.toString() + "])=>(" + syncOutput + "))"); - } - }; - var prevScope = b.x; - var prevCode = b.c; - b.x = { - l: "" - }; - b.c = ""; - var val$1 = fn(b); - var varsAllocation = b.x.l; - var code = varsAllocation === "" ? b.c : "let " + varsAllocation + ";" + b.c; - b.x = prevScope; - b.c = prevCode + code; - return val$1; + var registeredDefinitions = new Set(); + var asyncOutputVars = []; + return valScope(b, (function (b) { + var inputVar = $$var$1(b, b.i); + var prevCode = b.c; + b.c = ""; + unknownKeysRefinement(b, selfSchema, inputVar, path); + var unknownKeysRefinementCode = b.c; + b.c = ""; + var definitionToOutput = function (definition, outputPath) { + var kind = toKindWithSet(definition, itemDefinitionsSet); + switch (kind) { + case 0 : + var isArray = Array.isArray(definition); + var keys = Object.keys(definition); + var codeRef = isArray ? "[" : "{"; + for(var idx = 0 ,idx_finish = keys.length; idx < idx_finish; ++idx){ + var key = keys[idx]; + var definition$1 = definition[key]; + var output = definitionToOutput(definition$1, outputPath + ("[" + JSON.stringify(key) + "]")); + codeRef = codeRef + ( + isArray ? output : JSON.stringify(key) + ":" + output + ) + ","; + } + return codeRef + ( + isArray ? "]" : "}" + ); + case 1 : + return "e[" + (b.e.push(definition) - 1) + "]"; + case 2 : + registeredDefinitions.add(definition); + var inputPath = definition.p; + var schema = definition.s; + var fieldOuputVar = (function (__x) { + return inline(b, __x); + })(useWithTypeFilter(b, schema, (function (__x) { + return val(b, __x); + })(inputVar + inputPath), path + inputPath)); + var isAsyncField = schema.i; + if (isAsyncField) { + asyncOutputVars.push(fieldOuputVar); + } + return fieldOuputVar; + + } + }; + var syncOutput = definitionToOutput(definition, ""); + var registeredFieldsCode = b.c; + b.c = ""; + for(var idx = 0 ,idx_finish = itemDefinitions.length; idx < idx_finish; ++idx){ + var itemDefinition = itemDefinitions[idx]; + if (!registeredDefinitions.has(itemDefinition)) { + var inputPath = itemDefinition.p; + var schema = itemDefinition.s; + var fieldOuputVar = (function (__x) { + return inline(b, __x); + })(useWithTypeFilter(b, schema, (function (__x) { + return val(b, __x); + })(inputVar + inputPath), path + inputPath)); + var isAsyncField = schema.i; + if (isAsyncField) { + asyncOutputVars.push(fieldOuputVar); + } + + } + + } + var unregisteredFieldsCode = b.c; + b.c = prevCode + unregisteredFieldsCode + registeredFieldsCode + unknownKeysRefinementCode; + if (asyncOutputVars.length === 0) { + return val(b, syncOutput); + } else { + return asyncVal(b, "()=>Promise.all([" + asyncOutputVars.map(function (asyncOutputVar) { + return asyncOutputVar + "()"; + }).join(",") + "]).then(([" + asyncOutputVars.toString() + "])=>(" + syncOutput + "))"); + } + })); }; } @@ -2080,17 +2112,17 @@ function factory$4(schema, spaceOpt) { t: "String", n: primitiveName, p: (function (b, param, path) { - var input = inline(b, b.i); - var jsonVar = $$var(b); - b.c = b.c + ("try{" + jsonVar + "=JSON.parse(" + input + ")}catch(t){" + raiseWithArg(b, path, (function (message) { + var input = b.i; + var jsonVal = allocateVal(b); + b.c = b.c + ("try{" + set(b, jsonVal, "JSON.parse(" + inline(b, input) + ")") + "}catch(t){" + raiseWithArg(b, path, (function (message) { return { TAG: "OperationFailed", _0: message }; }), "t.message") + "}"); - return useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(jsonVar), path); + return valScope(b, (function (b) { + return useWithTypeFilter(b, schema, jsonVal, path); + })); }), s: (function (b, param, path) { var input = b.i; @@ -2257,17 +2289,16 @@ function factory$5(schema) { var iteratorVar = varWithoutAllocation(b); var outputVal = val(b, "[]"); b.c = b.c + ("for(let " + iteratorVar + "=0;" + iteratorVar + "<" + inputVar + ".length;++" + iteratorVar + "){" + scope(b, (function (b) { - var itemOutputVar = withPathPrepend(b, path, iteratorVar, (function (b, path) { - var __x = useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(inputVar + "[" + iteratorVar + "]"), path); - return inline(b, __x); + var itemOutputVal = withPathPrepend(b, path, iteratorVar, (function (b, path) { + return useWithTypeFilter(b, schema, (function (__x) { + return val(b, __x); + })(inputVar + "[" + iteratorVar + "]"), path); })); - return push(b, outputVal, itemOutputVar); + return push(b, outputVal, inline(b, itemOutputVal)); })) + "}"); var isAsync = schema.i; if (isAsync) { - return asyncVal(b, "Promise.all(" + $$var$1(b, outputVal) + ".map(t=>t()))"); + return asyncVal(b, "()=>Promise.all(" + $$var$1(b, outputVal) + ".map(t=>t()))"); } else { return outputVal; } @@ -2280,12 +2311,13 @@ function factory$5(schema) { var iteratorVar = varWithoutAllocation(b); var outputVal = val(b, "[]"); b.c = b.c + ("for(let " + iteratorVar + "=0;" + iteratorVar + "<" + inputVar + ".length;++" + iteratorVar + "){" + scope(b, (function (b) { - var itemOutputVar = withPathPrepend(b, path, iteratorVar, (function (b, path) { - var __x = use(b, schema, (function (__x) { - return val(b, __x); - })(inputVar + "[" + iteratorVar + "]"), path); - return inline(b, __x); - })); + var itemOutputVar = (function (__x) { + return $$var$1(b, __x); + })(withPathPrepend(b, path, iteratorVar, (function (b, path) { + return use(b, schema, (function (__x) { + return val(b, __x); + })(inputVar + "[" + iteratorVar + "]"), path); + }))); return push(b, outputVal, itemOutputVar); })) + "}"); return outputVal; @@ -2347,12 +2379,13 @@ function factory$6(schema) { var keyVar = varWithoutAllocation(b); var outputVar = $$var(b); b.c = b.c + (outputVar + "={};for(let " + keyVar + " in " + inputVar + "){" + scope(b, (function (b) { - var itemOutputVar = withPathPrepend(b, path, keyVar, (function (b, path) { - var __x = useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(inputVar + "[" + keyVar + "]"), path); - return inline(b, __x); - })); + var itemOutputVar = (function (__x) { + return $$var$1(b, __x); + })(withPathPrepend(b, path, keyVar, (function (b, path) { + return useWithTypeFilter(b, schema, (function (__x) { + return val(b, __x); + })(inputVar + "[" + keyVar + "]"), path); + }))); return outputVar + "[" + keyVar + "]=" + itemOutputVar; })) + "}"); var isAsync = schema.i; @@ -2379,12 +2412,13 @@ function factory$6(schema) { var keyVar = varWithoutAllocation(b); var outputVar = $$var(b); b.c = b.c + (outputVar + "={};for(let " + keyVar + " in " + inputVar + "){" + scope(b, (function (b) { - var itemOutputVar = withPathPrepend(b, path, keyVar, (function (b, path) { - var __x = use(b, schema, (function (__x) { - return val(b, __x); - })(inputVar + "[" + keyVar + "]"), path); - return inline(b, __x); - })); + var itemOutputVar = (function (__x) { + return $$var$1(b, __x); + })(withPathPrepend(b, path, keyVar, (function (b, path) { + return use(b, schema, (function (__x) { + return val(b, __x); + })(inputVar + "[" + keyVar + "]"), path); + }))); return outputVar + "[" + keyVar + "]=" + itemOutputVar; })) + "}"); tmp = outputVar; @@ -2730,27 +2764,26 @@ function $$catch(schema, getFallbackValue) { n: schema.n, p: (function (b, selfSchema, path) { var inputVar = $$var$1(b, b.i); - return val(b, withCatch(b, (function (b, errorVar) { - return "e[" + (b.e.push(function (input, internalError) { - return getFallbackValue({ - e: internalError, - i: input, - s: selfSchema, - f: (function (message, customPathOpt) { - var customPath = customPathOpt !== undefined ? customPathOpt : ""; - throw new RescriptSchemaError({ - TAG: "OperationFailed", - _0: message - }, b.o, path + customPath); - }) - }); - }) - 1) + "](" + inputVar + "," + errorVar + ")"; - }), (function (b) { - var __x = useWithTypeFilter(b, schema, (function (__x) { - return val(b, __x); - })(inputVar), path); - return inline(b, __x); - }))); + return withCatch(b, (function (b, errorVar) { + return "e[" + (b.e.push(function (input, internalError) { + return getFallbackValue({ + e: internalError, + i: input, + s: selfSchema, + f: (function (message, customPathOpt) { + var customPath = customPathOpt !== undefined ? customPathOpt : ""; + throw new RescriptSchemaError({ + TAG: "OperationFailed", + _0: message + }, b.o, path + customPath); + }) + }); + }) - 1) + "](" + inputVar + "," + errorVar + ")"; + }), (function (b) { + return useWithTypeFilter(b, schema, (function (__x) { + return val(b, __x); + })(inputVar), path); + })); }), s: schema.s, f: undefined, diff --git a/src/S_Core.res b/src/S_Core.res index 932b8550..ea4aa3a7 100644 --- a/src/S_Core.res +++ b/src/S_Core.res @@ -270,16 +270,18 @@ and builder and builderScope = { @as("l") mutable _varsAllocation: string, + @as("a") + mutable _isAllocated: bool, + @as("p") + _parent: builderScope, } and val = { @as("v") mutable _var?: string, @as("i") - mutable _initial?: string, + _initial?: string, @as("x") _varScope: builderScope, - @as("a") - _isAsync: bool, } and b = { @as("a") @@ -409,31 +411,37 @@ module Builder = { } let scope = (b: b, fn) => { - let prevScope = b._scope let prevCode = b.code - b._scope = { + let newScope = { _varsAllocation: "", + _isAllocated: false, + _parent: b._scope, } + b._scope = newScope b.code = "" let resultCode = fn(b) - let varsAllocation = b._scope._varsAllocation + let varsAllocation = newScope._varsAllocation let code = varsAllocation === "" ? b.code : `let ${varsAllocation};${b.code}` - b._scope = prevScope + newScope._isAllocated = true + b._scope = newScope._parent b.code = prevCode code ++ resultCode } let valScope = (b: b, fn) => { - let prevScope = b._scope let prevCode = b.code - b._scope = { + let newScope = { _varsAllocation: "", + _isAllocated: false, + _parent: b._scope, } + b._scope = newScope b.code = "" let val = fn(b) - let varsAllocation = b._scope._varsAllocation + let varsAllocation = newScope._varsAllocation let code = varsAllocation === "" ? b.code : `let ${varsAllocation};${b.code}` - b._scope = prevScope + newScope._isAllocated = true + b._scope = newScope._parent b.code = prevCode ++ code val } @@ -454,36 +462,46 @@ module Builder = { } let allocateVal = (b: b): val => { - {_varScope: b._scope, _isAsync: false} + {_varScope: b._scope} } let val = (b: b, initial: string): val => { // TODO: Get rid of _vars if b._vars->Stdlib.Set.has(initial) { - {_var: initial, _varScope: b._scope, _isAsync: false} + {_var: initial, _varScope: b._scope} } else { - {_initial: initial, _varScope: b._scope, _isAsync: false} + {_initial: initial, _varScope: b._scope} } } let asyncVal = (b: b, initial: string): val => { let var = b->varWithoutAllocation - let allocation = `${var}=()=>${initial}` + let allocation = `${var}=${initial}` let varsAllocation = b._scope._varsAllocation b._scope._varsAllocation = varsAllocation === "" ? allocation : varsAllocation ++ "," ++ allocation // TODO: Don't require for it to be a var. // FIXME: isAsync is currently not used - {_var: var, _varScope: b._scope, _isAsync: true} + {_var: var, _varScope: b._scope} } module Val = { - let inline = (b: b, val: val) => { + let inline = (_b: b, val: val) => { switch val { - | {_var: ?Some(var)} => var - | {_initial: ?Some(initial)} => initial - | _ => b->var + | {_var: var} => var + | {_initial: initial} => initial + | _ => + // TODO: This branch should be invalid + Js.Exn.raiseError("Can't inline undefined val") + } + } + + let rec getActiveScope = (scope: builderScope) => { + if scope._isAllocated { + getActiveScope(scope._parent) + } else { + scope } } @@ -492,14 +510,20 @@ module Builder = { | {_var} => _var | _ => { let var = b->varWithoutAllocation + let activeScope = getActiveScope(val._varScope) + let isVarScopeActive = val._varScope === activeScope let allocation = switch val._initial { - | Some(i) => `${var}=${i}` - | None => var + | Some(i) if isVarScopeActive => `${var}=${i}` + | _ => var } - let varsAllocation = val._varScope._varsAllocation - val._varScope._varsAllocation = varsAllocation === "" + let varsAllocation = activeScope._varsAllocation + activeScope._varsAllocation = varsAllocation === "" ? allocation : varsAllocation ++ "," ++ allocation + switch val._initial { + | Some(i) if !isVarScopeActive => b.code = b.code ++ `${var}=${i};` + | _ => () + } val._var = Some(var) var } @@ -541,35 +565,35 @@ module Builder = { if b.isAsyncBranch === true { let prevCode = b.code b.code = "" - let inputVar = b->varWithoutAllocation - let operationOutputVal = operation(b, ~input=inputVar) - let outputVar = b->var - b.code = - prevCode ++ - `${outputVar}=()=>${input}().then(${inputVar}=>{${b.code}return ${b->Val.inline( - operationOutputVal, - )}${isAsync ? "()" : ""}});` - outputVar + let operationInput = b->varWithoutAllocation->(val(b, _)) + let operationOutputVal = operation(b, ~input=operationInput) + let operationCode = b.code + b.code = prevCode + b->asyncVal( + `()=>${b->Val.var(input)}().then(${b->Val.var( + operationInput, + )}=>{${operationCode}return ${b->Val.inline(operationOutputVal)}${isAsync + ? "()" + : ""}})`, + ) } else if isAsync { b.isAsyncBranch = true // TODO: Would be nice to remove. Needed to enforce that async ops are always vars - let outputVar = b->var - b.code = b.code ++ `${outputVar}=${b->Val.inline(operation(b, ~input))};` - outputVar + b->asyncVal(b->Val.inline(operation(b, ~input))) } else { - b->Val.inline(operation(b, ~input)) + operation(b, ~input) } } let embedSyncOperation = (b: b, ~input, ~fn: 'input => 'output) => { b->transform(~input, ~isAsync=false, (b, ~input) => { - b->val(`${b->embed(fn)}(${input})`) + b->val(`${b->embed(fn)}(${b->Val.inline(input)})`) }) } let embedAsyncOperation = (b: b, ~input, ~fn: 'input => unit => promise<'output>) => { b->transform(~input, ~isAsync=true, (b, ~input) => { - b->val(`${b->embed(fn)}(${input})`) + b->val(`${b->embed(fn)}(${b->Val.inline(input)})`) }) } @@ -593,6 +617,7 @@ module Builder = { ) } + // FIXME: Refactor let withCatch = (b: b, ~catch, fn) => { let prevCode = b.code @@ -602,11 +627,10 @@ module Builder = { let catchCode = `if(${b->isInternalError(errorVar)}){${b.code}` b.code = "" - let fnOutput = fn(b) + let fnOutput = b->valScope(fn) let isAsync = b.isAsyncBranch - let isInlined = !(b._vars->Stdlib.Set.has(fnOutput)) - let outputVar = isAsync || isInlined ? b->var : fnOutput + let outputVal = b->allocateVal let catchCode = switch maybeResolveVar { | None => _ => `${catchCode}}throw ${errorVar}` @@ -614,8 +638,8 @@ module Builder = { catchLocation => catchCode ++ switch catchLocation { - | #0 if isAsync => `${outputVar}=()=>Promise.resolve(${resolveVar})` - | #0 => `${outputVar}=${resolveVar}` + | #0 if isAsync => b->Val.set(outputVal, `()=>Promise.resolve(${resolveVar})`) + | #0 => b->Val.set(outputVal, resolveVar) | #1 => `return Promise.resolve(${resolveVar})` | #2 => `return ${resolveVar}` } ++ @@ -625,17 +649,19 @@ module Builder = { b.code = prevCode ++ `try{${b.code}${{ - switch (isAsync, isInlined) { - | (true, _) => - `${outputVar}=()=>{try{return ${fnOutput}().catch(${errorVar}=>{${catchCode( - #2, - )}})}catch(${errorVar}){${catchCode(#1)}}};` - | (_, true) => `${outputVar}=${fnOutput}` - | _ => "" + switch isAsync { + | true => + b->Val.set( + outputVal, + `()=>{try{return ${b->Val.var(fnOutput)}().catch(${errorVar}=>{${catchCode( + #2, + )}})}catch(${errorVar}){${catchCode(#1)}}}`, + ) + | false => b->Val.set(outputVal, b->Val.inline(fnOutput)) } }}}catch(${errorVar}){${catchCode(#0)}}` - outputVar + outputVal } let withPathPrepend = (b: b, ~path, ~dynamicLocationVar as maybeDynamicLocationVar=?, fn) => { @@ -727,8 +753,10 @@ module Builder = { let build = (builder, ~schema, ~operation) => { let scope = { _varsAllocation: "", + _isAllocated: false, + _parent: %raw(`void 0`), } - let input = {_var: intitialInputVar, _varScope: scope, _isAsync: false} + let input = {_var: intitialInputVar, _varScope: scope} let b = { _embeded: [], _varCounter: -1, @@ -1380,16 +1408,18 @@ let recursive = fn => { { let builder = placeholder.parseOperationBuilder placeholder.parseOperationBuilder = Builder.make((b, ~selfSchema, ~path) => { - let input = b->B.useInput + let input = b->B.useInputVal let isAsync = { selfSchema.parseOperationBuilder = Builder.noop let scope = { _varsAllocation: "", + _isAllocated: false, + _parent: %raw(`void 0`), } let ctx = { _embeded: [], code: "", - _input: {_var: Builder.intitialInputVar, _varScope: scope, _isAsync: false}, + _input: {_var: Builder.intitialInputVar, _varScope: scope}, _scope: scope, _varCounter: -1, _vars: Stdlib.Set.fromArray([Builder.intitialInputVar]), @@ -1401,14 +1431,12 @@ let recursive = fn => { } selfSchema.parseOperationBuilder = Builder.make((b, ~selfSchema, ~path as _) => { - let input = b->B.useInput - b->B.val( - if isAsync { - b->B.embedAsyncOperation(~input, ~fn=input => input->internalParseAsyncWith(selfSchema)) - } else { - b->B.embedSyncOperation(~input, ~fn=input => input->parseAnyOrRaiseWith(selfSchema)) - }, - ) + let input = b->B.useInputVal + if isAsync { + b->B.embedAsyncOperation(~input, ~fn=input => input->internalParseAsyncWith(selfSchema)) + } else { + b->B.embedSyncOperation(~input, ~fn=input => input->parseAnyOrRaiseWith(selfSchema)) + } }) let operation = builder->Builder.build(~schema=selfSchema, ~operation=Parsing) @@ -1420,14 +1448,13 @@ let recursive = fn => { } selfSchema.parseOperationBuilder = builder - b->B.val( - b->B.withPathPrepend(~path, (b, ~path as _) => - if isAsync { - b->B.embedAsyncOperation(~input, ~fn=operation) - } else { - b->B.embedSyncOperation(~input, ~fn=operation) - } - ), + + b->B.withPathPrepend(~path, (b, ~path as _) => + if isAsync { + b->B.embedAsyncOperation(~input, ~fn=operation) + } else { + b->B.embedSyncOperation(~input, ~fn=operation) + } ) }) } @@ -1435,14 +1462,12 @@ let recursive = fn => { { let builder = placeholder.serializeOperationBuilder placeholder.serializeOperationBuilder = Builder.make((b, ~selfSchema, ~path) => { - let input = b->B.useInput + let input = b->B.useInputVal selfSchema.serializeOperationBuilder = Builder.make((b, ~selfSchema, ~path as _) => { - let input = b->B.useInput - b->B.val( - b->B.embedSyncOperation( - ~input, - ~fn=input => input->serializeToUnknownOrRaiseWith(selfSchema), - ), + let input = b->B.useInputVal + b->B.embedSyncOperation( + ~input, + ~fn=input => input->serializeToUnknownOrRaiseWith(selfSchema), ) }) @@ -1453,11 +1478,7 @@ let recursive = fn => { selfSchema->Obj.magic->Js.Dict.set((Operation.Serializer :> string), operation) selfSchema.serializeOperationBuilder = builder - b->B.val( - b->B.withPathPrepend(~path, (b, ~path as _) => - b->B.embedSyncOperation(~input, ~fn=operation) - ), - ) + b->B.withPathPrepend(~path, (b, ~path as _) => b->B.embedSyncOperation(~input, ~fn=operation)) }) } @@ -1491,31 +1512,21 @@ let internalRefine = (schema, refiner) => { ~tagged=schema.tagged, ~parseOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { let input = b->B.useInputVal - b->B.val( - b->B.transform( - ~input=b->B.use(~schema, ~input, ~path)->(B.Val.inline(b, _)), - ~isAsync=false, - (b, ~input) => { - let input = b->B.val(input) - b.code = b.code ++ refiner(b, ~input, ~selfSchema, ~path) - input - }, - ), - ) + b->B.transform(~input=b->B.use(~schema, ~input, ~path), ~isAsync=false, (b, ~input) => { + let rCode = refiner(b, ~input, ~selfSchema, ~path) + b.code = b.code ++ rCode + input + }) }), ~serializeOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { - let input = b->B.useInput - + let input = b->B.useInputVal b->B.use( ~schema, - ~input=b - ->B.transform(~input, ~isAsync=false, (b, ~input) => { - let input = b->B.val(input) + ~input=b->B.transform(~input, ~isAsync=false, (b, ~input) => { b.code = b.code ++ refiner(b, ~input, ~selfSchema, ~path) input - }) + }), // TODO: Remove all ->(B.val(b, _)) and clean up many B.val/B.var/B.inline in other places - ->(B.val(b, _)), ~path, ) }), @@ -1562,33 +1573,28 @@ let transform: (t<'input>, s<'output> => transformDefinition<'input, 'output>) = ~tagged=schema.tagged, ~parseOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { let input = b->B.useInputVal - let input = b->B.use(~schema, ~input, ~path)->(B.Val.inline(b, _)) - b->B.val( - switch transformer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { - | {parser, asyncParser: ?None} => b->B.embedSyncOperation(~input, ~fn=parser) - | {parser: ?None, asyncParser} => b->B.embedAsyncOperation(~input, ~fn=asyncParser) - | {parser: ?None, asyncParser: ?None, serializer: ?None} => input - | {parser: ?None, asyncParser: ?None, serializer: _} => - b->B.invalidOperation(~path, ~description=`The S.transform parser is missing`) - | {parser: _, asyncParser: _} => - b->B.invalidOperation( - ~path, - ~description=`The S.transform doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser.`, - ) - }, - ) + let input = b->B.use(~schema, ~input, ~path) + + switch transformer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { + | {parser, asyncParser: ?None} => b->B.embedSyncOperation(~input, ~fn=parser) + | {parser: ?None, asyncParser} => b->B.embedAsyncOperation(~input, ~fn=asyncParser) + | {parser: ?None, asyncParser: ?None, serializer: ?None} => input + | {parser: ?None, asyncParser: ?None, serializer: _} => + b->B.invalidOperation(~path, ~description=`The S.transform parser is missing`) + | {parser: _, asyncParser: _} => + b->B.invalidOperation( + ~path, + ~description=`The S.transform doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser.`, + ) + } }), ~serializeOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { b->B.val( switch transformer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { | {serializer} => - let input = b->B.useInput + let input = b->B.useInputVal b - ->B.use( - ~schema, - ~input=b->B.embedSyncOperation(~input, ~fn=serializer)->(B.val(b, _)), - ~path, - ) + ->B.use(~schema, ~input=b->B.embedSyncOperation(~input, ~fn=serializer), ~path) ->(B.Val.inline(b, _)) | {parser: ?None, asyncParser: ?None, serializer: ?None} => let input = b->B.useInputVal @@ -1633,19 +1639,23 @@ let rec preprocess = (schema, transformer) => { ~name=schema.name, ~tagged=schema.tagged, ~parseOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { - let input = b->B.useInput + let input = b->B.useInputVal b->B.val( switch transformer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { | {parser, asyncParser: ?None} => let operationResultVar = b->B.var b.code = - b.code ++ `${operationResultVar}=${b->B.embedSyncOperation(~input, ~fn=parser)};` + b.code ++ + `${operationResultVar}=${b + ->B.embedSyncOperation(~input, ~fn=parser) + ->(B.Val.inline(b, _))};` b ->B.useWithTypeFilter(~schema, ~input=operationResultVar->(B.val(b, _)), ~path) ->(B.Val.inline(b, _)) | {parser: ?None, asyncParser} => { - let parseResultVar = b->B.embedAsyncOperation(~input, ~fn=asyncParser) + let parseResultVar = + b->B.embedAsyncOperation(~input, ~fn=asyncParser)->(B.Val.var(b, _)) let outputVar = b->B.var let asyncResultVar = b->B.varWithoutAllocation @@ -1664,7 +1674,7 @@ let rec preprocess = (schema, transformer) => { } | {parser: ?None, asyncParser: ?None} => b - ->B.useWithTypeFilter(~schema, ~input=input->(B.val(b, _)), ~path) + ->B.useWithTypeFilter(~schema, ~input, ~path) ->(B.Val.inline(b, _)) | {parser: _, asyncParser: _} => b->B.invalidOperation( @@ -1676,15 +1686,13 @@ let rec preprocess = (schema, transformer) => { }), ~serializeOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { let input = b->B.useInputVal - let input = b->B.use(~schema, ~input, ~path)->(B.Val.inline(b, _)) + let input = b->B.use(~schema, ~input, ~path) - b->B.val( - switch transformer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { - | {serializer} => b->B.embedSyncOperation(~input, ~fn=serializer) - // TODO: Test that it doesn't return InvalidOperation when parser is passed but not serializer - | {serializer: ?None} => input - }, - ) + switch transformer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { + | {serializer} => b->B.embedSyncOperation(~input, ~fn=serializer) + // TODO: Test that it doesn't return InvalidOperation when parser is passed but not serializer + | {serializer: ?None} => input + } }), ~maybeTypeFilter=None, ~metadataMap=schema.metadataMap, @@ -1706,34 +1714,30 @@ let custom = (name, definer) => { ~metadataMap=Metadata.Map.empty, ~tagged=Unknown, ~parseOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { - let input = b->B.useInput + let input = b->B.useInputVal - b->B.val( - switch definer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { - | {parser, asyncParser: ?None} => b->B.embedSyncOperation(~input, ~fn=parser) - | {parser: ?None, asyncParser} => b->B.embedAsyncOperation(~input, ~fn=asyncParser) - | {parser: ?None, asyncParser: ?None, serializer: ?None} => input - | {parser: ?None, asyncParser: ?None, serializer: _} => - b->B.invalidOperation(~path, ~description=`The S.custom parser is missing`) - | {parser: _, asyncParser: _} => - b->B.invalidOperation( - ~path, - ~description=`The S.custom doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser.`, - ) - }, - ) + switch definer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { + | {parser, asyncParser: ?None} => b->B.embedSyncOperation(~input, ~fn=parser) + | {parser: ?None, asyncParser} => b->B.embedAsyncOperation(~input, ~fn=asyncParser) + | {parser: ?None, asyncParser: ?None, serializer: ?None} => input + | {parser: ?None, asyncParser: ?None, serializer: _} => + b->B.invalidOperation(~path, ~description=`The S.custom parser is missing`) + | {parser: _, asyncParser: _} => + b->B.invalidOperation( + ~path, + ~description=`The S.custom doesn't allow parser and asyncParser at the same time. Remove parser in favor of asyncParser.`, + ) + } }), ~serializeOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { - let input = b->B.useInput - b->B.val( - switch definer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { - | {serializer} => b->B.embedSyncOperation(~input, ~fn=serializer) - | {parser: ?None, asyncParser: ?None, serializer: ?None} => input - | {serializer: ?None, asyncParser: ?Some(_)} - | {serializer: ?None, parser: ?Some(_)} => - b->B.invalidOperation(~path, ~description=`The S.custom serializer is missing`) - }, - ) + let input = b->B.useInputVal + switch definer(EffectCtx.make(~selfSchema, ~path, ~operation=b.operation)) { + | {serializer} => b->B.embedSyncOperation(~input, ~fn=serializer) + | {parser: ?None, asyncParser: ?None, serializer: ?None} => input + | {serializer: ?None, asyncParser: ?Some(_)} + | {serializer: ?None, parser: ?Some(_)} => + b->B.invalidOperation(~path, ~description=`The S.custom serializer is missing`) + } }), ~maybeTypeFilter=None, ) @@ -1811,12 +1815,7 @@ module Variant = { ~tagged=schema.tagged, ~parseOperationBuilder=Builder.make((b, ~selfSchema as _, ~path) => { let input = b->B.useInputVal - b->B.val( - b->B.embedSyncOperation( - ~input=b->B.use(~schema, ~input, ~path)->(B.Val.inline(b, _)), - ~fn=definer, - ), - ) + b->B.embedSyncOperation(~input=b->B.use(~schema, ~input, ~path), ~fn=definer) }), ~serializeOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { let inputVar = b->B.useInputVar @@ -2006,21 +2005,15 @@ module Option = { ~tagged=schema.tagged, ~parseOperationBuilder=Builder.make((b, ~selfSchema as _, ~path) => { let input = b->B.useInputVal - b->B.val( - b->B.transform( - ~input=b->B.use(~schema, ~input, ~path)->(B.Val.inline(b, _)), - ~isAsync=false, - (b, ~input) => { - // TODO: Reassign input if it's not a var - b->B.val( - `${input}===void 0?${switch default { - | Value(v) => b->B.embed(v) - | Callback(cb) => `${b->B.embed(cb)}()` - }}:${input}`, - ) - }, - ), - ) + b->B.transform(~input=b->B.use(~schema, ~input, ~path), ~isAsync=false, (b, ~input) => { + let inputVar = b->B.Val.var(input) + b->B.val( + `${inputVar}===void 0?${switch default { + | Value(v) => b->B.embed(v) + | Callback(cb) => `${b->B.embed(cb)}()` + }}:${inputVar}`, + ) + }) }), ~serializeOperationBuilder=schema.serializeOperationBuilder, ~maybeTypeFilter=schema.maybeTypeFilter, @@ -2083,10 +2076,11 @@ module Object = { | None => () } + let registeredDefinitions = Stdlib.Set.empty() + let asyncOutputVars = [] + b->B.valScope(b => { let inputVar = b->B.useInputVar - let registeredDefinitions = Stdlib.Set.empty() - let asyncOutputVars = [] let prevCode = b.code b.code = "" unknownKeysRefinement(b, ~selfSchema, ~inputVar, ~path) @@ -2174,7 +2168,7 @@ module Object = { b->B.val(syncOutput) } else { b->B.asyncVal( - `Promise.all([${asyncOutputVars + `()=>Promise.all([${asyncOutputVars ->Js.Array2.map(asyncOutputVar => `${asyncOutputVar}()`) ->Js.Array2.joinWith( ",", @@ -2689,17 +2683,21 @@ module JsonString = { ~metadataMap=Metadata.Map.empty, ~tagged=String, ~parseOperationBuilder=Builder.make((b, ~selfSchema as _, ~path) => { - let input = b->B.useInput - let jsonVar = b->B.var + let input = b->B.useInputVal + let jsonVal = b->B.allocateVal + b.code = b.code ++ - `try{${jsonVar}=JSON.parse(${input})}catch(t){${b->B.raiseWithArg( + `try{${b->B.Val.set( + jsonVal, + `JSON.parse(${b->B.Val.inline(input)})`, + )}}catch(t){${b->B.raiseWithArg( ~path, message => OperationFailed(message), "t.message", )}}` - b->B.useWithTypeFilter(~schema, ~input=jsonVar->(B.val(b, _)), ~path) + b->B.valScope(b => b->B.useWithTypeFilter(~schema, ~input=jsonVal, ~path)) }), ~serializeOperationBuilder=Builder.make((b, ~selfSchema as _, ~path) => { let input = b->B.useInputVal @@ -2918,25 +2916,24 @@ module Array = { b.code ++ `for(let ${iteratorVar}=0;${iteratorVar}<${inputVar}.length;++${iteratorVar}){${b->B.scope( b => { - let itemOutputVar = b->B.withPathPrepend( - ~path, - ~dynamicLocationVar=iteratorVar, - (b, ~path) => - b - ->B.useWithTypeFilter( - ~schema, - ~input=`${inputVar}[${iteratorVar}]`->(B.val(b, _)), - ~path, - ) - ->(B.Val.inline(b, _)), - ) - b->B.Val.push(outputVal, itemOutputVar) + let itemOutputVal = + b->B.withPathPrepend( + ~path, + ~dynamicLocationVar=iteratorVar, + (b, ~path) => + b->B.useWithTypeFilter( + ~schema, + ~input=`${inputVar}[${iteratorVar}]`->(B.val(b, _)), + ~path, + ), + ) + b->B.Val.push(outputVal, b->B.Val.inline(itemOutputVal)) }, )}}` let isAsync = schema.isAsyncParse->(Obj.magic: isAsyncParse => bool) if isAsync { - b->B.asyncVal(`Promise.all(${b->B.Val.var(outputVal)}.map(t=>t()))`) + b->B.asyncVal(`()=>Promise.all(${b->B.Val.var(outputVal)}.map(t=>t()))`) } else { outputVal } @@ -2953,14 +2950,19 @@ module Array = { b.code ++ `for(let ${iteratorVar}=0;${iteratorVar}<${inputVar}.length;++${iteratorVar}){${b->B.scope( b => { - let itemOutputVar = b->B.withPathPrepend( - ~path, - ~dynamicLocationVar=iteratorVar, - (b, ~path) => - b - ->B.use(~schema, ~input=`${inputVar}[${iteratorVar}]`->(B.val(b, _)), ~path) - ->(B.Val.inline(b, _)), - ) + let itemOutputVar = + b + ->B.withPathPrepend( + ~path, + ~dynamicLocationVar=iteratorVar, + (b, ~path) => + b->B.use( + ~schema, + ~input=`${inputVar}[${iteratorVar}]`->(B.val(b, _)), + ~path, + ), + ) + ->(B.Val.var(b, _)) b->B.Val.push(outputVal, itemOutputVar) }, )}}` @@ -3039,18 +3041,19 @@ module Dict = { b.code = b.code ++ `${outputVar}={};for(let ${keyVar} in ${inputVar}){${b->B.scope(b => { - let itemOutputVar = b->B.withPathPrepend( - ~path, - ~dynamicLocationVar=keyVar, - (b, ~path) => - b - ->B.useWithTypeFilter( - ~schema, - ~input=`${inputVar}[${keyVar}]`->(B.val(b, _)), - ~path, - ) - ->(B.Val.inline(b, _)), - ) + let itemOutputVar = + b + ->B.withPathPrepend( + ~path, + ~dynamicLocationVar=keyVar, + (b, ~path) => + b->B.useWithTypeFilter( + ~schema, + ~input=`${inputVar}[${keyVar}]`->(B.val(b, _)), + ~path, + ), + ) + ->(B.Val.var(b, _)) `${outputVar}[${keyVar}]=${itemOutputVar}` })}}` @@ -3083,14 +3086,15 @@ module Dict = { b.code = b.code ++ `${outputVar}={};for(let ${keyVar} in ${inputVar}){${b->B.scope(b => { - let itemOutputVar = b->B.withPathPrepend( - ~path, - ~dynamicLocationVar=keyVar, - (b, ~path) => - b - ->B.use(~schema, ~input=`${inputVar}[${keyVar}]`->(B.val(b, _)), ~path) - ->(B.Val.inline(b, _)), - ) + let itemOutputVar = + b + ->B.withPathPrepend( + ~path, + ~dynamicLocationVar=keyVar, + (b, ~path) => + b->B.use(~schema, ~input=`${inputVar}[${keyVar}]`->(B.val(b, _)), ~path), + ) + ->(B.Val.var(b, _)) `${outputVar}[${keyVar}]=${itemOutputVar}` })}}` @@ -3552,30 +3556,27 @@ let catch = (schema, getFallbackValue) => { ~name=schema.name, ~parseOperationBuilder=Builder.make((b, ~selfSchema, ~path) => { let inputVar = b->B.useInputVar - b->B.val( - b->B.withCatch( - ~catch=(b, ~errorVar) => Some( - `${b->B.embed((input, internalError) => - getFallbackValue({ - Catch.input, - error: internalError, - schema: selfSchema->castUnknownSchemaToAnySchema, - fail: (message, ~path as customPath=Path.empty) => { - InternalError.raise( - ~path=path->Path.concat(customPath), - ~code=OperationFailed(message), - ~operation=b.operation, - ) - }, - }) - )}(${inputVar},${errorVar})`, - ), - b => { - b - ->B.useWithTypeFilter(~schema, ~input=inputVar->(B.val(b, _)), ~path) - ->(B.Val.inline(b, _)) - }, + + b->B.withCatch( + ~catch=(b, ~errorVar) => Some( + `${b->B.embed((input, internalError) => + getFallbackValue({ + Catch.input, + error: internalError, + schema: selfSchema->castUnknownSchemaToAnySchema, + fail: (message, ~path as customPath=Path.empty) => { + InternalError.raise( + ~path=path->Path.concat(customPath), + ~code=OperationFailed(message), + ~operation=b.operation, + ) + }, + }) + )}(${inputVar},${errorVar})`, ), + b => { + b->B.useWithTypeFilter(~schema, ~input=inputVar->(B.val(b, _)), ~path) + }, ) }), ~serializeOperationBuilder=schema.serializeOperationBuilder,