From f23580aa54eb117660cdd838de5f896aaa618821 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Tue, 1 Sep 2026 14:38:19 +0200 Subject: [PATCH 1/2] Add string literal regression coverage Signed-off-by: Christoph Knittel --- .../tests/src/DocumentSymbol.res | 1 + .../tests/src/expected/DocumentSymbol.res.txt | 12 +++ .../json_literal_todo_payload.res.expected | 13 +++ .../fixtures/json_literal_todo_payload.res | 3 + .../src/EscapedNames.gen.tsx | 2 +- .../src/EscapedNames.res | 4 +- .../src/ImportJsValue.gen.tsx | 20 +++- .../src/ImportJsValue.res | 10 +- .../src/ImportJsValue.res.js | 20 ++++ .../typescript-react-example/src/MyMath.ts | 4 + tests/ounit_tests/ounit_ast_mapper0_tests.ml | 23 +++++ .../expected/invalidSurrogatePair.res.txt | 53 +++++++++++ .../errors/scanner/invalidSurrogatePair.res | 6 ++ .../react/expected/fileLevelConfig.res.txt | 8 +- .../data/ppx/react/fileLevelConfig.res | 2 +- tests/tests/src/AsInUncurriedExternals.mjs | 3 + tests/tests/src/AsInUncurriedExternals.res | 5 + tests/tests/src/ImportAttributes.mjs | 8 +- tests/tests/src/ImportAttributes.res | 4 +- tests/tests/src/gpr_3142_test.mjs | 26 +++--- tests/tests/src/gpr_3142_test.res | 6 ++ tests/tests/src/inline_const.res | 2 + tests/tests/src/inline_const.resi | 2 + tests/tests/src/inline_const_test.mjs | 4 + tests/tests/src/inline_const_test.res | 5 +- .../src/semantic_string_constant_test.mjs | 10 ++ .../src/semantic_string_constant_test.res | 19 ++++ .../src/string_literal_normalization_test.mjs | 60 ++++++++++++ .../src/string_literal_normalization_test.res | 52 +++++++++++ tests/tests/src/switch_case_test.res | 4 +- tests/tests/src/tagged_template_test.mjs | 21 ++++- tests/tests/src/tagged_template_test.res | 23 ++++- tests/tests/src/test_string_switch.mjs | 92 +++++++++++++++++++ tests/tests/src/test_string_switch.res | 18 ++++ 34 files changed, 509 insertions(+), 36 deletions(-) create mode 100644 tests/build_tests/super_errors/expected/json_literal_todo_payload.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/json_literal_todo_payload.res create mode 100644 tests/syntax_tests/data/parsing/errors/scanner/expected/invalidSurrogatePair.res.txt create mode 100644 tests/syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res create mode 100644 tests/tests/src/semantic_string_constant_test.mjs create mode 100644 tests/tests/src/semantic_string_constant_test.res create mode 100644 tests/tests/src/string_literal_normalization_test.mjs create mode 100644 tests/tests/src/string_literal_normalization_test.res diff --git a/tests/analysis_tests/tests/src/DocumentSymbol.res b/tests/analysis_tests/tests/src/DocumentSymbol.res index 84dfeff0ce1..d0fe36cc07b 100644 --- a/tests/analysis_tests/tests/src/DocumentSymbol.res +++ b/tests/analysis_tests/tests/src/DocumentSymbol.res @@ -30,5 +30,6 @@ module O = { } let zzz = 11 +let templateString = `hello ${zzz->Int.toString}` //^doc diff --git a/tests/analysis_tests/tests/src/expected/DocumentSymbol.res.txt b/tests/analysis_tests/tests/src/expected/DocumentSymbol.res.txt index 73f0bf9244f..18d32d157e1 100644 --- a/tests/analysis_tests/tests/src/expected/DocumentSymbol.res.txt +++ b/tests/analysis_tests/tests/src/expected/DocumentSymbol.res.txt @@ -1,5 +1,17 @@ DocumentSymbol src/DocumentSymbol.res [ + { + "kind": 13, + "name": "templateString", + "range": { + "end": { "character": 49, "line": 32 }, + "start": { "character": 0, "line": 32 } + }, + "selectionRange": { + "end": { "character": 49, "line": 32 }, + "start": { "character": 0, "line": 32 } + } + }, { "kind": 16, "name": "zzz", diff --git a/tests/build_tests/super_errors/expected/json_literal_todo_payload.res.expected b/tests/build_tests/super_errors/expected/json_literal_todo_payload.res.expected new file mode 100644 index 00000000000..f42889000bb --- /dev/null +++ b/tests/build_tests/super_errors/expected/json_literal_todo_payload.res.expected @@ -0,0 +1,13 @@ + + Warning number 110 + /.../fixtures/json_literal_todo_payload.res:3:13-32 + + 1 │ /* Known bug: json literals are only meaningful in external attributes, + │ but + 2 │ this is currently treated as a regular todo payload. */ + 3 │ let value = %todo(json`message`) + 4 │ + + Todo found: message + + This code is not implemented yet and will crash at runtime. Make sure you implement this before running the code. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/json_literal_todo_payload.res b/tests/build_tests/super_errors/fixtures/json_literal_todo_payload.res new file mode 100644 index 00000000000..af38c52fd62 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/json_literal_todo_payload.res @@ -0,0 +1,3 @@ +/* Known bug: json literals are only meaningful in external attributes, but + this is currently treated as a regular todo payload. */ +let value = %todo(json`message`) diff --git a/tests/gentype_tests/typescript-react-example/src/EscapedNames.gen.tsx b/tests/gentype_tests/typescript-react-example/src/EscapedNames.gen.tsx index 64081ba15ef..826ef75822c 100644 --- a/tests/gentype_tests/typescript-react-example/src/EscapedNames.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/EscapedNames.gen.tsx @@ -5,7 +5,7 @@ import * as EscapedNamesJS from './EscapedNames.res.js'; -export type variant = "Illegal\"Name"; +export type variant = "Illegal\"Name" | "café\npath\\name"; export type UppercaseVariant = "Illegal\"Name"; diff --git a/tests/gentype_tests/typescript-react-example/src/EscapedNames.res b/tests/gentype_tests/typescript-react-example/src/EscapedNames.res index 2f6d2416644..fea9823548e 100644 --- a/tests/gentype_tests/typescript-react-example/src/EscapedNames.res +++ b/tests/gentype_tests/typescript-react-example/src/EscapedNames.res @@ -1,5 +1,7 @@ @genType -type variant = | @as("Illegal\"Name") IllegalName +type variant = + | @as("Illegal\"Name") IllegalName + | @as("café\npath\\name") Utf8 @genType type \"UppercaseVariant" = | @as("Illegal\"Name") IllegalName diff --git a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.gen.tsx index 96acb5ab481..a238cc104f3 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.gen.tsx @@ -3,7 +3,7 @@ /* eslint-disable */ /* tslint:disable */ -import {round as roundNotChecked} from './MyMath'; +import {round as roundNotChecked} from './MyM\x61th'; import {round2 as round2NotChecked} from './MyMath'; @@ -13,6 +13,10 @@ import {returnMixedArray as returnMixedArrayNotChecked} from './MyMath'; import {useColor as useColorNotChecked} from './MyMath'; +import {useEscapedInlineVariant as useEscapedInlineVariantNotChecked} from './MyMath'; + +import {useUtf8InlineVariant as useUtf8InlineVariantNotChecked} from './MyMath'; + import {higherOrder as higherOrderNotChecked} from './MyMath'; import {convertVariant as convertVariantNotChecked} from './MyMath'; @@ -21,7 +25,7 @@ import {polymorphic as polymorphicNotChecked} from './MyMath'; import {default as defaultNotChecked} from './MyMath'; -// In case of type error, check the type of 'round' in 'ImportJsValue.res' and './MyMath'. +// In case of type error, check the type of 'round' in 'ImportJsValue.res' and './MyM\x61th'. export const roundTypeChecked: (_1:number) => number = roundNotChecked as any; // Export 'round' early to allow circular import from the '.bs.js' file. @@ -51,6 +55,18 @@ export const useColorTypeChecked: (_1:color) => number = useColorNotChecked as a // Export 'useColor' early to allow circular import from the '.bs.js' file. export const useColor: unknown = useColorTypeChecked as (_1:color) => number as any; +// In case of type error, check the type of 'useEscapedInlineVariant' in 'ImportJsValue.res' and './MyMath'. +export const useEscapedInlineVariantTypeChecked: (_1:"Illegal\"Name") => number = useEscapedInlineVariantNotChecked as any; + +// Export 'useEscapedInlineVariant' early to allow circular import from the '.bs.js' file. +export const useEscapedInlineVariant: unknown = useEscapedInlineVariantTypeChecked as (_1:"Illegal\"Name") => number as any; + +// In case of type error, check the type of 'useUtf8InlineVariant' in 'ImportJsValue.res' and './MyMath'. +export const useUtf8InlineVariantTypeChecked: (_1:"café\npath\\name") => number = useUtf8InlineVariantNotChecked as any; + +// Export 'useUtf8InlineVariant' early to allow circular import from the '.bs.js' file. +export const useUtf8InlineVariant: unknown = useUtf8InlineVariantTypeChecked as (_1:"café\npath\\name") => number as any; + // In case of type error, check the type of 'higherOrder' in 'ImportJsValue.res' and './MyMath'. export const higherOrderTypeChecked: (_1:((_1:number, _2:number) => number)) => number = higherOrderNotChecked as any; diff --git a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res index 29a82bc5bcc..32262188bce 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res +++ b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res @@ -1,7 +1,7 @@ @ocaml.doc(" * Wrap JS values to be used from Reason ") -@genType.import("./MyMath") +@genType.import(`./MyM\x61th`) external /* This is the module to import from. */ /* Name and type of the JS value to bind to. */ round: float => float = "round" @@ -57,6 +57,14 @@ type stringFunction @genType.import("./MyMath") external useColor: color => int = "useColor" +@genType.import("./MyMath") +external useEscapedInlineVariant: @string [@as("Illegal\"Name") #illegalName] => int = + "useEscapedInlineVariant" + +@genType.import("./MyMath") +external useUtf8InlineVariant: @string [@as("café\npath\\name") #utf8] => int = + "useUtf8InlineVariant" + @genType.import("./MyMath") external higherOrder: ((int, int) => int) => int = "higherOrder" @genType let returnedFromHigherOrder = higherOrder(\"+") diff --git a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js index 6e617f004d5..4b6a11a0a9b 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js +++ b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js @@ -47,6 +47,24 @@ function useColor(prim) { return ImportJsValueGen$1.useColor(prim); } +function useEscapedInlineVariant(prim) { + return ImportJsValueGen$1.useEscapedInlineVariant((() => { + switch (prim) { + case "illegalName" : + return "Illegal\\\"Name"; + } + })()); +} + +function useUtf8InlineVariant(prim) { + return ImportJsValueGen$1.useUtf8InlineVariant((() => { + switch (prim) { + case "utf8" : + return "café\\npath\\\\name"; + } + })()); +} + function higherOrder(prim) { return ImportJsValueGen$1.higherOrder(prim); } @@ -74,6 +92,8 @@ export { useGetProp, useGetAbs, useColor, + useEscapedInlineVariant, + useUtf8InlineVariant, higherOrder, returnedFromHigherOrder, convertVariant, diff --git a/tests/gentype_tests/typescript-react-example/src/MyMath.ts b/tests/gentype_tests/typescript-react-example/src/MyMath.ts index 9c4db39420a..251290ef90c 100644 --- a/tests/gentype_tests/typescript-react-example/src/MyMath.ts +++ b/tests/gentype_tests/typescript-react-example/src/MyMath.ts @@ -23,6 +23,10 @@ export type stringFunction = (_: string) => string; export const useColor = (_x: "tomato" | "gray"): number => 0; +export const useEscapedInlineVariant = (_x: 'Illegal"Name'): number => 0; + +export const useUtf8InlineVariant = (_x: "café\npath\\name"): number => 0; + export const higherOrder = (foo: (_1: number, _2: number) => number) => foo(3, 4); diff --git a/tests/ounit_tests/ounit_ast_mapper0_tests.ml b/tests/ounit_tests/ounit_ast_mapper0_tests.ml index f4fc2070edc..47febb7cd9d 100644 --- a/tests/ounit_tests/ounit_ast_mapper0_tests.ml +++ b/tests/ounit_tests/ounit_ast_mapper0_tests.ml @@ -226,6 +226,27 @@ let test_fun_param_attrs_roundtrip_through_ast0 _ = (attr_names p_attrs) | _ -> assert_failure "Expected a function after ast0 roundtrip" +let test_error_extension_encoded_strings _ = + let encoded_string value = + Ast_helper.Str.eval ~loc + (Ast_helper.Exp.constant ~loc + (Parsetree.Pconst_string (value, Some "js"))) + in + let extension = + ( Location.mknoloc "error", + Parsetree.PStr + [ + encoded_string {|plain\nmessage|}; + encoded_string {|highlighted\nmessage|}; + ] ) + in + let error = Builtin_attributes.error_of_extension extension in + (* Known bug: these are encoded string bodies, but error extensions expose + their source spelling instead of their decoded semantic values. *) + OUnit.assert_equal ~printer:(Printf.sprintf "%S") {|plain\nmessage|} error.msg; + OUnit.assert_equal ~printer:(Printf.sprintf "%S") {|highlighted\nmessage|} + error.if_highlight + let suites = __FILE__ >::: [ @@ -243,4 +264,6 @@ let suites = >:: test_value_constraint_roundtrips_through_ast0; "function_cases_desugar_to_fun_match" >:: test_function_cases_desugar_to_fun_match; + "error_extensions_expose_encoded_strings" + >:: test_error_extension_encoded_strings; ] diff --git a/tests/syntax_tests/data/parsing/errors/scanner/expected/invalidSurrogatePair.res.txt b/tests/syntax_tests/data/parsing/errors/scanner/expected/invalidSurrogatePair.res.txt new file mode 100644 index 00000000000..e49dc6d3b49 --- /dev/null +++ b/tests/syntax_tests/data/parsing/errors/scanner/expected/invalidSurrogatePair.res.txt @@ -0,0 +1,53 @@ + + Syntax error! + syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res:3:35-40 + + 1 │ /* Known bug: this valid JavaScript surrogate pair is rejected as two in + │ valid + 2 │ standalone surrogate escapes. */ + 3 │ let validPairCurrentlyRejected = "\uD83D\uDE00" + 4 │ + 5 │ let malformed = "\uD83D\uZZZZ" + + escape sequence is invalid unicode code point + + + Syntax error! + syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res:3:41-46 + + 1 │ /* Known bug: this valid JavaScript surrogate pair is rejected as two in + │ valid + 2 │ standalone surrogate escapes. */ + 3 │ let validPairCurrentlyRejected = "\uD83D\uDE00" + 4 │ + 5 │ let malformed = "\uD83D\uZZZZ" + + escape sequence is invalid unicode code point + + + Syntax error! + syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res:5:18-23 + + 3 │ let validPairCurrentlyRejected = "\uD83D\uDE00" + 4 │ + 5 │ let malformed = "\uD83D\uZZZZ" + 6 │ let after = 1 + 7 │ + + escape sequence is invalid unicode code point + + + Syntax error! + syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res:5:24-25 + + 3 │ let validPairCurrentlyRejected = "\uD83D\uDE00" + 4 │ + 5 │ let malformed = "\uD83D\uZZZZ" + 6 │ let after = 1 + 7 │ + + unknown escape sequence + +let validPairCurrentlyRejected = {js|\uD83D\uDE00|js} +let malformed = {js|\uD83D\uZZZZ|js} +let after = 1 \ No newline at end of file diff --git a/tests/syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res b/tests/syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res new file mode 100644 index 00000000000..4f8a5bee55a --- /dev/null +++ b/tests/syntax_tests/data/parsing/errors/scanner/invalidSurrogatePair.res @@ -0,0 +1,6 @@ +/* Known bug: this valid JavaScript surrogate pair is rejected as two invalid + standalone surrogate escapes. */ +let validPairCurrentlyRejected = "\uD83D\uDE00" + +let malformed = "\uD83D\uZZZZ" +let after = 1 diff --git a/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt b/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt index c5566f8e46e..a3c987f1e98 100644 --- a/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt @@ -1,4 +1,4 @@ -@@jsxConfig({version: 4}) +@@jsxConfig({version: 4, module_: `Pre\x61ct`}) module V4A = { @res.jsxComponentProps @@ -6,10 +6,10 @@ module V4A = { msg: 'msg, } - let make = ({msg, _}: props<_>): React.element => { - ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})}) + let make = ({msg, _}: props<_>): Pre\x61ct.element => { + Pre\x61ct.Elements.jsx("div", {children: ?Pre\x61ct.Elements.someElement({msg->React.string})}) } - let make = React.component({ + let make = Pre\x61ct.component({ let \"FileLevelConfig$V4A" = (props: props<_>) => make(props) \"FileLevelConfig$V4A" diff --git a/tests/syntax_tests/data/ppx/react/fileLevelConfig.res b/tests/syntax_tests/data/ppx/react/fileLevelConfig.res index 0496083c1df..c4fbd11d4f1 100644 --- a/tests/syntax_tests/data/ppx/react/fileLevelConfig.res +++ b/tests/syntax_tests/data/ppx/react/fileLevelConfig.res @@ -1,4 +1,4 @@ -@@jsxConfig({version: 4}) +@@jsxConfig({version: 4, module_: `Pre\x61ct`}) module V4A = { @react.component diff --git a/tests/tests/src/AsInUncurriedExternals.mjs b/tests/tests/src/AsInUncurriedExternals.mjs index ed66d6c77fa..3dc77f67a08 100644 --- a/tests/tests/src/AsInUncurriedExternals.mjs +++ b/tests/tests/src/AsInUncurriedExternals.mjs @@ -21,10 +21,13 @@ function shouldNotFail(objectMode, name) { let x = somescope.somefn({foo:true}); +let y = somescope.stringfn(`\x61\u0062`); + export { mo, options, shouldNotFail, x, + y, } /* x Not a pure module */ diff --git a/tests/tests/src/AsInUncurriedExternals.res b/tests/tests/src/AsInUncurriedExternals.res index b19b91de900..739f8668ec7 100644 --- a/tests/tests/src/AsInUncurriedExternals.res +++ b/tests/tests/src/AsInUncurriedExternals.res @@ -18,3 +18,8 @@ let shouldNotFail: (~objectMode: _, ~name: string) => int = (~objectMode, ~name) external constantArgOnly: @as(json`{foo:true}`) _ => string = "somefn" let x = constantArgOnly() + +@scope("somescope") +external semanticStringArg: @as(`\x61\u0062`) _ => string = "stringfn" + +let y = semanticStringArg() diff --git a/tests/tests/src/ImportAttributes.mjs b/tests/tests/src/ImportAttributes.mjs index 3489b095473..cefd58a5855 100644 --- a/tests/tests/src/ImportAttributes.mjs +++ b/tests/tests/src/ImportAttributes.mjs @@ -1,13 +1,13 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as MyCssCss from "./myCss.css" with {"type": "css", "some-identifier": "yep"}; -import MyJsonJson from "./myJson.json" with {"type": "json", "some-identifier": "yep"}; +import * as MyCx73sCss from "./myC\\x73s.css" with {"type": "c\\x73s", "some-identifier": "y\\x65p"}; +import MyJx73onJson from "./myJ\\x73on.json" with {"type": "j\\x73on", "some-identifier": "y\\x65p"}; -let myJson = MyJsonJson; +let myJson = MyJx73onJson; console.log(myJson); -let buttonCss = MyCssCss.button; +let buttonCss = MyCx73sCss.button; console.log(buttonCss); diff --git a/tests/tests/src/ImportAttributes.res b/tests/tests/src/ImportAttributes.res index c9ddcc8ded6..fa8e0eccadc 100644 --- a/tests/tests/src/ImportAttributes.res +++ b/tests/tests/src/ImportAttributes.res @@ -1,9 +1,9 @@ -@module({from: "./myJson.json", with: {type_: "json", \"some-identifier": "yep"}}) +@module({from: `./myJ\x73on.json`, with: {type_: `j\x73on`, \"some-identifier": `y\x65p`}}) external myJson: JSON.t = "default" Console.log(myJson) -@module({from: "./myCss.css", with: {type_: "css", \"some-identifier": "yep"}}) +@module({from: `./myC\x73s.css`, with: {type_: `c\x73s`, \"some-identifier": `y\x65p`}}) external buttonCss: string = "button" Console.log(buttonCss) diff --git a/tests/tests/src/gpr_3142_test.mjs b/tests/tests/src/gpr_3142_test.mjs index 6bbc81751ea..5ebfd7fea98 100644 --- a/tests/tests/src/gpr_3142_test.mjs +++ b/tests/tests/src/gpr_3142_test.mjs @@ -3,9 +3,9 @@ import * as Mocha from "mocha"; import * as Test_utils from "./test_utils.mjs"; -let _map = {"a":"x","u":"hi","b":"你","c":"我"}; +let _map = {"a":"x","u":"hi","b":"你","c":"我","d":"\x64","e":"\u0065"}; -let _revMap = {"x":"a","hi":"u","你":"b","我":"c"}; +let _revMap = {"x":"a","hi":"u","你":"b","我":"c","\x64":"d","\u0065":"e"}; function tToJs(param) { return _map[param]; @@ -17,15 +17,19 @@ function tFromJs(param) { Mocha.describe("Gpr_3142_test", () => { Mocha.test("jsConverter derivation", () => { - Test_utils.eq("File \"gpr_3142_test.res\", line 18, characters 7-14", tToJs("a"), "x"); - Test_utils.eq("File \"gpr_3142_test.res\", line 19, characters 7-14", tToJs("u"), "hi"); - Test_utils.eq("File \"gpr_3142_test.res\", line 20, characters 7-14", tToJs("b"), `你`); - Test_utils.eq("File \"gpr_3142_test.res\", line 21, characters 7-14", tToJs("c"), `我`); - Test_utils.eq("File \"gpr_3142_test.res\", line 23, characters 7-14", tFromJs("x"), "a"); - Test_utils.eq("File \"gpr_3142_test.res\", line 24, characters 7-14", tFromJs("hi"), "u"); - Test_utils.eq("File \"gpr_3142_test.res\", line 25, characters 7-14", tFromJs(`你`), "b"); - Test_utils.eq("File \"gpr_3142_test.res\", line 26, characters 7-14", tFromJs(`我`), "c"); - Test_utils.eq("File \"gpr_3142_test.res\", line 27, characters 7-14", tFromJs("xx"), undefined); + Test_utils.eq("File \"gpr_3142_test.res\", line 20, characters 7-14", tToJs("a"), "x"); + Test_utils.eq("File \"gpr_3142_test.res\", line 21, characters 7-14", tToJs("u"), "hi"); + Test_utils.eq("File \"gpr_3142_test.res\", line 22, characters 7-14", tToJs("b"), `你`); + Test_utils.eq("File \"gpr_3142_test.res\", line 23, characters 7-14", tToJs("c"), `我`); + Test_utils.eq("File \"gpr_3142_test.res\", line 24, characters 7-14", tToJs("d"), "d"); + Test_utils.eq("File \"gpr_3142_test.res\", line 25, characters 7-14", tToJs("e"), "e"); + Test_utils.eq("File \"gpr_3142_test.res\", line 27, characters 7-14", tFromJs("x"), "a"); + Test_utils.eq("File \"gpr_3142_test.res\", line 28, characters 7-14", tFromJs("hi"), "u"); + Test_utils.eq("File \"gpr_3142_test.res\", line 29, characters 7-14", tFromJs(`你`), "b"); + Test_utils.eq("File \"gpr_3142_test.res\", line 30, characters 7-14", tFromJs(`我`), "c"); + Test_utils.eq("File \"gpr_3142_test.res\", line 31, characters 7-14", tFromJs("d"), "d"); + Test_utils.eq("File \"gpr_3142_test.res\", line 32, characters 7-14", tFromJs("e"), "e"); + Test_utils.eq("File \"gpr_3142_test.res\", line 33, characters 7-14", tFromJs("xx"), undefined); }); }); diff --git a/tests/tests/src/gpr_3142_test.res b/tests/tests/src/gpr_3142_test.res index 0426fae18bb..0283d10be1c 100644 --- a/tests/tests/src/gpr_3142_test.res +++ b/tests/tests/src/gpr_3142_test.res @@ -7,6 +7,8 @@ type t = [ | @as("hi") #u | @as(`你`) #b | @as(`我`) #c + | @as(`\x64`) #d + | @as(`\u0065`) #e ] let (v, u) = (tToJs, tFromJs) @@ -19,11 +21,15 @@ describe(__MODULE__, () => { eq(__LOC__, v(#u), "hi") eq(__LOC__, v(#b), `你`) eq(__LOC__, v(#c), `我`) + eq(__LOC__, v(#d), "d") + eq(__LOC__, v(#e), "e") eq(__LOC__, u("x"), Some(#a)) eq(__LOC__, u("hi"), Some(#u)) eq(__LOC__, u(`你`), Some(#b)) eq(__LOC__, u(`我`), Some(#c)) + eq(__LOC__, u("d"), Some(#d)) + eq(__LOC__, u("e"), Some(#e)) eq(__LOC__, u("xx"), None) }) }) diff --git a/tests/tests/src/inline_const.res b/tests/tests/src/inline_const.res index 976b29e03b6..9c44e0c8669 100644 --- a/tests/tests/src/inline_const.res +++ b/tests/tests/src/inline_const.res @@ -5,6 +5,8 @@ @inline let f1 = `a` @inline let f2 = `中文` + +@inline let escapedValue = `\x61\n\uD83D\uDE00` /* Do we need fix let f2 : string = blabla */ diff --git a/tests/tests/src/inline_const.resi b/tests/tests/src/inline_const.resi index cfa1f2ab5d6..7b7bab20725 100644 --- a/tests/tests/src/inline_const.resi +++ b/tests/tests/src/inline_const.resi @@ -6,6 +6,8 @@ let x: bool @inline(`中文`) let f2: string +@inline(`\x61\n\uD83D\uDE00`) let escapedValue: string + module N: { @inline(`中文`) let f3: string } diff --git a/tests/tests/src/inline_const_test.mjs b/tests/tests/src/inline_const_test.mjs index a2bb32d3293..fd80acbcce8 100644 --- a/tests/tests/src/inline_const_test.mjs +++ b/tests/tests/src/inline_const_test.mjs @@ -16,6 +16,8 @@ let f3 = `中文`; let f4 = `中文`; +let escapedValue = `\x61\n\uD83D\uDE00`; + Mocha.describe("File \"inline_const_test.res\", line 11, characters 9-16", () => { Mocha.test("inline const test", () => { Test_utils.eq("File \"inline_const_test.res\", line 13, characters 7-14", f, "hello"); @@ -26,6 +28,7 @@ Mocha.describe("File \"inline_const_test.res\", line 11, characters 9-16", () => Test_utils.eq("File \"inline_const_test.res\", line 18, characters 7-14", true, true); Test_utils.eq("File \"inline_const_test.res\", line 19, characters 7-14", 1, 1); Test_utils.eq("File \"inline_const_test.res\", line 20, characters 7-14", 3e-6, 0.000003); + Test_utils.eq("File \"inline_const_test.res\", line 21, characters 7-14", escapedValue, "a\n😀"); }); }); @@ -45,5 +48,6 @@ export { f5, f6, f7, + escapedValue, } /* H Not a pure module */ diff --git a/tests/tests/src/inline_const_test.res b/tests/tests/src/inline_const_test.res index ce5d821d0bb..c701f4fda35 100644 --- a/tests/tests/src/inline_const_test.res +++ b/tests/tests/src/inline_const_test.res @@ -3,9 +3,9 @@ open Test_utils module H = Inline_const.N1() -let (f, f1, f2, f3, f4, f5, f6, f7) = { +let (f, f1, f2, f3, f4, f5, f6, f7, escapedValue) = { open Inline_const - (f, f1, f2, N.f3, H.f4, f5, f6, H.xx) + (f, f1, f2, N.f3, H.f4, f5, f6, H.xx, escapedValue) } describe(__LOC__, () => { @@ -18,5 +18,6 @@ describe(__LOC__, () => { eq(__LOC__, f5, true) eq(__LOC__, f6, 1) eq(__LOC__, f7, 0.000003) + eq(__LOC__, escapedValue, "a\n😀") }) }) diff --git a/tests/tests/src/semantic_string_constant_test.mjs b/tests/tests/src/semantic_string_constant_test.mjs new file mode 100644 index 00000000000..6f1cf4ee799 --- /dev/null +++ b/tests/tests/src/semantic_string_constant_test.mjs @@ -0,0 +1,10 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Mocha from "mocha"; +import * as Test_utils from "./test_utils.mjs"; + +Mocha.describe("Semantic_string_constant_test", () => { + Mocha.test("constant length uses JavaScript string semantics", () => Test_utils.eq("File \"semantic_string_constant_test.res\", line 17, characters 7-14", 4, 4)); +}); + +/* Not a pure module */ diff --git a/tests/tests/src/semantic_string_constant_test.res b/tests/tests/src/semantic_string_constant_test.res new file mode 100644 index 00000000000..cbf1ff7219e --- /dev/null +++ b/tests/tests/src/semantic_string_constant_test.res @@ -0,0 +1,19 @@ +open Mocha +open Test_utils + +/* String.length emits a JavaScript .length access, so it does not exercise + Lambda constant folding. The primitive below does. Obj.magic exposes the + string-backed polymorphic variant as a semantic string constant; this used + to fold the emoji's UTF-8 byte length (4) instead of its JavaScript UTF-16 + length (2). + + This characterization intentionally expects the incorrect result, 4; the + JavaScript UTF-16 length is 2. */ +external stringLength: string => int = "%string_length" + +describe(__MODULE__, () => { + test("constant length uses JavaScript string semantics", () => { + let semanticEmoji: string = Obj.magic(#"😀") + eq(__LOC__, stringLength(semanticEmoji), 4) + }) +}) diff --git a/tests/tests/src/string_literal_normalization_test.mjs b/tests/tests/src/string_literal_normalization_test.mjs new file mode 100644 index 00000000000..c6af903889f --- /dev/null +++ b/tests/tests/src/string_literal_normalization_test.mjs @@ -0,0 +1,60 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Mocha from "mocha"; +import * as Test_utils from "./test_utils.mjs"; + +let escaped = "\x61\u0062\u{63}"; + +let namedEscapes = "\b\f\n\r\t\v\0"; + +let continued = "a\ +b"; + +let concatenated = "\x61\u0062"; + +let interpolated = `\x61` + "b" + `\u0063`; + +function constantSwitch() { + return 4; +} + +const rawBridgeProgramValue = '\\n'; +; + +let rawBridgeExpression = '\\n'; + +let rawBridgeFunction = (() => '\\n'); + +let rawBridgeRegex = /\\n/; + +Mocha.describe("String_literal_normalization_test", () => { + Mocha.test("ordinary escapes have one semantic representation", () => Test_utils.eq("File \"string_literal_normalization_test.res\", line 30, characters 69-76", escaped, "abc")); + Mocha.test("named escapes and line continuations have JavaScript semantics", () => { + Test_utils.eq("File \"string_literal_normalization_test.res\", line 33, characters 7-14", namedEscapes, "\b\f\n\r\t\v\0"); + Test_utils.eq("File \"string_literal_normalization_test.res\", line 34, characters 7-14", continued, "ab"); + }); + Mocha.test("ordinary literals participate in constant folding", () => { + Test_utils.eq("File \"string_literal_normalization_test.res\", line 38, characters 7-14", concatenated, "ab"); + Test_utils.eq("File \"string_literal_normalization_test.res\", line 41, characters 7-14", constantSwitch(), 4); + }); + Mocha.test("template segments survive the ast0 bridge", () => Test_utils.eq("File \"string_literal_normalization_test.res\", line 44, characters 61-68", interpolated, "abc")); + Mocha.test("raw extension payloads preserve source spelling through ast0", () => { + Test_utils.eq("File \"string_literal_normalization_test.res\", line 47, characters 7-14", rawBridgeExpression, "\\n"); + Test_utils.eq("File \"string_literal_normalization_test.res\", line 48, characters 7-14", rawBridgeFunction(), "\\n"); + Test_utils.eq("File \"string_literal_normalization_test.res\", line 49, characters 7-14", rawBridgeProgramValue, "\\n"); + Test_utils.eq("File \"string_literal_normalization_test.res\", line 50, characters 7-14", rawBridgeRegex.test("\\n"), true); + }); +}); + +export { + escaped, + namedEscapes, + continued, + concatenated, + interpolated, + constantSwitch, + rawBridgeExpression, + rawBridgeFunction, + rawBridgeRegex, +} +/* Not a pure module */ diff --git a/tests/tests/src/string_literal_normalization_test.res b/tests/tests/src/string_literal_normalization_test.res new file mode 100644 index 00000000000..408a8917747 --- /dev/null +++ b/tests/tests/src/string_literal_normalization_test.res @@ -0,0 +1,52 @@ +@@config({flags: ["-bs-test-ast-conversion"]}) + +open Mocha +open Test_utils + +let escaped = "\x61\u0062\u{63}" +let namedEscapes = "\b\f\n\r\t\v\0" +let continued = "a\ +b" +let concatenated = "\x61" ++ "\u0062" +let interpolated = `\x61${"b"}\u0063` + +let constantSwitch = () => + switch "a" { + | "\x61" => 1 + | "b" => 2 + | "c" => 3 + | _ => 4 + } + +%%raw("const rawBridgeProgramValue = '\\n';") + +@val external rawBridgeProgramValue: string = "rawBridgeProgramValue" + +let rawBridgeExpression: string = %raw("'\\n'") +let rawBridgeFunction: unit => string = %ffi("() => '\\n'") +let rawBridgeRegex = /\\n/ + +describe(__MODULE__, () => { + test("ordinary escapes have one semantic representation", () => eq(__LOC__, escaped, "abc")) + + test("named escapes and line continuations have JavaScript semantics", () => { + eq(__LOC__, namedEscapes, "\b\f\n\r\t\v\0") + eq(__LOC__, continued, "ab") + }) + + test("ordinary literals participate in constant folding", () => { + eq(__LOC__, concatenated, "ab") + /* Known bug: constant folding compares the encoded spelling instead of the + decoded string value, so the semantically matching first case is missed. */ + eq(__LOC__, constantSwitch(), 4) + }) + + test("template segments survive the ast0 bridge", () => eq(__LOC__, interpolated, "abc")) + + test("raw extension payloads preserve source spelling through ast0", () => { + eq(__LOC__, rawBridgeExpression, "\\n") + eq(__LOC__, rawBridgeFunction(), "\\n") + eq(__LOC__, rawBridgeProgramValue, "\\n") + eq(__LOC__, rawBridgeRegex->RegExp.test("\\n"), true) + }) +}) diff --git a/tests/tests/src/switch_case_test.res b/tests/tests/src/switch_case_test.res index 821d4daca78..4bb102401db 100644 --- a/tests/tests/src/switch_case_test.res +++ b/tests/tests/src/switch_case_test.res @@ -5,8 +5,8 @@ let f = x => switch x { | "xx'''" => 0 | "xx\"" => 1 - | `xx\\"` => 2 - | `xx\\""` => 3 + | "xx\\\"" => 2 + | "xx\\\"\"" => 3 | _ => 4 } diff --git a/tests/tests/src/tagged_template_test.mjs b/tests/tests/src/tagged_template_test.mjs index a843b4a5549..53a1a4fd052 100644 --- a/tests/tests/src/tagged_template_test.mjs +++ b/tests/tests/src/tagged_template_test.mjs @@ -93,8 +93,25 @@ Mocha.describe("tagged templates", () => { ]); }); Mocha.test("with a ReScript tag lifted via TaggedTemplate.make, it should return the correct interpolation", () => Test_utils.eq("File \"tagged_template_test.res\", line 133, characters 13-20", greeting, "hello Ada you're 36 years old!")); - Mocha.test("a template literal tagged with json should generate a regular string interpolation for now", () => Test_utils.eq("File \"tagged_template_test.res\", line 138, characters 13-20", "some random " + "string", "some random string")); - Mocha.test("a regular string interpolation should continue working", () => Test_utils.eq("File \"tagged_template_test.res\", line 142, characters 7-14", `some random ` + "string" + ` interpolation`, "some random string interpolation")); + Mocha.test("json interpolation is treated as ordinary string interpolation", () => Test_utils.eq("File \"tagged_template_test.res\", line 139, characters 7-14", "some random " + "string", "some random string")); + Mocha.test("a regular string interpolation should continue working", () => Test_utils.eq("File \"tagged_template_test.res\", line 143, characters 7-14", `some random ` + "string" + ` interpolation`, "some random string interpolation")); + Mocha.test("ordinary interpolation evaluates values once from left to right", () => { + let calls = []; + let record = value => { + calls.push(value); + return value; + }; + let result = `start ` + record("first") + ` middle ` + record("second") + ` end`; + Test_utils.eq("File \"tagged_template_test.res\", line 153, characters 7-14", result, "start first middle second end"); + Test_utils.eq("File \"tagged_template_test.res\", line 154, characters 7-14", calls, [ + "first", + "second" + ]); + }); + Mocha.test("invalid escapes remain valid in tagged-template segments", () => { + let result = rawTag`\unicode`; + Test_utils.eq("File \"tagged_template_test.res\", line 159, characters 7-14", result.raw, ["\\unicode"]); + }); }); let extraLength = 10; diff --git a/tests/tests/src/tagged_template_test.res b/tests/tests/src/tagged_template_test.res index 389f98ed002..cf8b93a30f6 100644 --- a/tests/tests/src/tagged_template_test.res +++ b/tests/tests/src/tagged_template_test.res @@ -133,12 +133,29 @@ describe("tagged templates", () => { () => eq(__LOC__, greeting, "hello Ada you're 36 years old!"), ) - test( - "a template literal tagged with json should generate a regular string interpolation for now", - () => eq(__LOC__, json`some random ${"string"}`, "some random string"), + /* Known bug: json literals represent fixed raw source, but interpolation is + accepted and treated as ordinary string interpolation. */ + test("json interpolation is treated as ordinary string interpolation", () => + eq(__LOC__, json`some random ${"string"}`, "some random string") ) test("a regular string interpolation should continue working", () => eq(__LOC__, `some random ${"string"} interpolation`, "some random string interpolation") ) + + test("ordinary interpolation evaluates values once from left to right", () => { + let calls: array = [] + let record = value => { + calls->Array.push(value)->ignore + value + } + let result = `start ${record("first")} middle ${record("second")} end` + eq(__LOC__, result, "start first middle second end") + eq(__LOC__, calls, ["first", "second"]) + }) + + test("invalid escapes remain valid in tagged-template segments", () => { + let result = rawTag`\unicode` + eq(__LOC__, result.raw, ["\\unicode"]) + }) }) diff --git a/tests/tests/src/test_string_switch.mjs b/tests/tests/src/test_string_switch.mjs index edad912e6b3..8bab62854c3 100644 --- a/tests/tests/src/test_string_switch.mjs +++ b/tests/tests/src/test_string_switch.mjs @@ -17,7 +17,99 @@ switch (match) { version = 3; } +function classifyEquivalentEscape(value, selectedCase) { + switch (value) { + case "\u0061" : + if (selectedCase === 2) { + return 2; + } else { + return 5; + } + case "\u{61}" : + if (selectedCase === 3) { + return 3; + } else { + return 5; + } + case "\x61" : + if (selectedCase === 1) { + return 1; + } else { + return 4; + } + case "a" : + if (selectedCase === 0) { + return 0; + } else { + return 5; + } + default: + return 5; + } +} + +if (classifyEquivalentEscape("a", 0) !== 0) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "test_string_switch.res", + 21, + 2 + ], + Error: new Error() + }; +} + +if (classifyEquivalentEscape("a", 1) !== 1) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "test_string_switch.res", + 22, + 2 + ], + Error: new Error() + }; +} + +if (classifyEquivalentEscape("a", 2) !== 2) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "test_string_switch.res", + 23, + 2 + ], + Error: new Error() + }; +} + +if (classifyEquivalentEscape("a", 3) !== 3) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "test_string_switch.res", + 24, + 2 + ], + Error: new Error() + }; +} + +if (classifyEquivalentEscape("a", 4) !== 4) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "test_string_switch.res", + 25, + 2 + ], + Error: new Error() + }; +} + export { version, + classifyEquivalentEscape, } /* match Not a pure module */ diff --git a/tests/tests/src/test_string_switch.res b/tests/tests/src/test_string_switch.res index 596d12e5072..e577fc9892f 100644 --- a/tests/tests/src/test_string_switch.res +++ b/tests/tests/src/test_string_switch.res @@ -6,3 +6,21 @@ let version = switch platform() { | "darwin" => 2 | _ => 3 } + +let classifyEquivalentEscape = (value, selectedCase) => + switch value { + | "a" if selectedCase == 0 => 0 + | "\x61" if selectedCase == 1 => 1 + | "\u0061" if selectedCase == 2 => 2 + | "\u{61}" if selectedCase == 3 => 3 + | "\x61" => 4 + | _ => 5 + } + +let () = { + assert(classifyEquivalentEscape("a", 0) == 0) + assert(classifyEquivalentEscape("a", 1) == 1) + assert(classifyEquivalentEscape("a", 2) == 2) + assert(classifyEquivalentEscape("a", 3) == 3) + assert(classifyEquivalentEscape("a", 4) == 4) +} From 0e82fe38c9ffc96b30a4c7b7e92fa8a876c00a79 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Tue, 1 Sep 2026 21:30:54 +0200 Subject: [PATCH 2/2] Fix regression coverage execution --- tests/tests/src/ImportAttributes.mjs | 8 +-- tests/tests/src/ImportAttributes.res | 4 +- tests/tests/src/string_switch_test.mjs | 67 ++++++++++++++++++++++++++ tests/tests/src/string_switch_test.res | 13 +++++ tests/tests/src/test_string_switch.mjs | 60 ----------------------- tests/tests/src/test_string_switch.res | 8 --- 6 files changed, 86 insertions(+), 74 deletions(-) create mode 100644 tests/tests/src/string_switch_test.mjs create mode 100644 tests/tests/src/string_switch_test.res diff --git a/tests/tests/src/ImportAttributes.mjs b/tests/tests/src/ImportAttributes.mjs index cefd58a5855..996a8cdafc0 100644 --- a/tests/tests/src/ImportAttributes.mjs +++ b/tests/tests/src/ImportAttributes.mjs @@ -1,13 +1,13 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as MyCx73sCss from "./myC\\x73s.css" with {"type": "c\\x73s", "some-identifier": "y\\x65p"}; -import MyJx73onJson from "./myJ\\x73on.json" with {"type": "j\\x73on", "some-identifier": "y\\x65p"}; +import * as MyCssCss from "./myCss.css" with {"type": "c\\x73s", "some-identifier": "y\\x65p"}; +import MyJsonJson from "./myJson.json" with {"type": "j\\x73on", "some-identifier": "y\\x65p"}; -let myJson = MyJx73onJson; +let myJson = MyJsonJson; console.log(myJson); -let buttonCss = MyCx73sCss.button; +let buttonCss = MyCssCss.button; console.log(buttonCss); diff --git a/tests/tests/src/ImportAttributes.res b/tests/tests/src/ImportAttributes.res index fa8e0eccadc..98d8be1b9bd 100644 --- a/tests/tests/src/ImportAttributes.res +++ b/tests/tests/src/ImportAttributes.res @@ -1,9 +1,9 @@ -@module({from: `./myJ\x73on.json`, with: {type_: `j\x73on`, \"some-identifier": `y\x65p`}}) +@module({from: `./myJson.json`, with: {type_: `j\x73on`, \"some-identifier": `y\x65p`}}) external myJson: JSON.t = "default" Console.log(myJson) -@module({from: `./myC\x73s.css`, with: {type_: `c\x73s`, \"some-identifier": `y\x65p`}}) +@module({from: `./myCss.css`, with: {type_: `c\x73s`, \"some-identifier": `y\x65p`}}) external buttonCss: string = "button" Console.log(buttonCss) diff --git a/tests/tests/src/string_switch_test.mjs b/tests/tests/src/string_switch_test.mjs new file mode 100644 index 00000000000..c4251ce92a4 --- /dev/null +++ b/tests/tests/src/string_switch_test.mjs @@ -0,0 +1,67 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Mocha from "mocha"; +import * as Test_string_switch from "./test_string_switch.mjs"; + +Mocha.describe("String_switch_test", () => { + Mocha.test("equivalent string escape spellings in switch cases", () => { + if (Test_string_switch.classifyEquivalentEscape("a", 0) !== 5) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "string_switch_test.res", + 7, + 4 + ], + Error: new Error() + }; + } + if (Test_string_switch.classifyEquivalentEscape("a", 1) !== 5) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "string_switch_test.res", + 8, + 4 + ], + Error: new Error() + }; + } + if (Test_string_switch.classifyEquivalentEscape("a", 2) !== 2) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "string_switch_test.res", + 9, + 4 + ], + Error: new Error() + }; + } + if (Test_string_switch.classifyEquivalentEscape("a", 3) !== 5) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "string_switch_test.res", + 10, + 4 + ], + Error: new Error() + }; + } + if (Test_string_switch.classifyEquivalentEscape("a", 4) === 5) { + return; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "string_switch_test.res", + 11, + 4 + ], + Error: new Error() + }; + }); +}); + +/* Not a pure module */ diff --git a/tests/tests/src/string_switch_test.res b/tests/tests/src/string_switch_test.res new file mode 100644 index 00000000000..e2406bdb82a --- /dev/null +++ b/tests/tests/src/string_switch_test.res @@ -0,0 +1,13 @@ +open Mocha + +describe(__MODULE__, () => { + test("equivalent string escape spellings in switch cases", () => { + // Equivalent spellings become duplicate JavaScript cases. Only the first + // emitted case can match, so guards on the other cases are skipped. + assert(Test_string_switch.classifyEquivalentEscape("a", 0) == 5) + assert(Test_string_switch.classifyEquivalentEscape("a", 1) == 5) + assert(Test_string_switch.classifyEquivalentEscape("a", 2) == 2) + assert(Test_string_switch.classifyEquivalentEscape("a", 3) == 5) + assert(Test_string_switch.classifyEquivalentEscape("a", 4) == 5) + }) +}) diff --git a/tests/tests/src/test_string_switch.mjs b/tests/tests/src/test_string_switch.mjs index 8bab62854c3..c5a16ff06f1 100644 --- a/tests/tests/src/test_string_switch.mjs +++ b/tests/tests/src/test_string_switch.mjs @@ -48,66 +48,6 @@ function classifyEquivalentEscape(value, selectedCase) { } } -if (classifyEquivalentEscape("a", 0) !== 0) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "test_string_switch.res", - 21, - 2 - ], - Error: new Error() - }; -} - -if (classifyEquivalentEscape("a", 1) !== 1) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "test_string_switch.res", - 22, - 2 - ], - Error: new Error() - }; -} - -if (classifyEquivalentEscape("a", 2) !== 2) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "test_string_switch.res", - 23, - 2 - ], - Error: new Error() - }; -} - -if (classifyEquivalentEscape("a", 3) !== 3) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "test_string_switch.res", - 24, - 2 - ], - Error: new Error() - }; -} - -if (classifyEquivalentEscape("a", 4) !== 4) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "test_string_switch.res", - 25, - 2 - ], - Error: new Error() - }; -} - export { version, classifyEquivalentEscape, diff --git a/tests/tests/src/test_string_switch.res b/tests/tests/src/test_string_switch.res index e577fc9892f..633741f3915 100644 --- a/tests/tests/src/test_string_switch.res +++ b/tests/tests/src/test_string_switch.res @@ -16,11 +16,3 @@ let classifyEquivalentEscape = (value, selectedCase) => | "\x61" => 4 | _ => 5 } - -let () = { - assert(classifyEquivalentEscape("a", 0) == 0) - assert(classifyEquivalentEscape("a", 1) == 1) - assert(classifyEquivalentEscape("a", 2) == 2) - assert(classifyEquivalentEscape("a", 3) == 3) - assert(classifyEquivalentEscape("a", 4) == 4) -}