From 140440b9735ba73553b63fa08f3414e41bb87b3b Mon Sep 17 00:00:00 2001 From: Florian Hammerschmidt Date: Wed, 10 Sep 2025 00:44:23 +0200 Subject: [PATCH 1/3] Playground toggles for jsx preserve and experimental features --- src/Playground.res | 131 ++++++++++++++++++++++---- src/bindings/RescriptCompilerApi.res | 15 ++- src/bindings/RescriptCompilerApi.resi | 4 + src/common/CompilerManagerHook.res | 43 +++++++-- src/common/CompilerManagerHook.resi | 10 ++ 5 files changed, 176 insertions(+), 27 deletions(-) diff --git a/src/Playground.res b/src/Playground.res index b11f75250..c89667e68 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -13,6 +13,38 @@ module Api = RescriptCompilerApi type layout = Column | Row type tab = JavaScript | Output | Problems | Settings + +module JsxCompilation = { + type t = + | Plain + | PreserveJsx + + let getLabel = (mode: t): string => + switch mode { + | Plain => "Plain JS functions" + | PreserveJsx => "Preserve JSX" + } + + let toBool = (mode: t): bool => + switch mode { + | Plain => false + | PreserveJsx => true + } + + let fromBool = (bool): t => bool ? PreserveJsx : Plain +} + +module ExperimentalFeatures = { + type t = LetUnwrap + + let getLabel = (feature: t): string => + switch feature { + | LetUnwrap => "let?" + } + + let list = [LetUnwrap] +} + let breakingPoint = 1024 module DropdownSelect = { @@ -31,23 +63,23 @@ module DropdownSelect = { } } -module ToggleSelection = { - module SelectionOption = { - @react.component - let make = (~label, ~isActive, ~disabled, ~onClick) => { - - } +module SelectionOption = { + @react.component + let make = (~label, ~isActive, ~disabled, ~onClick) => { + } +} +module ToggleSelection = { @react.component let make = ( ~onChange: 'a => unit, @@ -867,6 +899,25 @@ module Settings = { setConfig(config) } + let onJsxPreserveModeUpdate = compilation => { + let jsx_preserve_mode = JsxCompilation.toBool(compilation) + let config = {...config, jsx_preserve_mode} + setConfig(config) + } + + let onExperimentalFeaturesUpdate = feature => { + let features = config.experimental_features->Option.getOr([]) + + let experimental_features = if features->Array.includes(feature) { + features->Array.filter(x => x !== feature) + } else { + [...features, feature] + } + + let config = {...config, experimental_features} + setConfig(config) + } + let warnFlagTokens = WarningFlagDescription.Parser.parse(warn_flags)->Result.getOr([]) let onWarningFlagsResetClick = _evt => { @@ -1000,6 +1051,40 @@ module Settings = { onChange=onModuleSystemUpdate /> + {switch readyState.selected.apiVersion { + | V1 | V2 | V3 | V4 | V5 | UnknownVersion(_) => React.null + | V6 => + <> +
+
{React.string("JSX")}
+ Option.getOr(false)->JsxCompilation.fromBool} + onChange=onJsxPreserveModeUpdate + /> +
+
+
{React.string("Experimental Features")}
+ {ExperimentalFeatures.list + ->Array.map(feature => { + let key = (feature :> string) + + ExperimentalFeatures.getLabel} + isActive={config.experimental_features + ->Option.getOr([]) + ->Array.includes(key)} + onClick={_evt => onExperimentalFeaturesUpdate(key)} + /> + }) + ->React.array} +
+ + }} +
{React.string("Loaded Libraries")}
- {switch readyState.selected.apiVersion { - | V1 | V2 | V3 | V4 | V5 | UnknownVersion(_) => React.null - | V6 => - <> -
-
{React.string("JSX")}
- Option.getOr(false)->JsxCompilation.fromBool} - onChange=onJsxPreserveModeUpdate - /> -
-
-
{React.string("Experimental Features")}
- {ExperimentalFeatures.list - ->Array.map(feature => { - let key = (feature :> string) - - ExperimentalFeatures.getLabel} - isActive={config.experimental_features - ->Option.getOr([]) - ->Array.includes(key)} - onClick={_evt => onExperimentalFeaturesUpdate(key)} + {readyState.selected.apiVersion->RescriptCompilerApi.Version.isMinimumVersion(V6) + ? <> +
+
{React.string("JSX")}
+ Option.getOr(false)->JsxCompilation.fromBool} + onChange=onJsxPreserveModeUpdate /> - }) - ->React.array} -
- - }} +
+
+
{React.string("Experimental Features")}
+ {ExperimentalFeatures.list + ->Array.map(feature => { + let key = (feature :> string) + + ExperimentalFeatures.getLabel} + isActive={config.experimentalFeatures + ->Option.getOr([]) + ->Array.includes(key)} + onClick={_evt => onExperimentalFeaturesUpdate(key)} + /> + }) + ->React.array} +
+ + : React.null}
{React.string("Loaded Libraries")}
diff --git a/src/bindings/RescriptCompilerApi.res b/src/bindings/RescriptCompilerApi.res index 48fcdf1e4..66b8dcca5 100644 --- a/src/bindings/RescriptCompilerApi.res +++ b/src/bindings/RescriptCompilerApi.res @@ -28,13 +28,16 @@ module Lang = { } module Version = { + type numbered = + | @as(1) V1 + | @as(2) V2 + | @as(3) V3 + | @as(4) V4 + | @as(5) V5 + | @as(6) V6 + type t = - | V1 - | V2 - | V3 - | V4 - | V5 - | V6 + | ...numbered | UnknownVersion(string) // Helps finding the right API version @@ -81,6 +84,12 @@ module Version = { | V2 | V3 | V4 | V5 | V6 => [Lang.Res] | UnknownVersion(_) => [Res] } + + let isMinimumVersion = (version: t, minimum: numbered) => + switch version { + | ...numbered as version => version >= minimum + | UnknownVersion(_) => false + } } module LocMsg = { @@ -478,19 +487,25 @@ module Compiler = { @send external setJsxPreserveMode: (t, bool) => bool = "setJsxPreserveMode" - let setConfig = (t: t, config: Config.t): unit => { - let moduleSystem = switch config.module_system { + let setConfig = (t: t, config: Config.t, version: Version.t): unit => { + let moduleSystem = switch config.moduleSystem { | "commonjs" => #nodejs->Some | "esmodule" => #es6->Some | _ => None } Option.forEach(moduleSystem, moduleSystem => t->setModuleSystem(moduleSystem)->ignore) - Option.forEach(config.openModules, modules => t->setOpenModules(modules)->ignore) - Option.forEach(config.experimentalFeatures, features => - t->setExperimentalFeatures(features)->ignore - ) - Option.forEach(config.jsxPreserveMode, toggle => t->setJsxPreserveMode(toggle)->ignore) + + if version->Version.isMinimumVersion(V4) { + Option.forEach(config.openModules, modules => t->setOpenModules(modules)->ignore) + } + + if version->Version.isMinimumVersion(V6) { + Option.forEach(config.experimentalFeatures, features => + t->setExperimentalFeatures(features)->ignore + ) + Option.forEach(config.jsxPreserveMode, toggle => t->setJsxPreserveMode(toggle)->ignore) + } t->setWarnFlags(config.warnFlags)->ignore } diff --git a/src/bindings/RescriptCompilerApi.resi b/src/bindings/RescriptCompilerApi.resi index 25f57ef88..3d17b4193 100644 --- a/src/bindings/RescriptCompilerApi.resi +++ b/src/bindings/RescriptCompilerApi.resi @@ -19,13 +19,16 @@ module Lang: { } module Version: { + type numbered = + | @as(1) V1 + | @as(2) V2 + | @as(3) V3 + | @as(4) V4 + | @as(5) V5 + | @as(6) V6 + type t = - | V1 - | V2 - | V3 - | V4 - | V5 - | V6 + | ...numbered | UnknownVersion(string) // Helps finding the right API version @@ -36,6 +39,8 @@ module Version: { let defaultTargetLang: Lang.t let availableLanguages: t => array + + let isMinimumVersion: (t, numbered) => bool } module LocMsg: { @@ -205,7 +210,7 @@ module Compiler: { let setWarnFlags: (t, string) => bool let setOpenModules: (t, array) => bool - let setConfig: (t, Config.t) => unit + let setConfig: (t, Config.t, Version.t) => unit // General format function let convertSyntax: (~fromLang: Lang.t, ~toLang: Lang.t, ~code: string, t) => ConversionResult.t diff --git a/src/common/CompilerManagerHook.res b/src/common/CompilerManagerHook.res index 88dd8df47..d5a4e2176 100644 --- a/src/common/CompilerManagerHook.res +++ b/src/common/CompilerManagerHook.res @@ -269,7 +269,7 @@ let useCompilerManager = ( | UpdateConfig(config) => switch state { | Ready(ready) => - ready.selected.instance->Compiler.setConfig(config) + ready.selected.instance->Compiler.setConfig(config, ready.selected.apiVersion) let selected = {...ready.selected, config} Compiling({state: {...ready, selected}, previousJsCode: None}) | _ => state @@ -450,7 +450,8 @@ let useCompilerManager = ( jsxPreserveMode: initialJsxPreserveMode, ?openModules, } - instance->Compiler.setConfig(config) + + instance->Compiler.setConfig(config, apiVersion) let selected = { id: version, @@ -510,7 +511,8 @@ let useCompilerManager = ( moduleSystem: defaultModuleSystem, ?openModules, } - instance->Compiler.setConfig(config) + + instance->Compiler.setConfig(config, apiVersion) let selected = { id: version,