typia 13.1.0 → 13.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/README.md +3 -0
  2. package/lib/_virtual/_rolldown/runtime.mjs +1 -5
  3. package/lib/executable/FileSystemIdentity.d.ts +21 -0
  4. package/lib/executable/FileSystemIdentity.js +183 -0
  5. package/lib/executable/FileSystemIdentity.js.map +1 -0
  6. package/lib/executable/FileSystemIdentity.mjs +129 -0
  7. package/lib/executable/FileSystemIdentity.mjs.map +1 -0
  8. package/lib/executable/TypiaGenerateWizard.js +264 -104
  9. package/lib/executable/TypiaGenerateWizard.js.map +1 -1
  10. package/lib/executable/TypiaGenerateWizard.mjs +233 -93
  11. package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
  12. package/lib/functional.d.ts +15 -12
  13. package/lib/functional.js.map +1 -1
  14. package/lib/functional.mjs.map +1 -1
  15. package/lib/internal/_ProtobufReader.d.ts +17 -0
  16. package/lib/internal/_ProtobufReader.js +117 -45
  17. package/lib/internal/_ProtobufReader.js.map +1 -1
  18. package/lib/internal/_ProtobufReader.mjs +108 -39
  19. package/lib/internal/_ProtobufReader.mjs.map +1 -1
  20. package/lib/internal/_createStandardSchema.js +18 -1
  21. package/lib/internal/_createStandardSchema.js.map +1 -1
  22. package/lib/internal/_createStandardSchema.mjs +12 -1
  23. package/lib/internal/_createStandardSchema.mjs.map +1 -1
  24. package/lib/internal/_decimal.d.ts +14 -0
  25. package/lib/internal/_decimal.js +61 -0
  26. package/lib/internal/_decimal.js.map +1 -0
  27. package/lib/internal/_decimal.mjs +49 -0
  28. package/lib/internal/_decimal.mjs.map +1 -0
  29. package/lib/internal/_httpQueryParseURLSearchParams.js +23 -2
  30. package/lib/internal/_httpQueryParseURLSearchParams.js.map +1 -1
  31. package/lib/internal/_httpQueryParseURLSearchParams.mjs +20 -2
  32. package/lib/internal/_httpQueryParseURLSearchParams.mjs.map +1 -1
  33. package/lib/internal/_isFormatByte.js +2 -5
  34. package/lib/internal/_isFormatByte.js.map +1 -1
  35. package/lib/internal/_isFormatByte.mjs +2 -5
  36. package/lib/internal/_isFormatByte.mjs.map +1 -1
  37. package/lib/internal/_isFormatDate.js +15 -2
  38. package/lib/internal/_isFormatDate.js.map +1 -1
  39. package/lib/internal/_isFormatDate.mjs +22 -2
  40. package/lib/internal/_isFormatDate.mjs.map +1 -1
  41. package/lib/internal/_isFormatDateTime.js +21 -2
  42. package/lib/internal/_isFormatDateTime.js.map +1 -1
  43. package/lib/internal/_isFormatDateTime.mjs +13 -2
  44. package/lib/internal/_isFormatDateTime.mjs.map +1 -1
  45. package/lib/internal/_isFormatIri.js +3 -2
  46. package/lib/internal/_isFormatIri.js.map +1 -1
  47. package/lib/internal/_isFormatIri.mjs +3 -2
  48. package/lib/internal/_isFormatIri.mjs.map +1 -1
  49. package/lib/internal/_isFormatIriReference.js +10 -2
  50. package/lib/internal/_isFormatIriReference.js.map +1 -1
  51. package/lib/internal/_isFormatIriReference.mjs +9 -2
  52. package/lib/internal/_isFormatIriReference.mjs.map +1 -1
  53. package/lib/internal/_isFormatUriReference.js +1 -1
  54. package/lib/internal/_isFormatUriReference.js.map +1 -1
  55. package/lib/internal/_isFormatUriReference.mjs +1 -1
  56. package/lib/internal/_isFormatUriReference.mjs.map +1 -1
  57. package/lib/internal/_isMultipleOf.d.ts +1 -0
  58. package/lib/internal/_isMultipleOf.js +13 -0
  59. package/lib/internal/_isMultipleOf.js.map +1 -0
  60. package/lib/internal/_isMultipleOf.mjs +12 -0
  61. package/lib/internal/_isMultipleOf.mjs.map +1 -0
  62. package/lib/internal/_isTypeFloat.js +1 -1
  63. package/lib/internal/_isTypeFloat.js.map +1 -1
  64. package/lib/internal/_isTypeFloat.mjs +1 -1
  65. package/lib/internal/_isTypeFloat.mjs.map +1 -1
  66. package/lib/internal/_isTypeInt64.js +1 -0
  67. package/lib/internal/_isTypeInt64.js.map +1 -1
  68. package/lib/internal/_isTypeInt64.mjs.map +1 -1
  69. package/lib/internal/_isTypeInt64Bigint.d.ts +1 -0
  70. package/lib/internal/_isTypeInt64Bigint.js +15 -0
  71. package/lib/internal/_isTypeInt64Bigint.js.map +1 -0
  72. package/lib/internal/_isTypeInt64Bigint.mjs +8 -0
  73. package/lib/internal/_isTypeInt64Bigint.mjs.map +1 -0
  74. package/lib/internal/_isTypeUint64.js +1 -0
  75. package/lib/internal/_isTypeUint64.js.map +1 -1
  76. package/lib/internal/_isTypeUint64.mjs.map +1 -1
  77. package/lib/internal/_isTypeUint64Bigint.d.ts +1 -0
  78. package/lib/internal/_isTypeUint64Bigint.js +10 -0
  79. package/lib/internal/_isTypeUint64Bigint.js.map +1 -0
  80. package/lib/internal/_isTypeUint64Bigint.mjs +8 -0
  81. package/lib/internal/_isTypeUint64Bigint.mjs.map +1 -0
  82. package/lib/internal/_isUniqueItems.js +96 -109
  83. package/lib/internal/_isUniqueItems.js.map +1 -1
  84. package/lib/internal/_isUniqueItems.mjs +62 -50
  85. package/lib/internal/_isUniqueItems.mjs.map +1 -1
  86. package/lib/internal/_notationAny.js +8 -1
  87. package/lib/internal/_notationAny.js.map +1 -1
  88. package/lib/internal/_notationAny.mjs +7 -1
  89. package/lib/internal/_notationAny.mjs.map +1 -1
  90. package/lib/internal/_notationAssign.d.ts +1 -0
  91. package/lib/internal/_notationAssign.js +18 -0
  92. package/lib/internal/_notationAssign.js.map +1 -0
  93. package/lib/internal/_notationAssign.mjs +17 -0
  94. package/lib/internal/_notationAssign.mjs.map +1 -0
  95. package/lib/internal/_notationCamel.js +30 -9
  96. package/lib/internal/_notationCamel.js.map +1 -1
  97. package/lib/internal/_notationCamel.mjs +13 -5
  98. package/lib/internal/_notationCamel.mjs.map +1 -1
  99. package/lib/internal/_notationKebab.d.ts +1 -0
  100. package/lib/internal/_notationKebab.js +15 -0
  101. package/lib/internal/_notationKebab.js.map +1 -0
  102. package/lib/internal/_notationKebab.mjs +15 -0
  103. package/lib/internal/_notationKebab.mjs.map +1 -0
  104. package/lib/internal/_notationKeyCollision.d.ts +1 -0
  105. package/lib/internal/_notationKeyCollision.js +8 -0
  106. package/lib/internal/_notationKeyCollision.js.map +1 -0
  107. package/lib/internal/_notationKeyCollision.mjs +8 -0
  108. package/lib/internal/_notationKeyCollision.mjs.map +1 -0
  109. package/lib/internal/_notationPascal.js +20 -5
  110. package/lib/internal/_notationPascal.js.map +1 -1
  111. package/lib/internal/_notationPascal.mjs +10 -5
  112. package/lib/internal/_notationPascal.mjs.map +1 -1
  113. package/lib/internal/_notationSnake.js +25 -22
  114. package/lib/internal/_notationSnake.js.map +1 -1
  115. package/lib/internal/_notationSnake.mjs +11 -11
  116. package/lib/internal/_notationSnake.mjs.map +1 -1
  117. package/lib/internal/_plainCloneAny.js +174 -38
  118. package/lib/internal/_plainCloneAny.js.map +1 -1
  119. package/lib/internal/_plainCloneAny.mjs +126 -22
  120. package/lib/internal/_plainCloneAny.mjs.map +1 -1
  121. package/lib/internal/_randomArray.d.ts +1 -1
  122. package/lib/internal/_randomArray.js +11 -4
  123. package/lib/internal/_randomArray.js.map +1 -1
  124. package/lib/internal/_randomArray.mjs +9 -3
  125. package/lib/internal/_randomArray.mjs.map +1 -1
  126. package/lib/internal/_randomFormatByte.d.ts +2 -1
  127. package/lib/internal/_randomFormatByte.js +2 -1
  128. package/lib/internal/_randomFormatByte.js.map +1 -1
  129. package/lib/internal/_randomFormatByte.mjs +2 -1
  130. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  131. package/lib/internal/_randomFormatDate.d.ts +2 -0
  132. package/lib/internal/_randomFormatDate.js +3 -2
  133. package/lib/internal/_randomFormatDate.js.map +1 -1
  134. package/lib/internal/_randomFormatDate.mjs +3 -2
  135. package/lib/internal/_randomFormatDate.mjs.map +1 -1
  136. package/lib/internal/_randomFormatDatetime.d.ts +2 -0
  137. package/lib/internal/_randomFormatDatetime.js +3 -2
  138. package/lib/internal/_randomFormatDatetime.js.map +1 -1
  139. package/lib/internal/_randomFormatDatetime.mjs +3 -2
  140. package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
  141. package/lib/internal/_randomFormatDuration.d.ts +2 -1
  142. package/lib/internal/_randomFormatDuration.js +3 -2
  143. package/lib/internal/_randomFormatDuration.js.map +1 -1
  144. package/lib/internal/_randomFormatDuration.mjs +3 -2
  145. package/lib/internal/_randomFormatDuration.mjs.map +1 -1
  146. package/lib/internal/_randomFormatEmail.d.ts +2 -1
  147. package/lib/internal/_randomFormatEmail.js +8 -1
  148. package/lib/internal/_randomFormatEmail.js.map +1 -1
  149. package/lib/internal/_randomFormatEmail.mjs +5 -1
  150. package/lib/internal/_randomFormatEmail.mjs.map +1 -1
  151. package/lib/internal/_randomFormatHostname.d.ts +8 -1
  152. package/lib/internal/_randomFormatHostname.js +45 -2
  153. package/lib/internal/_randomFormatHostname.js.map +1 -1
  154. package/lib/internal/_randomFormatHostname.mjs +38 -2
  155. package/lib/internal/_randomFormatHostname.mjs.map +1 -1
  156. package/lib/internal/_randomFormatIdnEmail.d.ts +2 -1
  157. package/lib/internal/_randomFormatIdnEmail.js +16 -2
  158. package/lib/internal/_randomFormatIdnEmail.js.map +1 -1
  159. package/lib/internal/_randomFormatIdnEmail.mjs +11 -2
  160. package/lib/internal/_randomFormatIdnEmail.mjs.map +1 -1
  161. package/lib/internal/_randomFormatIdnHostname.d.ts +2 -1
  162. package/lib/internal/_randomFormatIdnHostname.js +26 -1
  163. package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
  164. package/lib/internal/_randomFormatIdnHostname.mjs +25 -2
  165. package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
  166. package/lib/internal/_randomFormatIpv4.d.ts +2 -1
  167. package/lib/internal/_randomFormatIpv4.js +2 -1
  168. package/lib/internal/_randomFormatIpv4.js.map +1 -1
  169. package/lib/internal/_randomFormatIpv4.mjs +2 -1
  170. package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
  171. package/lib/internal/_randomFormatIpv6.d.ts +2 -1
  172. package/lib/internal/_randomFormatIpv6.js +2 -1
  173. package/lib/internal/_randomFormatIpv6.js.map +1 -1
  174. package/lib/internal/_randomFormatIpv6.mjs +2 -1
  175. package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
  176. package/lib/internal/_randomFormatIri.d.ts +2 -1
  177. package/lib/internal/_randomFormatIri.js +1 -1
  178. package/lib/internal/_randomFormatIri.js.map +1 -1
  179. package/lib/internal/_randomFormatIri.mjs +1 -1
  180. package/lib/internal/_randomFormatIri.mjs.map +1 -1
  181. package/lib/internal/_randomFormatIriReference.d.ts +2 -1
  182. package/lib/internal/_randomFormatIriReference.js +1 -1
  183. package/lib/internal/_randomFormatIriReference.js.map +1 -1
  184. package/lib/internal/_randomFormatIriReference.mjs +1 -1
  185. package/lib/internal/_randomFormatIriReference.mjs.map +1 -1
  186. package/lib/internal/_randomFormatJsonPointer.d.ts +2 -1
  187. package/lib/internal/_randomFormatJsonPointer.js +8 -1
  188. package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
  189. package/lib/internal/_randomFormatJsonPointer.mjs +5 -1
  190. package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
  191. package/lib/internal/_randomFormatPassword.d.ts +2 -1
  192. package/lib/internal/_randomFormatPassword.js +7 -5
  193. package/lib/internal/_randomFormatPassword.js.map +1 -1
  194. package/lib/internal/_randomFormatPassword.mjs +5 -1
  195. package/lib/internal/_randomFormatPassword.mjs.map +1 -1
  196. package/lib/internal/_randomFormatRegex.d.ts +2 -1
  197. package/lib/internal/_randomFormatRegex.js +2 -1
  198. package/lib/internal/_randomFormatRegex.js.map +1 -1
  199. package/lib/internal/_randomFormatRegex.mjs +2 -1
  200. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  201. package/lib/internal/_randomFormatRelativeJsonPointer.d.ts +2 -1
  202. package/lib/internal/_randomFormatRelativeJsonPointer.js +3 -2
  203. package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
  204. package/lib/internal/_randomFormatRelativeJsonPointer.mjs +3 -2
  205. package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
  206. package/lib/internal/_randomFormatTime.d.ts +2 -1
  207. package/lib/internal/_randomFormatTime.js +3 -2
  208. package/lib/internal/_randomFormatTime.js.map +1 -1
  209. package/lib/internal/_randomFormatTime.mjs +3 -2
  210. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  211. package/lib/internal/_randomFormatUri.d.ts +2 -1
  212. package/lib/internal/_randomFormatUri.js +1 -1
  213. package/lib/internal/_randomFormatUri.js.map +1 -1
  214. package/lib/internal/_randomFormatUri.mjs +1 -1
  215. package/lib/internal/_randomFormatUri.mjs.map +1 -1
  216. package/lib/internal/_randomFormatUriReference.d.ts +2 -1
  217. package/lib/internal/_randomFormatUriReference.js +1 -1
  218. package/lib/internal/_randomFormatUriReference.js.map +1 -1
  219. package/lib/internal/_randomFormatUriReference.mjs +1 -1
  220. package/lib/internal/_randomFormatUriReference.mjs.map +1 -1
  221. package/lib/internal/_randomFormatUriTemplate.d.ts +2 -1
  222. package/lib/internal/_randomFormatUriTemplate.js +1 -1
  223. package/lib/internal/_randomFormatUriTemplate.js.map +1 -1
  224. package/lib/internal/_randomFormatUriTemplate.mjs +1 -1
  225. package/lib/internal/_randomFormatUriTemplate.mjs.map +1 -1
  226. package/lib/internal/_randomFormatUrl.d.ts +2 -1
  227. package/lib/internal/_randomFormatUrl.js +21 -1
  228. package/lib/internal/_randomFormatUrl.js.map +1 -1
  229. package/lib/internal/_randomFormatUrl.mjs +18 -1
  230. package/lib/internal/_randomFormatUrl.mjs.map +1 -1
  231. package/lib/internal/_randomFormatUuid.d.ts +2 -1
  232. package/lib/internal/_randomFormatUuid.js +3 -2
  233. package/lib/internal/_randomFormatUuid.js.map +1 -1
  234. package/lib/internal/_randomFormatUuid.mjs +3 -2
  235. package/lib/internal/_randomFormatUuid.mjs.map +1 -1
  236. package/lib/internal/_randomInteger.js +59 -28
  237. package/lib/internal/_randomInteger.js.map +1 -1
  238. package/lib/internal/_randomInteger.mjs +56 -16
  239. package/lib/internal/_randomInteger.mjs.map +1 -1
  240. package/lib/internal/_randomMultiple.d.ts +8 -0
  241. package/lib/internal/_randomMultiple.js +168 -0
  242. package/lib/internal/_randomMultiple.js.map +1 -0
  243. package/lib/internal/_randomMultiple.mjs +158 -0
  244. package/lib/internal/_randomMultiple.mjs.map +1 -0
  245. package/lib/internal/_randomNumber.js +42 -42
  246. package/lib/internal/_randomNumber.js.map +1 -1
  247. package/lib/internal/_randomNumber.mjs +41 -27
  248. package/lib/internal/_randomNumber.mjs.map +1 -1
  249. package/lib/internal/_randomPattern.d.ts +2 -1
  250. package/lib/internal/_randomPattern.js +19 -4
  251. package/lib/internal/_randomPattern.js.map +1 -1
  252. package/lib/internal/_randomPattern.mjs +10 -4
  253. package/lib/internal/_randomPattern.mjs.map +1 -1
  254. package/lib/internal/_randomStringLength.d.ts +33 -0
  255. package/lib/internal/_randomStringLength.js +48 -0
  256. package/lib/internal/_randomStringLength.js.map +1 -0
  257. package/lib/internal/_randomStringLength.mjs +44 -0
  258. package/lib/internal/_randomStringLength.mjs.map +1 -0
  259. package/lib/internal/_stringLength.d.ts +1 -0
  260. package/lib/internal/_stringLength.js +11 -0
  261. package/lib/internal/_stringLength.js.map +1 -0
  262. package/lib/internal/_stringLength.mjs +10 -0
  263. package/lib/internal/_stringLength.mjs.map +1 -0
  264. package/lib/internal/_validateReport.js +4 -1
  265. package/lib/internal/_validateReport.js.map +1 -1
  266. package/lib/internal/_validateReport.mjs +2 -1
  267. package/lib/internal/_validateReport.mjs.map +1 -1
  268. package/lib/internal/private/__notationRename.d.ts +14 -0
  269. package/lib/internal/private/__notationRename.js +25 -0
  270. package/lib/internal/private/__notationRename.js.map +1 -0
  271. package/lib/internal/private/__notationRename.mjs +24 -0
  272. package/lib/internal/private/__notationRename.mjs.map +1 -0
  273. package/lib/json.d.ts +2 -2
  274. package/lib/json.mjs.map +1 -1
  275. package/lib/module.d.ts +2 -2
  276. package/lib/module.js.map +1 -1
  277. package/lib/module.mjs.map +1 -1
  278. package/lib/notations.d.ts +20 -4
  279. package/lib/notations.js.map +1 -1
  280. package/lib/notations.mjs.map +1 -1
  281. package/native/adapter/plugin_options.go +117 -0
  282. package/native/adapter/plugin_options_payload_matrix_test.go +181 -0
  283. package/native/cmd/ttsc-typia/any_array_type_tags_transform_test.go +63 -9
  284. package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +152 -0
  285. package/native/cmd/ttsc-typia/build.go +81 -64
  286. package/native/cmd/ttsc-typia/build_no_emit_preserves_analysis_options_test.go +67 -0
  287. package/native/cmd/ttsc-typia/build_no_emit_transform_diagnostics_test.go +138 -0
  288. package/native/cmd/ttsc-typia/build_plugin_options_come_from_payload_test.go +48 -0
  289. package/native/cmd/ttsc-typia/build_transactional_emit_success_test.go +81 -0
  290. package/native/cmd/ttsc-typia/build_transform_failure_atomicity_test.go +138 -0
  291. package/native/cmd/ttsc-typia/command_routes_and_diagnostics_coverage_test.go +3 -1
  292. package/native/cmd/ttsc-typia/compare_less_nan_transform_test.go +98 -0
  293. package/native/cmd/ttsc-typia/compare_native_object_overmatch_transform_test.go +161 -0
  294. package/native/cmd/ttsc-typia/compare_nondiscriminable_union_transform_test.go +343 -0
  295. package/native/cmd/ttsc-typia/compare_union_discrimination_transform_test.go +289 -0
  296. package/native/cmd/ttsc-typia/escaped_property_key_path_transform_test.go +193 -0
  297. package/native/cmd/ttsc-typia/finite_option_number_leaf_transform_test.go +240 -0
  298. package/native/cmd/ttsc-typia/functional_promised_type_transform_test.go +220 -0
  299. package/native/cmd/ttsc-typia/functional_receiver_transform_test.go +232 -0
  300. package/native/cmd/ttsc-typia/is_object_function_member_transform_test.go +205 -0
  301. package/native/cmd/ttsc-typia/json_application_alias_function_validation_transform_test.go +151 -0
  302. package/native/cmd/ttsc-typia/json_is_stringify_finite_number_transform_test.go +198 -0
  303. package/native/cmd/ttsc-typia/json_stringify_special_key_transform_test.go +238 -0
  304. package/native/cmd/ttsc-typia/main_wasm.go +21 -2
  305. package/native/cmd/ttsc-typia/native_collection_identity_is_transform_test.go +234 -0
  306. package/native/cmd/ttsc-typia/native_generic_name_guard_is_transform_test.go +194 -0
  307. package/native/cmd/ttsc-typia/native_name_collision_is_transform_test.go +204 -0
  308. package/native/cmd/ttsc-typia/non_trailing_rest_tuple_transform_test.go +23 -11
  309. package/native/cmd/ttsc-typia/notation_dynamic_keys_transform_test.go +286 -0
  310. package/native/cmd/ttsc-typia/notation_kebab_case_transform_test.go +1 -1
  311. package/native/cmd/ttsc-typia/notation_literal_collision_transform_test.go +164 -0
  312. package/native/cmd/ttsc-typia/notation_pascal_case_transform_test.go +230 -0
  313. package/native/cmd/ttsc-typia/notation_unicode_key_transform_test.go +309 -0
  314. package/native/cmd/ttsc-typia/pattern_line_terminator_escape_transform_test.go +224 -0
  315. package/native/cmd/ttsc-typia/plain_prune_union_object_overmatch_transform_test.go +219 -0
  316. package/native/cmd/ttsc-typia/plugin_options_payload_helpers_test.go +181 -0
  317. package/native/cmd/ttsc-typia/private_field_filter_is_transform_test.go +278 -0
  318. package/native/cmd/ttsc-typia/project_catalog_transform_coverage_test.go +73 -27
  319. package/native/cmd/ttsc-typia/project_dependencies_barrel_reexport_transform_test.go +120 -0
  320. package/native/cmd/ttsc-typia/project_dependencies_collapsed_alias_transform_test.go +134 -0
  321. package/native/cmd/ttsc-typia/project_dependencies_custom_lib_name_transform_test.go +135 -0
  322. package/native/cmd/ttsc-typia/project_dependencies_default_barrel_transform_test.go +114 -0
  323. package/native/cmd/ttsc-typia/project_dependencies_empty_heritage_transform_test.go +100 -0
  324. package/native/cmd/ttsc-typia/project_dependencies_envelope_transform_test.go +148 -0
  325. package/native/cmd/ttsc-typia/project_dependencies_index_signature_alias_transform_test.go +139 -0
  326. package/native/cmd/ttsc-typia/project_dependencies_local_reexport_transform_test.go +122 -0
  327. package/native/cmd/ttsc-typia/project_dependencies_signature_alias_transform_test.go +125 -0
  328. package/native/cmd/ttsc-typia/project_dependencies_star_barrel_transform_test.go +112 -0
  329. package/native/cmd/ttsc-typia/project_reference_graph_envelope_transform_test.go +190 -0
  330. package/native/cmd/ttsc-typia/protobuf_is_encode_finite_number_transform_test.go +98 -0
  331. package/native/cmd/ttsc-typia/protobuf_sequence_field_numbers_transform_test.go +52 -22
  332. package/native/cmd/ttsc-typia/symbol_key_member_filter_transform_test.go +279 -0
  333. package/native/cmd/ttsc-typia/template_interpolation_type_tags_transform_test.go +86 -23
  334. package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +3 -1
  335. package/native/cmd/ttsc-typia/transform.go +228 -39
  336. package/native/cmd/ttsc-typia/{transform_declaration_source_produces_no_js_test.go → transform_declaration_source_produces_no_javascript_test.go} +10 -2
  337. package/native/cmd/ttsc-typia/transform_fixtures_emit_coverage_test.go +21 -4
  338. package/native/cmd/ttsc-typia/transform_helpers_test.go +159 -1
  339. package/native/cmd/ttsc-typia/transform_plugin_options_come_from_payload_test.go +43 -0
  340. package/native/cmd/ttsc-typia/transform_single_file_failure_atomicity_test.go +114 -0
  341. package/native/cmd/ttsc-typia/transform_single_file_failure_writes_no_stdout_test.go +43 -0
  342. package/native/cmd/ttsc-typia/transform_single_file_js_distinguishes_same_basename_sources_test.go +81 -0
  343. package/native/cmd/ttsc-typia/transform_single_file_js_empty_emit_reports_no_output_test.go +100 -0
  344. package/native/cmd/ttsc-typia/transform_single_file_js_locates_output_across_layouts_test.go +160 -0
  345. package/native/cmd/ttsc-typia/transform_single_file_success_publishes_artifact_test.go +54 -0
  346. package/native/cmd/ttsc-typia/transform_wasm_host_argv_reports_diagnostics_test.go +39 -0
  347. package/native/cmd/ttsc-typia/tuple_optional_compare_clone_transform_test.go +227 -0
  348. package/native/core/factories/FormatCheatSheet.go +40 -7
  349. package/native/core/factories/IdentifierFactory.go +131 -4
  350. package/native/core/factories/MetadataCommentTagFactory.go +83 -40
  351. package/native/core/factories/MetadataTypeTagFactory.go +13 -1
  352. package/native/core/factories/NumericRangeFactory.go +60 -17
  353. package/native/core/factories/ProtobufFactory.go +7 -4
  354. package/native/core/factories/factory_utility_coverage_test.go +8 -2
  355. package/native/core/factories/format_alias_resolves_to_cheat_sheet_test.go +57 -0
  356. package/native/core/factories/format_alias_table_targets_the_cheat_sheet_test.go +44 -0
  357. package/native/core/factories/identifier_factory_postfix_escapes_every_key_test.go +147 -0
  358. package/native/core/factories/identifier_factory_postfix_survives_every_code_point_test.go +86 -0
  359. package/native/core/factories/internal/metadata/MetadataHelper.go +134 -7
  360. package/native/core/factories/internal/metadata/emplace_metadata_object.go +116 -8
  361. package/native/core/factories/internal/metadata/iterate_metadata.go +6 -0
  362. package/native/core/factories/internal/metadata/iterate_metadata_function.go +4 -11
  363. package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +8 -6
  364. package/native/core/factories/internal/metadata/iterate_metadata_map.go +9 -0
  365. package/native/core/factories/internal/metadata/iterate_metadata_native.go +27 -2
  366. package/native/core/factories/internal/metadata/iterate_metadata_set.go +9 -0
  367. package/native/core/factories/internal/metadata/js_doc_link_text_test.go +69 -0
  368. package/native/core/factories/internal/metadata/type_arguments_precondition_test.go +70 -0
  369. package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +39 -0
  370. package/native/core/factories/metadata_comment_tag_factory_exclusivity_matches_interface_test.go +84 -0
  371. package/native/core/factories/metadata_type_tag_factory_accepts_legal_tag_combinations_test.go +60 -0
  372. package/native/core/factories/metadata_type_tag_factory_declarations_test.go +86 -0
  373. package/native/core/factories/metadata_type_tag_factory_keeps_bool_form_exclusivity_test.go +38 -0
  374. package/native/core/factories/metadata_type_tag_factory_rejects_cross_kind_exclusive_tags_test.go +65 -0
  375. package/native/core/factories/metadata_type_tag_factory_rejects_duplicated_array_form_tags_test.go +41 -0
  376. package/native/core/factories/numeric_range_factory_enforces_64bit_bounds_test.go +69 -0
  377. package/native/core/factories/protobuf_recovery_ownership_test.go +64 -0
  378. package/native/core/programmers/IsProgrammer.go +15 -1
  379. package/native/core/programmers/RandomProgrammer.go +51 -14
  380. package/native/core/programmers/compare/CompareEqualProgrammer.go +393 -5
  381. package/native/core/programmers/compare/CompareLessProgrammer.go +4 -2
  382. package/native/core/programmers/functional/FunctionalAssertFunctionProgrammer.go +4 -6
  383. package/native/core/programmers/functional/FunctionalAssertParametersProgrammer.go +5 -13
  384. package/native/core/programmers/functional/FunctionalAssertReturnProgrammer.go +6 -14
  385. package/native/core/programmers/functional/FunctionalIsFunctionProgrammer.go +4 -6
  386. package/native/core/programmers/functional/FunctionalIsParametersProgrammer.go +49 -14
  387. package/native/core/programmers/functional/FunctionalIsReturnProgrammer.go +5 -13
  388. package/native/core/programmers/functional/FunctionalValidateFunctionProgrammer.go +4 -6
  389. package/native/core/programmers/functional/FunctionalValidateParametersProgrammer.go +5 -13
  390. package/native/core/programmers/functional/FunctionalValidateReturnProgrammer.go +5 -13
  391. package/native/core/programmers/functional/internal/FunctionalGeneralProgrammer.go +4 -17
  392. package/native/core/programmers/helpers/CloneJoiner.go +32 -0
  393. package/native/core/programmers/helpers/NotationJoiner.go +86 -28
  394. package/native/core/programmers/helpers/StringifyJoinder.go +32 -1
  395. package/native/core/programmers/helpers/UnionExplorer.go +203 -61
  396. package/native/core/programmers/helpers/joiner_branch_coverage_test.go +5 -3
  397. package/native/core/programmers/helpers/union_explorer_coverage_test.go +1 -1
  398. package/native/core/programmers/internal/CheckerProgrammer.go +100 -48
  399. package/native/core/programmers/iterate/check_template.go +344 -32
  400. package/native/core/programmers/iterate/json_schema_discriminator.go +36 -10
  401. package/native/core/programmers/iterate/json_schema_discriminator_declaration_syntax_test.go +205 -0
  402. package/native/core/programmers/iterate/openapi_v3_downgrader.go +641 -0
  403. package/native/core/programmers/iterate/openapi_v3_downgrader_boolean_default_test.go +95 -0
  404. package/native/core/programmers/iterate/openapi_v3_downgrader_test.go +123 -0
  405. package/native/core/programmers/iterate/template_interpolation_tags_test.go +40 -8
  406. package/native/core/programmers/iterate/template_runtime_pattern.go +52 -7
  407. package/native/core/programmers/json/JsonApplicationProgrammer.go +45 -11
  408. package/native/core/programmers/json/JsonSchemasProgrammer.go +12 -2
  409. package/native/core/programmers/llm/LlmApplicationProgrammer.go +12 -10
  410. package/native/core/programmers/llm/LlmSchemaProgrammer.go +23 -6
  411. package/native/core/programmers/llm/llm_reference_codec_test.go +24 -0
  412. package/native/core/programmers/notations/NotationGeneralProgrammer.go +183 -67
  413. package/native/core/programmers/notations/notation_general_helpers_test.go +1 -3
  414. package/native/core/programmers/notations/notation_general_programmer_pascal_multiword_test.go +72 -0
  415. package/native/core/programmers/notations/notation_general_programmer_underscore_boundary_test.go +68 -0
  416. package/native/core/programmers/plain/PlainClassifyProgrammer.go +23 -15
  417. package/native/core/programmers/plain/PlainCloneProgrammer.go +20 -7
  418. package/native/core/programmers/plain/PlainPruneProgrammer.go +19 -5
  419. package/native/core/programmers/plain/plain_tuple_seed_recovery_ownership_test.go +25 -0
  420. package/native/core/programmers/protobuf/ProtobufDecodeProgrammer.go +37 -28
  421. package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +40 -21
  422. package/native/core/programmers/protobuf/protobuf_programmer_helper_coverage_test.go +26 -0
  423. package/native/core/programmers/random_programmer_length_argument_test.go +53 -0
  424. package/native/core/schemas/metadata/MetadataCollection.go +270 -20
  425. package/native/core/schemas/metadata/MetadataDependency.go +388 -0
  426. package/native/core/schemas/metadata/MetadataObjectType.go +17 -4
  427. package/native/core/schemas/metadata/metadata_collection_generic_argument_dot_test.go +122 -0
  428. package/native/core/schemas/metadata/metadata_collection_name_allocation_test.go +147 -0
  429. package/native/core/schemas/metadata/metadata_collection_openapi_name_cascade_test.go +55 -0
  430. package/native/core/schemas/metadata/metadata_collection_openapi_name_test.go +68 -0
  431. package/native/core/utils/PatternUtil.go +13 -0
  432. package/native/core/utils/PromiseTypeFactory.go +59 -0
  433. package/native/core/utils/ProtobufNameEncoder.go +8 -0
  434. package/native/core/utils/promise_type_factory_semantics_test.go +118 -0
  435. package/native/go.mod +9 -1
  436. package/native/transform/CallExpressionTransformer.go +12 -0
  437. package/native/transform/features/json/JsonApplicationTransformer.go +1 -1
  438. package/native/transform/features/json/JsonSchemaTransformer.go +1 -1
  439. package/native/transform/features/json/JsonSchemasTransformer.go +5 -4
  440. package/package.json +16 -4
  441. package/src/executable/FileSystemIdentity.ts +189 -0
  442. package/src/executable/TypiaGenerateWizard.ts +377 -110
  443. package/src/functional.ts +30 -60
  444. package/src/internal/_ProtobufReader.ts +129 -43
  445. package/src/internal/_createStandardSchema.ts +15 -1
  446. package/src/internal/_decimal.ts +69 -0
  447. package/src/internal/_httpQueryParseURLSearchParams.ts +24 -2
  448. package/src/internal/_isFormatByte.ts +2 -5
  449. package/src/internal/_isFormatDate.ts +15 -2
  450. package/src/internal/_isFormatDateTime.ts +28 -2
  451. package/src/internal/_isFormatIri.ts +5 -2
  452. package/src/internal/_isFormatIriReference.ts +11 -3
  453. package/src/internal/_isFormatUriReference.ts +1 -1
  454. package/src/internal/_isMultipleOf.ts +8 -0
  455. package/src/internal/_isTypeFloat.ts +1 -1
  456. package/src/internal/_isTypeInt64.ts +1 -0
  457. package/src/internal/_isTypeInt64Bigint.ts +12 -0
  458. package/src/internal/_isTypeUint64.ts +1 -0
  459. package/src/internal/_isTypeUint64Bigint.ts +7 -0
  460. package/src/internal/_isUniqueItems.ts +134 -132
  461. package/src/internal/_notationAny.ts +9 -4
  462. package/src/internal/_notationAssign.ts +20 -0
  463. package/src/internal/_notationCamel.ts +31 -10
  464. package/src/internal/_notationKebab.ts +11 -0
  465. package/src/internal/_notationKeyCollision.ts +9 -0
  466. package/src/internal/_notationPascal.ts +19 -6
  467. package/src/internal/_notationSnake.ts +24 -21
  468. package/src/internal/_plainCloneAny.ts +208 -33
  469. package/src/internal/_randomArray.ts +13 -4
  470. package/src/internal/_randomFormatByte.ts +4 -1
  471. package/src/internal/_randomFormatDate.ts +17 -12
  472. package/src/internal/_randomFormatDatetime.ts +15 -10
  473. package/src/internal/_randomFormatDuration.ts +16 -14
  474. package/src/internal/_randomFormatEmail.ts +8 -2
  475. package/src/internal/_randomFormatHostname.ts +48 -1
  476. package/src/internal/_randomFormatIdnEmail.ts +18 -2
  477. package/src/internal/_randomFormatIdnHostname.ts +34 -2
  478. package/src/internal/_randomFormatIpv4.ts +3 -2
  479. package/src/internal/_randomFormatIpv6.ts +3 -2
  480. package/src/internal/_randomFormatIri.ts +3 -1
  481. package/src/internal/_randomFormatIriReference.ts +3 -1
  482. package/src/internal/_randomFormatJsonPointer.ts +8 -2
  483. package/src/internal/_randomFormatPassword.ts +11 -6
  484. package/src/internal/_randomFormatRegex.ts +4 -1
  485. package/src/internal/_randomFormatRelativeJsonPointer.ts +13 -6
  486. package/src/internal/_randomFormatTime.ts +13 -10
  487. package/src/internal/_randomFormatUri.ts +3 -1
  488. package/src/internal/_randomFormatUriReference.ts +3 -1
  489. package/src/internal/_randomFormatUriTemplate.ts +3 -1
  490. package/src/internal/_randomFormatUrl.ts +25 -2
  491. package/src/internal/_randomFormatUuid.ts +10 -6
  492. package/src/internal/_randomInteger.ts +87 -40
  493. package/src/internal/_randomMultiple.ts +245 -0
  494. package/src/internal/_randomNumber.ts +72 -55
  495. package/src/internal/_randomPattern.ts +26 -4
  496. package/src/internal/_randomStringLength.ts +72 -0
  497. package/src/internal/_stringLength.ts +5 -0
  498. package/src/internal/_validateReport.ts +5 -1
  499. package/src/internal/private/__notationRename.ts +24 -0
  500. package/src/json.ts +2 -2
  501. package/src/module.ts +4 -6
  502. package/src/notations.ts +20 -4
  503. package/lib/internal/private/__notationCapitalize.d.ts +0 -1
  504. package/lib/internal/private/__notationCapitalize.js +0 -6
  505. package/lib/internal/private/__notationCapitalize.js.map +0 -1
  506. package/lib/internal/private/__notationCapitalize.mjs +0 -6
  507. package/lib/internal/private/__notationCapitalize.mjs.map +0 -1
  508. package/lib/internal/private/__notationUnsnake.d.ts +0 -4
  509. package/lib/internal/private/__notationUnsnake.js +0 -26
  510. package/lib/internal/private/__notationUnsnake.js.map +0 -1
  511. package/lib/internal/private/__notationUnsnake.mjs +0 -15
  512. package/lib/internal/private/__notationUnsnake.mjs.map +0 -1
  513. package/native/cmd/ttsc-typia/plugin_options_missing_config_test.go +0 -26
  514. package/native/cmd/ttsc-typia/plugin_options_undefined_false_test.go +0 -36
  515. package/src/internal/private/__notationCapitalize.ts +0 -2
  516. package/src/internal/private/__notationUnsnake.ts +0 -24
@@ -3,6 +3,7 @@ package notations
3
3
  import (
4
4
  "fmt"
5
5
  "strings"
6
+ "unicode/utf8"
6
7
 
7
8
  shimast "github.com/microsoft/typescript-go/shim/ast"
8
9
  shimchecker "github.com/microsoft/typescript-go/shim/checker"
@@ -14,6 +15,8 @@ import (
14
15
  nativeinternal "github.com/samchon/typia/packages/typia/native/core/programmers/internal"
15
16
  nativeiterate "github.com/samchon/typia/packages/typia/native/core/programmers/iterate"
16
17
  schemametadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
18
+ "golang.org/x/text/cases"
19
+ "golang.org/x/text/language"
17
20
  )
18
21
 
19
22
  type notationGeneralProgrammerNamespace struct{}
@@ -1017,7 +1020,26 @@ func notationGeneralProgrammer_configure(props struct {
1017
1020
  },
1018
1021
  Joiner: func(next nativeinternal.FeatureProgrammer_ObjectorJoinerProps) *shimast.Node {
1019
1022
  return nativehelpers.NotationJoiner.Object(nativehelpers.NotationJoiner_ObjectProps{
1020
- Rename: props.Rename.Func,
1023
+ Rename: props.Rename.Func,
1024
+ DynamicRename: func() *shimast.Node {
1025
+ return notationGeneralProgrammer_internal(props.Context, "notation"+notationGeneralProgrammer_capitalize(props.Rename.Name))
1026
+ },
1027
+ DynamicAssign: func() *shimast.Node {
1028
+ return notationGeneralProgrammer_internal(props.Context, "notationAssign")
1029
+ },
1030
+ ThrowCollision: func(first string, second string, destination string) *shimast.Node {
1031
+ return f.NewCallExpression(
1032
+ notationGeneralProgrammer_internal(props.Context, "notationKeyCollision"),
1033
+ nil,
1034
+ nil,
1035
+ f.NewNodeList([]*shimast.Node{
1036
+ f.NewStringLiteral(first, shimast.TokenFlagsNone),
1037
+ f.NewStringLiteral(second, shimast.TokenFlagsNone),
1038
+ f.NewStringLiteral(destination, shimast.TokenFlagsNone),
1039
+ }),
1040
+ shimast.NodeFlagsNone,
1041
+ )
1042
+ },
1021
1043
  Input: next.Input,
1022
1044
  Entries: next.Entries,
1023
1045
  Emit: props.Context.Emit,
@@ -1320,51 +1342,154 @@ var NotationGeneralProgrammer_Pascal = NotationGeneralProgrammer_IRename{Name: "
1320
1342
  var NotationGeneralProgrammer_Snake = NotationGeneralProgrammer_IRename{Name: "snake", Func: notationGeneralProgrammer_snake}
1321
1343
  var NotationGeneralProgrammer_Kebab = NotationGeneralProgrammer_IRename{Name: "kebab", Func: notationGeneralProgrammer_kebab}
1322
1344
 
1323
- func notationGeneralProgrammer_camel(str string) string {
1324
- return notationGeneralProgrammer_unsnake(str, func(value string) string {
1325
- if value == "" {
1326
- return value
1327
- }
1328
- if value == strings.ToUpper(value) {
1329
- return strings.ToLower(value)
1330
- }
1331
- return strings.ToLower(value[:1]) + value[1:]
1332
- }, func(value string, index int) string {
1333
- if index == 0 {
1334
- return strings.ToLower(value)
1335
- }
1336
- return notationGeneralProgrammer_capitalize(strings.ToLower(value))
1337
- })
1345
+ // notationGeneralProgrammer_toUpper and notationGeneralProgrammer_toLower
1346
+ // reproduce JavaScript's `String.prototype.toUpperCase` / `toLowerCase`, which
1347
+ // is the case operation the runtime helpers (`_notationCamel`,
1348
+ // `_notationPascal`, `_notationSnake`) and the `CamelCase<T>` / `PascalCase<T>`
1349
+ // typings both apply. JavaScript performs Unicode *full* case conversion, while
1350
+ // `strings.ToUpper` / `strings.ToLower` perform the *simple* per-rune mapping,
1351
+ // so the two disagree wherever a code point maps to a different number of code
1352
+ // points or depends on context: `ß` -> `SS`, `İ` -> `i` + U+0307, `fi` -> `FI`,
1353
+ // and the word-final sigma `ΑΣ` -> `ας`. Emitting a key through the simple
1354
+ // mapping would make the compile-time emit disagree with the runtime helper and
1355
+ // with the declared `*Case<T>` return type. `language.Und` selects the
1356
+ // locale-independent root mapping, matching JavaScript's locale-independent
1357
+ // `toUpperCase` / `toLowerCase` (as opposed to `toLocaleUpperCase`).
1358
+ //
1359
+ // A `cases.Caser` carries mutable state and must not be shared across
1360
+ // goroutines, so each call builds its own; notation renaming runs once per
1361
+ // object key at compile time, not on a hot path.
1362
+ func notationGeneralProgrammer_toUpper(str string) string {
1363
+ return cases.Upper(language.Und).String(str)
1338
1364
  }
1339
1365
 
1340
- func notationGeneralProgrammer_pascal(str string) string {
1341
- return notationGeneralProgrammer_unsnake(str, func(value string) string {
1342
- if value == "" {
1343
- return value
1344
- }
1345
- return strings.ToUpper(value[:1]) + value[1:]
1346
- }, func(value string, index int) string {
1347
- return notationGeneralProgrammer_capitalize(value)
1348
- })
1366
+ func notationGeneralProgrammer_toLower(str string) string {
1367
+ return cases.Lower(language.Und).String(str)
1349
1368
  }
1350
1369
 
1351
- func notationGeneralProgrammer_snake(str string) string {
1352
- if str == "" {
1353
- return str
1370
+ // notationGeneralProgrammer_head splits str after the character a JavaScript
1371
+ // `str[0]` expression addresses, returning that head and the remainder.
1372
+ //
1373
+ // The runtime helpers and the `*Case<T>` typings capitalize a key by indexing
1374
+ // its first character, so the emit has to slice at the same boundary. Slicing
1375
+ // by byte (`str[:1]`) instead splits a multi-byte UTF-8 rune and hands a lone
1376
+ // lead byte to the case operation, which cannot decode it and substitutes
1377
+ // U+FFFD — `École` was emitted as `��cole`.
1378
+ func notationGeneralProgrammer_head(str string) (string, string) {
1379
+ _, size := utf8.DecodeRuneInString(str)
1380
+ return str[:size], str[size:]
1381
+ }
1382
+
1383
+ // notationGeneralProgrammer_upperHead and notationGeneralProgrammer_lowerHead
1384
+ // case-convert a head produced by notationGeneralProgrammer_head the way
1385
+ // `str[0].toUpperCase()` / `str[0].toLowerCase()` does.
1386
+ //
1387
+ // JavaScript indexes a string by UTF-16 code unit, so `str[0]` of an astral
1388
+ // character is its lone high surrogate, and no case mapping applies to an
1389
+ // unpaired surrogate. Such a head is therefore returned verbatim rather than
1390
+ // case-mapped, which is what keeps a Deseret or Adlam key stable across the
1391
+ // emit, the runtime helper, and the type.
1392
+ func notationGeneralProgrammer_upperHead(head string) string {
1393
+ if r, _ := utf8.DecodeRuneInString(head); r > 0xFFFF {
1394
+ return head
1395
+ }
1396
+ return notationGeneralProgrammer_toUpper(head)
1397
+ }
1398
+
1399
+ func notationGeneralProgrammer_lowerHead(head string) string {
1400
+ if r, _ := utf8.DecodeRuneInString(head); r > 0xFFFF {
1401
+ return head
1354
1402
  }
1403
+ return notationGeneralProgrammer_toLower(head)
1404
+ }
1405
+
1406
+ // notationGeneralProgrammer_rename is the shared outer walk for the
1407
+ // camel/pascal notations. It mirrors the `CamelCase<T>` / `PascalCase<T>`
1408
+ // typings: leading underscores are preserved verbatim, an all-underscore key
1409
+ // stays untouched, and the presence of any remaining underscore — not the
1410
+ // number of non-empty segments — selects the snake conversion. Routing on
1411
+ // underscore presence keeps a trailing or doubled underscore (`fooBar_`) on the
1412
+ // same path the type takes, instead of collapsing it to the plain path.
1413
+ func notationGeneralProgrammer_rename(str string, plain func(string) string, snake func(string) string) string {
1355
1414
  prefix := ""
1356
1415
  for len(str) != 0 && str[0] == '_' {
1357
1416
  prefix += "_"
1358
1417
  str = str[1:]
1359
1418
  }
1360
- out := func(value string) string { return prefix + value }
1361
- items := strings.Split(str, "_")
1362
- if len(items) > 1 {
1363
- for i, item := range items {
1364
- items[i] = strings.ToLower(item)
1419
+ if str == "" {
1420
+ return prefix
1421
+ }
1422
+ if strings.Contains(str, "_") {
1423
+ return prefix + snake(str)
1424
+ }
1425
+ return prefix + plain(str)
1426
+ }
1427
+
1428
+ func notationGeneralProgrammer_camel(str string) string {
1429
+ return notationGeneralProgrammer_rename(str, func(value string) string {
1430
+ if value == notationGeneralProgrammer_toUpper(value) {
1431
+ return notationGeneralProgrammer_toLower(value)
1365
1432
  }
1366
- return out(strings.Join(items, "_"))
1433
+ head, tail := notationGeneralProgrammer_head(value)
1434
+ return notationGeneralProgrammer_lowerHead(head) + tail
1435
+ }, notationGeneralProgrammer_camel_snake)
1436
+ }
1437
+
1438
+ // notationGeneralProgrammer_camel_snake mirrors `CamelizeSnakeString`: the
1439
+ // character after each underscore is uppercased and everything else lowercased.
1440
+ // A trailing underscore leaves no character to uppercase, so the whole key is
1441
+ // lowercased; a doubled underscore collapses to a single one before continuing.
1442
+ func notationGeneralProgrammer_camel_snake(str string) string {
1443
+ for len(str) != 0 && str[0] == '_' {
1444
+ str = str[1:]
1445
+ }
1446
+ if str == "" {
1447
+ return ""
1367
1448
  }
1449
+ index := strings.IndexByte(str, '_')
1450
+ if index < 0 || index+1 >= len(str) {
1451
+ return notationGeneralProgrammer_toLower(str)
1452
+ }
1453
+ if str[index+1] == '_' {
1454
+ return notationGeneralProgrammer_camel_snake(str[:index] + "_" + str[index+2:])
1455
+ }
1456
+ // The character after the underscore is one whole rune, not one byte; `_` is
1457
+ // ASCII so it never falls inside a multi-byte sequence and `index` stays a
1458
+ // valid boundary.
1459
+ middle, rest := notationGeneralProgrammer_head(str[index+1:])
1460
+ return notationGeneralProgrammer_toLower(str[:index]) + notationGeneralProgrammer_upperHead(middle) + notationGeneralProgrammer_camel_snake(rest)
1461
+ }
1462
+
1463
+ func notationGeneralProgrammer_pascal(str string) string {
1464
+ return notationGeneralProgrammer_rename(str, func(value string) string {
1465
+ head, tail := notationGeneralProgrammer_head(value)
1466
+ return notationGeneralProgrammer_upperHead(head) + tail
1467
+ }, notationGeneralProgrammer_pascal_snake)
1468
+ }
1469
+
1470
+ // notationGeneralProgrammer_pascal_snake mirrors `PascalizeSnakeString`: each
1471
+ // underscore-delimited segment is capitalized and its tail lowercased
1472
+ // (`MAX_COUNT` -> `MaxCount`), with a trailing underscore dropped.
1473
+ func notationGeneralProgrammer_pascal_snake(str string) string {
1474
+ for len(str) != 0 && str[0] == '_' {
1475
+ str = str[1:]
1476
+ }
1477
+ if str == "" {
1478
+ return ""
1479
+ }
1480
+ head, tail := notationGeneralProgrammer_head(str)
1481
+ index := strings.IndexByte(str, '_')
1482
+ if index < 0 {
1483
+ return notationGeneralProgrammer_upperHead(head) + notationGeneralProgrammer_toLower(tail)
1484
+ }
1485
+ // `index` counts bytes from the start of `str`; the tail it delimits starts
1486
+ // after the whole leading rune, hence the `len(head)` offset.
1487
+ return notationGeneralProgrammer_upperHead(head) + notationGeneralProgrammer_toLower(tail[:index-len(head)]) + notationGeneralProgrammer_pascal_snake(str[index+1:])
1488
+ }
1489
+
1490
+ // notationGeneralProgrammer_snake_word runs the case-boundary walk over one
1491
+ // underscore-free segment, inserting a separator at every camelCase boundary.
1492
+ func notationGeneralProgrammer_snake_word(str string) string {
1368
1493
  indexes := []int{}
1369
1494
  for i := 0; i < len(str); i++ {
1370
1495
  code := str[i]
@@ -1383,7 +1508,7 @@ func notationGeneralProgrammer_snake(str string) string {
1383
1508
  indexes = indexes[1:]
1384
1509
  }
1385
1510
  if len(indexes) == 0 {
1386
- return out(strings.ToLower(str))
1511
+ return notationGeneralProgrammer_toLower(str)
1387
1512
  }
1388
1513
  ret := ""
1389
1514
  for i, last := range indexes {
@@ -1391,11 +1516,31 @@ func notationGeneralProgrammer_snake(str string) string {
1391
1516
  if i != 0 {
1392
1517
  first = indexes[i-1]
1393
1518
  }
1394
- ret += strings.ToLower(str[first:last])
1519
+ ret += notationGeneralProgrammer_toLower(str[first:last])
1395
1520
  ret += "_"
1396
1521
  }
1397
- ret += strings.ToLower(str[indexes[len(indexes)-1]:])
1398
- return out(ret)
1522
+ ret += notationGeneralProgrammer_toLower(str[indexes[len(indexes)-1]:])
1523
+ return ret
1524
+ }
1525
+
1526
+ func notationGeneralProgrammer_snake(str string) string {
1527
+ if str == "" {
1528
+ return str
1529
+ }
1530
+ prefix := ""
1531
+ for len(str) != 0 && str[0] == '_' {
1532
+ prefix += "_"
1533
+ str = str[1:]
1534
+ }
1535
+ // Run the case-boundary walk within each underscore-delimited segment, not
1536
+ // over the whole segment at once. Lowercasing a segment atomically would drop
1537
+ // the camelCase boundary inside it (`fooBar_baz` -> `foobar_baz`), diverging
1538
+ // from `SnakeCase<T>`; the per-segment walk keeps it (`foo_bar_baz`).
1539
+ segments := strings.Split(str, "_")
1540
+ for i, segment := range segments {
1541
+ segments[i] = notationGeneralProgrammer_snake_word(segment)
1542
+ }
1543
+ return prefix + strings.Join(segments, "_")
1399
1544
  }
1400
1545
 
1401
1546
  // notationGeneralProgrammer_kebab derives the snake_case form first and then
@@ -1410,32 +1555,3 @@ func notationGeneralProgrammer_kebab(str string) string {
1410
1555
  }
1411
1556
  return prefix + strings.ReplaceAll(snaked, "_", "-")
1412
1557
  }
1413
-
1414
- func notationGeneralProgrammer_unsnake(str string, plain func(string) string, snake func(string, int) string) string {
1415
- prefix := ""
1416
- for len(str) != 0 && str[0] == '_' {
1417
- prefix += "_"
1418
- str = str[1:]
1419
- }
1420
- out := func(value string) string { return prefix + value }
1421
- if str == "" {
1422
- return out("")
1423
- }
1424
- raw := strings.Split(str, "_")
1425
- items := []string{}
1426
- for _, item := range raw {
1427
- if item != "" {
1428
- items = append(items, item)
1429
- }
1430
- }
1431
- if len(items) == 0 {
1432
- return out("")
1433
- }
1434
- if len(items) == 1 {
1435
- return out(plain(items[0]))
1436
- }
1437
- for i, item := range items {
1438
- items[i] = snake(item, i)
1439
- }
1440
- return out(strings.Join(items, ""))
1441
- }
@@ -43,9 +43,7 @@ func TestNotationGeneralHelpers(t *testing.T) {
43
43
  {NotationGeneralProgrammer_Snake.Func("helloWorldAgain"), "hello_world_again"},
44
44
  {NotationGeneralProgrammer_Snake.Func("XMLHttp"), "xmlhttp"},
45
45
  {NotationGeneralProgrammer_Snake.Func("__"), "__"},
46
- {notationGeneralProgrammer_unsnake("__", strings.ToLower, func(value string, _ int) string {
47
- return strings.ToUpper(value)
48
- }), "__"},
46
+ {notationGeneralProgrammer_rename("__", strings.ToLower, strings.ToUpper), "__"},
49
47
  }
50
48
  for _, c := range cases {
51
49
  if c.actual != c.expected {
@@ -0,0 +1,72 @@
1
+ package notations
2
+
3
+ import "testing"
4
+
5
+ // TestNotationGeneralProgrammerPascalMultiword verifies pascal tail lowercasing.
6
+ //
7
+ // Issue #2183: the pascal multi-word callback capitalized each word without
8
+ // first lowercasing its tail, so a word carrying uppercase inner characters
9
+ // (`MAX`, `HTTP`) kept them and `MAX_COUNT` emitted `MAXCOUNT`. That diverged
10
+ // from the runtime `_notationPascal` helper (`__notationCapitalize` = upper
11
+ // first character, lowercase the rest) and from the declared `PascalCase<T>`
12
+ // type, leaving `.MaxCount` undefined on the compile-time result. The sibling
13
+ // `camel` callback already lowercased the tail, so pascal was the sole outlier.
14
+ // The single-word `plain` path (`userID` -> `UserID`, `ID` -> `ID`, tail kept)
15
+ // must stay untouched, because single words are dispatched to `plain` rather
16
+ // than the multi-word callback.
17
+ //
18
+ // 1. Pascalize multi-word keys whose non-leading words carry uppercase or
19
+ // mixed-case characters, plus digits and a leading underscore, and match
20
+ // the `PascalCase<T>` / `_notationPascal` oracle.
21
+ // 2. Confirm single-word keys still route through `plain` unchanged.
22
+ // 3. Confirm camel, snake, and kebab of the same keys are unaffected.
23
+ func TestNotationGeneralProgrammerPascalMultiword(t *testing.T) {
24
+ pascal := []struct{ input, expected string }{
25
+ // Multi-word: every word becomes upper-first + lower-rest, byte-equal to
26
+ // `_notationPascal` and assignable to `PascalCase<T>`.
27
+ {"MAX_COUNT", "MaxCount"},
28
+ {"HTTP_PORT", "HttpPort"},
29
+ {"USER_ID", "UserId"},
30
+ {"user_name", "UserName"},
31
+ {"fooBar_baz", "FoobarBaz"},
32
+ {"HTTP2_PORT", "Http2Port"},
33
+ {"MAX_COUNT_2", "MaxCount2"},
34
+ {"_MAX_COUNT", "_MaxCount"},
35
+ {"a_b_c", "ABC"},
36
+ // Single word: routed through `plain`, tail preserved — unchanged by the fix.
37
+ {"userID", "UserID"},
38
+ {"ID", "ID"},
39
+ {"MAX", "MAX"},
40
+ {"html5Parser", "Html5Parser"},
41
+ {"FirstName", "FirstName"},
42
+ {"_internal", "_Internal"},
43
+ {"XMLParser", "XMLParser"},
44
+ }
45
+ for _, c := range pascal {
46
+ if actual := NotationGeneralProgrammer_Pascal.Func(c.input); actual != c.expected {
47
+ t.Errorf("pascal(%q) == %q, expected %q", c.input, actual, c.expected)
48
+ }
49
+ }
50
+
51
+ // The fix touches pascal only; camel/snake/kebab of the same multi-word
52
+ // witnesses already lowercased the tail and must stay byte-for-byte the same.
53
+ siblings := []struct {
54
+ input, camel, snake, kebab string
55
+ }{
56
+ {"MAX_COUNT", "maxCount", "max_count", "max-count"},
57
+ {"HTTP_PORT", "httpPort", "http_port", "http-port"},
58
+ {"USER_ID", "userId", "user_id", "user-id"},
59
+ {"_MAX_COUNT", "_maxCount", "_max_count", "_max-count"},
60
+ }
61
+ for _, c := range siblings {
62
+ if actual := NotationGeneralProgrammer_Camel.Func(c.input); actual != c.camel {
63
+ t.Errorf("camel(%q) == %q, expected %q", c.input, actual, c.camel)
64
+ }
65
+ if actual := NotationGeneralProgrammer_Snake.Func(c.input); actual != c.snake {
66
+ t.Errorf("snake(%q) == %q, expected %q", c.input, actual, c.snake)
67
+ }
68
+ if actual := NotationGeneralProgrammer_Kebab.Func(c.input); actual != c.kebab {
69
+ t.Errorf("kebab(%q) == %q, expected %q", c.input, actual, c.kebab)
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,68 @@
1
+ package notations
2
+
3
+ import "testing"
4
+
5
+ // TestNotationGeneralProgrammerUnderscoreBoundary pins the snake/kebab/camel/
6
+ // pascal compile-time emit against the `SnakeCase`/`KebabCase`/`CamelCase`/
7
+ // `PascalCase` type oracle on keys that mix an underscore with a case boundary.
8
+ //
9
+ // Issue #2190: when a key combined an internal or trailing underscore with a
10
+ // camelCase boundary, `snake`/`kebab` lowercased each underscore-delimited
11
+ // segment atomically (`fooBar_baz` -> `foobar_baz`) instead of walking the case
12
+ // boundary inside the segment, and `camel`/`pascal` collapsed a trailing
13
+ // underscore onto the underscore-free path (`fooBar_` -> `FooBar`). Both
14
+ // disagreed with the declared `*Case<T>` type, so reading the declared key was
15
+ // `undefined`. The expected values below are the type-oracle output, obtained by
16
+ // revealing `keyof *Case<{ key: 1 }>` through the compiler.
17
+ //
18
+ // 1. Convert the underscore+case-boundary witnesses under every notation.
19
+ // 2. Assert each equals the `*Case<T>` value byte for byte.
20
+ // 3. Re-cover underscore-free and all-caps-segment keys so the boundary walk
21
+ // did not regress them (`userID`, `XMLParser`, `MAX_COUNT`, #2186's pascal).
22
+ func TestNotationGeneralProgrammerUnderscoreBoundary(t *testing.T) {
23
+ type row struct {
24
+ input string
25
+ snake string
26
+ kebab string
27
+ camel string
28
+ pascal string
29
+ }
30
+ rows := []row{
31
+ // issue matrix
32
+ {"fooBar_baz", "foo_bar_baz", "foo-bar-baz", "foobarBaz", "FoobarBaz"},
33
+ {"openAI_key", "open_ai_key", "open-ai-key", "openaiKey", "OpenaiKey"},
34
+ {"HTTP_fooBar", "http_foo_bar", "http-foo-bar", "httpFoobar", "HttpFoobar"},
35
+ {"fooBar", "foo_bar", "foo-bar", "fooBar", "FooBar"},
36
+ {"fooBar_", "foo_bar_", "foo-bar-", "foobar_", "Foobar"},
37
+ {"_fooBar", "_foo_bar", "_foo-bar", "_fooBar", "_FooBar"},
38
+ {"userID", "user_id", "user-id", "userID", "UserID"},
39
+ {"a_b_c", "a_b_c", "a-b-c", "aBc", "ABC"},
40
+ {"MAX_COUNT", "max_count", "max-count", "maxCount", "MaxCount"},
41
+ // boundary edges
42
+ {"_fooBar_", "_foo_bar_", "_foo-bar-", "_foobar_", "_Foobar"},
43
+ {"fooBarBaz_", "foo_bar_baz_", "foo-bar-baz-", "foobarbaz_", "Foobarbaz"},
44
+ {"foo__bar", "foo__bar", "foo--bar", "fooBar", "FooBar"},
45
+ {"userID_", "user_id_", "user-id-", "userid_", "Userid"},
46
+ {"HTTP_", "http_", "http-", "http_", "Http"},
47
+ // regressions that must stay unchanged (no underscore / all-caps segment)
48
+ {"XMLParser", "xmlparser", "xmlparser", "xMLParser", "XMLParser"},
49
+ {"toHTML", "to_html", "to-html", "toHTML", "ToHTML"},
50
+ {"html5Parser", "html5_parser", "html5-parser", "html5Parser", "Html5Parser"},
51
+ {"iOS", "i_os", "i-os", "iOS", "IOS"},
52
+ {"HTTP_PORT", "http_port", "http-port", "httpPort", "HttpPort"},
53
+ }
54
+ for _, c := range rows {
55
+ if actual := NotationGeneralProgrammer_Snake.Func(c.input); actual != c.snake {
56
+ t.Errorf("snake(%q) == %q, expected %q", c.input, actual, c.snake)
57
+ }
58
+ if actual := NotationGeneralProgrammer_Kebab.Func(c.input); actual != c.kebab {
59
+ t.Errorf("kebab(%q) == %q, expected %q", c.input, actual, c.kebab)
60
+ }
61
+ if actual := NotationGeneralProgrammer_Camel.Func(c.input); actual != c.camel {
62
+ t.Errorf("camel(%q) == %q, expected %q", c.input, actual, c.camel)
63
+ }
64
+ if actual := NotationGeneralProgrammer_Pascal.Func(c.input); actual != c.pascal {
65
+ t.Errorf("pascal(%q) == %q, expected %q", c.input, actual, c.pascal)
66
+ }
67
+ }
68
+ }
@@ -571,7 +571,7 @@ func plainClassifyProgrammer_decode_tuple_inline(props plainClassifyProgrammer_d
571
571
  explore := props.Explore
572
572
  explore.From = "array"
573
573
  explore.Postfix = postfix
574
- elements = append(elements, plainClassifyProgrammer_decode(struct {
574
+ value := plainClassifyProgrammer_decode(struct {
575
575
  Context nativecontext.ITypiaContext
576
576
  Config nativeinternal.FeatureProgrammer_IConfig
577
577
  Functor *nativehelpers.FunctionProgrammer
@@ -585,7 +585,18 @@ func plainClassifyProgrammer_decode_tuple_inline(props plainClassifyProgrammer_d
585
585
  Input: f.NewElementAccessExpression(props.Input, nil, nativefactories.ExpressionFactory.Number(index, props.Context.Emit), shimast.NodeFlagsNone),
586
586
  Metadata: elem,
587
587
  Explore: explore,
588
- }))
588
+ })
589
+ if elem.Optional {
590
+ // An omitted optional trailing element must not become a phantom
591
+ // `undefined`; gate it on presence so `classify(["a"])` stays `["a"]`.
592
+ value = nativehelpers.CloneJoiner.OptionalTupleElement(nativehelpers.CloneJoiner_OptionalElementProps{
593
+ Input: props.Input,
594
+ Value: value,
595
+ Index: index,
596
+ Emit: props.Context.Emit,
597
+ })
598
+ }
599
+ elements = append(elements, value)
589
600
  }
590
601
  var rest *shimast.Node
591
602
  if len(props.Tuple.Elements) != 0 {
@@ -631,7 +642,7 @@ func plainClassifyProgrammer_decode_native(props struct {
631
642
  }) *shimast.Node {
632
643
  f := nativecontext.EmitFactoryOf(plainClassifyProgrammer_factory, props.Context.Emit)
633
644
  switch props.Type {
634
- case "Date", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "BigUint64Array", "Int8Array", "Int16Array", "Int32Array", "BigInt64Array", "Float32Array", "Float64Array", "RegExp":
645
+ case "Date", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "BigUint64Array", "Int8Array", "Int16Array", "Int32Array", "BigInt64Array", "Float32Array", "Float64Array":
635
646
  return f.NewNewExpression(
636
647
  f.NewIdentifier(props.Type),
637
648
  nil,
@@ -639,11 +650,13 @@ func plainClassifyProgrammer_decode_native(props struct {
639
650
  )
640
651
  case "ArrayBuffer", "SharedArrayBuffer":
641
652
  return plainClassifyProgrammer_decode_native_buffer(props.Type, props.Input, props.Context.Emit)
642
- case "DataView":
643
- return f.NewNewExpression(
644
- f.NewIdentifier("DataView"),
653
+ case "DataView", "Blob", "File", "RegExp":
654
+ return f.NewCallExpression(
655
+ plainClassifyProgrammer_internal(props.Context, "plainCloneAny"),
656
+ nil,
645
657
  nil,
646
- f.NewNodeList([]*shimast.Node{nativefactories.IdentifierFactory.Access(props.Context.Emit, props.Input, "buffer")}),
658
+ f.NewNodeList([]*shimast.Node{props.Input}),
659
+ shimast.NodeFlagsNone,
647
660
  )
648
661
  default:
649
662
  return f.NewCallExpression(
@@ -1571,14 +1584,9 @@ func plainClassifyProgrammer_seed_type(checker *shimchecker.Checker, sig *shimch
1571
1584
  // the tuple is rejected (nil = field-copy) when it is empty or any element after
1572
1585
  // index 0 is REQUIRED — then `[] extends Rest` fails and ClassifiableSeed is
1573
1586
  // `never`. GetTypeArguments / TargetTupleType require an object reference; the
1574
- // IsTupleType caller guarantees that, but a recover degrades a surprise panic to
1575
- // field-copy (the same safe fallback as a failed seed analysis).
1576
- func plainClassifyProgrammer_tuple_seed(checker *shimchecker.Checker, restParamT *shimchecker.Type) (seed *shimchecker.Type) {
1577
- defer func() {
1578
- if recover() != nil {
1579
- seed = nil
1580
- }
1581
- }()
1587
+ // IsTupleType caller guarantees that capability. Any failure after that
1588
+ // precondition is an internal invariant violation and remains observable.
1589
+ func plainClassifyProgrammer_tuple_seed(checker *shimchecker.Checker, restParamT *shimchecker.Type) *shimchecker.Type {
1582
1590
  args := checker.GetTypeArguments(restParamT)
1583
1591
  if len(args) == 0 {
1584
1592
  return nil // `[]` -> ClassifiableSeed is never -> field-copy
@@ -531,7 +531,7 @@ func plainCloneProgrammer_decode_tuple_inline(props plainCloneProgrammer_decodeT
531
531
  explore := props.Explore
532
532
  explore.From = "array"
533
533
  explore.Postfix = postfix
534
- elements = append(elements, plainCloneProgrammer_decode(struct {
534
+ value := plainCloneProgrammer_decode(struct {
535
535
  Context nativecontext.ITypiaContext
536
536
  Config nativeinternal.FeatureProgrammer_IConfig
537
537
  Functor *nativehelpers.FunctionProgrammer
@@ -545,7 +545,18 @@ func plainCloneProgrammer_decode_tuple_inline(props plainCloneProgrammer_decodeT
545
545
  Input: f.NewElementAccessExpression(props.Input, nil, nativefactories.ExpressionFactory.Number(index, props.Context.Emit), shimast.NodeFlagsNone),
546
546
  Metadata: elem,
547
547
  Explore: explore,
548
- }))
548
+ })
549
+ if elem.Optional {
550
+ // An omitted optional trailing element must not become a phantom
551
+ // `undefined`; gate it on presence so `clone(["a"])` stays `["a"]`.
552
+ value = nativehelpers.CloneJoiner.OptionalTupleElement(nativehelpers.CloneJoiner_OptionalElementProps{
553
+ Input: props.Input,
554
+ Value: value,
555
+ Index: index,
556
+ Emit: props.Context.Emit,
557
+ })
558
+ }
559
+ elements = append(elements, value)
549
560
  }
550
561
  var rest *shimast.Node
551
562
  if len(props.Tuple.Elements) != 0 {
@@ -591,7 +602,7 @@ func plainCloneProgrammer_decode_native(props struct {
591
602
  }) *shimast.Node {
592
603
  f := nativecontext.EmitFactoryOf(plainCloneProgrammer_factory, props.Context.Emit)
593
604
  switch props.Type {
594
- case "Date", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "BigUint64Array", "Int8Array", "Int16Array", "Int32Array", "BigInt64Array", "Float32Array", "Float64Array", "RegExp":
605
+ case "Date", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "BigUint64Array", "Int8Array", "Int16Array", "Int32Array", "BigInt64Array", "Float32Array", "Float64Array":
595
606
  return f.NewNewExpression(
596
607
  f.NewIdentifier(props.Type),
597
608
  nil,
@@ -599,11 +610,13 @@ func plainCloneProgrammer_decode_native(props struct {
599
610
  )
600
611
  case "ArrayBuffer", "SharedArrayBuffer":
601
612
  return plainCloneProgrammer_decode_native_buffer(props.Type, props.Input, props.Context.Emit)
602
- case "DataView":
603
- return f.NewNewExpression(
604
- f.NewIdentifier("DataView"),
613
+ case "DataView", "Blob", "File", "RegExp":
614
+ return f.NewCallExpression(
615
+ plainCloneProgrammer_internal(props.Context, "plainCloneAny"),
616
+ nil,
605
617
  nil,
606
- f.NewNodeList([]*shimast.Node{nativefactories.IdentifierFactory.Access(props.Context.Emit, props.Input, "buffer")}),
618
+ f.NewNodeList([]*shimast.Node{props.Input}),
619
+ shimast.NodeFlagsNone,
607
620
  )
608
621
  default:
609
622
  return f.NewCallExpression(
@@ -313,13 +313,27 @@ func plainPruneProgrammer_decode(props struct {
313
313
  })
314
314
  }
315
315
 
316
- statements := make([]*shimast.Node, 0, len(unions))
317
- for _, u := range unions {
318
- statements = append(statements, f.NewIfStatement(
316
+ // Compose the arms as a mutually exclusive `if / else if` ladder rather than
317
+ // independent `if`s. The object arm is appended last and its guard is
318
+ // `IsObject` with CheckArray:false, which also matches arrays and native
319
+ // instances; with independent `if`s an array or native runs both its own arm
320
+ // and the object arm, and the object arm then deletes the keys of a value
321
+ // another arm already owns (a typed array throws, a plain array collapses to
322
+ // holes, a native loses its own properties). The ladder reaches the object
323
+ // arm only when every earlier arm missed, so each input is pruned by exactly
324
+ // one arm — the same shape clone/classify use.
325
+ var chain *shimast.Node
326
+ for i := len(unions) - 1; i >= 0; i-- {
327
+ u := unions[i]
328
+ chain = f.NewIfStatement(
319
329
  u.Is(),
320
330
  plainPruneProgrammer_to_statement(u.Value(), props.Context.Emit),
321
- nil,
322
- ))
331
+ chain,
332
+ )
333
+ }
334
+ statements := []*shimast.Node{}
335
+ if chain != nil {
336
+ statements = append(statements, chain)
323
337
  }
324
338
  return f.NewBlock(f.NewNodeList(statements), true)
325
339
  }
@@ -0,0 +1,25 @@
1
+ package plain
2
+
3
+ import (
4
+ "testing"
5
+
6
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
7
+ )
8
+
9
+ // TestPlainTupleSeedRecoveryOwnership verifies impossible checker state panics.
10
+ //
11
+ // The caller proves tuple ownership before extracting a tuple seed. A missing
12
+ // checker is therefore an invariant violation, not an ordinary field-copy
13
+ // fallback, and must remain observable.
14
+ //
15
+ // 1. Supply a tuple-seed type with no owning checker.
16
+ // 2. Invoke the ownership-only tuple seed helper.
17
+ // 3. Require the checker invariant panic to escape.
18
+ func TestPlainTupleSeedRecoveryOwnership(t *testing.T) {
19
+ defer func() {
20
+ if recover() == nil {
21
+ t.Fatal("unexpected tuple seed panic was swallowed")
22
+ }
23
+ }()
24
+ _ = plainClassifyProgrammer_tuple_seed(nil, &shimchecker.Type{})
25
+ }