diff --git a/CHANGELOG.md b/CHANGELOG.md
index 73ce10beba..6fa0a8475e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@
#### :rocket: New Feature
- Support renaming fields in inline records with `@as` attribute. [#6391](https://github.com/rescript-lang/rescript-compiler/pull/6391)
+- Support renaming object fields of `@obj` external ppx with `@as` attribute. [#6391](https://github.com/rescript-lang/rescript-compiler/pull/6412)
- Add builtin abstract types for File and Blob APIs. https://github.com/rescript-lang/rescript-compiler/pull/6383
- Untagged variants: Support `promise`, RegExes, Dates, File and Blob. https://github.com/rescript-lang/rescript-compiler/pull/6383
- Support aliased types as payloads to untagged variants. https://github.com/rescript-lang/rescript-compiler/pull/6394
diff --git a/jscomp/frontend/ast_external_process.ml b/jscomp/frontend/ast_external_process.ml
index c2137a7502..82a6000029 100644
--- a/jscomp/frontend/ast_external_process.ml
+++ b/jscomp/frontend/ast_external_process.ml
@@ -398,7 +398,14 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
| _ ->
Location.raise_errorf ~loc
"expect label, optional, or unit here")
- | Labelled name -> (
+ | Labelled label -> (
+ let fieldName =
+ match
+ Ast_attributes.iter_process_bs_string_as param_type.attr
+ with
+ | Some alias -> alias
+ | None -> label
+ in
let obj_arg_type = refine_obj_arg_type ~nolabel:false ty in
match obj_arg_type with
| Ignore ->
@@ -407,7 +414,7 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
result_types )
| Arg_cst _ ->
( {
- obj_arg_label = External_arg_spec.obj_label name;
+ obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
arg_types,
@@ -415,31 +422,31 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
result_types )
| Nothing ->
( {
- obj_arg_label = External_arg_spec.obj_label name;
+ obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
param_type :: arg_types,
- Parsetree.Otag ({Asttypes.txt = name; loc}, [], ty)
+ Parsetree.Otag ({Asttypes.txt = fieldName; loc}, [], ty)
:: result_types )
| Int _ ->
( {
- obj_arg_label = External_arg_spec.obj_label name;
+ obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
- ( {Asttypes.txt = name; loc},
+ ( {Asttypes.txt = fieldName; loc},
[],
Ast_literal.type_int ~loc () )
:: result_types )
| Poly_var_string _ ->
( {
- obj_arg_label = External_arg_spec.obj_label name;
+ obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
- ( {Asttypes.txt = name; loc},
+ ( {Asttypes.txt = fieldName; loc},
[],
Ast_literal.type_string ~loc () )
:: result_types )
@@ -449,11 +456,18 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
| Extern_unit -> assert false
| Poly_var _ ->
Location.raise_errorf ~loc
- "%@obj label %s does not support such arg type" name
+ "%@obj label %s does not support such arg type" label
| Unwrap ->
Location.raise_errorf ~loc
- "%@obj label %s does not support %@unwrap arguments" name)
- | Optional name -> (
+ "%@obj label %s does not support %@unwrap arguments" label)
+ | Optional label -> (
+ let fieldName =
+ match
+ Ast_attributes.iter_process_bs_string_as param_type.attr
+ with
+ | Some alias -> alias
+ | None -> label
+ in
let obj_arg_type = get_opt_arg_type ~nolabel:false ty in
match obj_arg_type with
| Ignore ->
@@ -469,35 +483,35 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
in
( {
obj_arg_label =
- External_arg_spec.optional for_sure_not_nested name;
+ External_arg_spec.optional for_sure_not_nested fieldName;
obj_arg_type;
},
param_type :: arg_types,
Parsetree.Otag
- ( {Asttypes.txt = name; loc},
+ ( {Asttypes.txt = fieldName; loc},
[],
Ast_comb.to_undefined_type loc ty )
:: result_types )
| Int _ ->
( {
- obj_arg_label = External_arg_spec.optional true name;
+ obj_arg_label = External_arg_spec.optional true fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
- ( {Asttypes.txt = name; loc},
+ ( {Asttypes.txt = fieldName; loc},
[],
Ast_comb.to_undefined_type loc
@@ Ast_literal.type_int ~loc () )
:: result_types )
| Poly_var_string _ ->
( {
- obj_arg_label = External_arg_spec.optional true name;
+ obj_arg_label = External_arg_spec.optional true fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
- ( {Asttypes.txt = name; loc},
+ ( {Asttypes.txt = fieldName; loc},
[],
Ast_comb.to_undefined_type loc
@@ Ast_literal.type_string ~loc () )
@@ -511,10 +525,10 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
| Extern_unit -> assert false
| Poly_var _ ->
Location.raise_errorf ~loc
- "%@obj label %s does not support such arg type" name
+ "%@obj label %s does not support such arg type" label
| Unwrap ->
Location.raise_errorf ~loc
- "%@obj label %s does not support %@unwrap arguments" name)
+ "%@obj label %s does not support %@unwrap arguments" label)
in
(new_arg_label :: arg_labels, new_arg_types, output_tys))
in
diff --git a/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt b/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt
index 5b6ad70b29..087f649aed 100644
--- a/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt
+++ b/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt
@@ -1,21 +1,38 @@
@@jsxConfig({version: 3})
-module C30 = {
- @obj external makeProps: (~_open: 'T_open, ~key: string=?, unit) => {"_open": 'T_open} = ""
+module C3A0 = {
+ @obj
+ external makeProps: (
+ ~_open: 'T_open,
+ ~_type: string,
+ ~key: string=?,
+ unit,
+ ) => {"_open": 'T_open, "_type": string} = ""
- @react.component let make = @warning("-16") (~_open) => React.string(_open)
+ @react.component
+ let make =
+ @warning("-16")
+ (@as("open") ~_open) => @warning("-16") (@as("type") ~_type: string) => React.string(_open)
let make = {
- let \"MangleKeyword$C30" = (\"Props": {"_open": 'T_open}) => make(~_open=\"Props"["_open"])
- \"MangleKeyword$C30"
+ let \"MangleKeyword$C3A0" = (\"Props": {"_open": 'T_open, "_type": string}) =>
+ make(~_type=\"Props"["_type"], ~_open=\"Props"["_open"])
+ \"MangleKeyword$C3A0"
}
}
-module C31 = {
- @obj external makeProps: (~_open: string, ~key: string=?, unit) => {"_open": string} = ""
- external make: React.componentLike<{"_open": string}, React.element> = "default"
+module C3A1 = {
+ @obj
+ external makeProps: (
+ ~_open: string,
+ ~_type: string,
+ ~key: string=?,
+ unit,
+ ) => {"_open": string, "_type": string} = ""
+ external make: @as("open")
+ React.componentLike<{"_open": string, "_type": string}, React.element> = "default"
}
-let c30 = React.createElement(C30.make, C30.makeProps(~_open="x", ()))
-let c31 = React.createElement(C31.make, C31.makeProps(~_open="x", ()))
+let c3a0 = React.createElement(C3A0.make, C3A0.makeProps(~_open="x", ~_type="t", ()))
+let c3a1 = React.createElement(C3A1.make, C3A1.makeProps(~_open="x", ~_type="t", ()))
@@jsxConfig({version: 4, mode: "classic"})
diff --git a/jscomp/syntax/tests/ppx/react/mangleKeyword.res b/jscomp/syntax/tests/ppx/react/mangleKeyword.res
index 2e0fa7c344..94dad3c2c0 100644
--- a/jscomp/syntax/tests/ppx/react/mangleKeyword.res
+++ b/jscomp/syntax/tests/ppx/react/mangleKeyword.res
@@ -1,16 +1,18 @@
@@jsxConfig({version: 3})
-module C30 = {
+module C3A0 = {
@react.component
- let make = (~_open) => React.string(_open)
+ let make =
+ (@as("open") ~_open, @as("type") ~_type: string) => React.string(_open)
}
-module C31 = {
+module C3A1 = {
@react.component
- external make: (~_open: string) => React.element = "default"
+ external make: (@as("open") ~_open: string, @as("type") ~_type: string) => React.element =
+ "default"
}
-let c30 =
-let c31 =
+let c3a0 =
+let c3a1 =
@@jsxConfig({version: 4, mode: "classic"})
diff --git a/jscomp/test/external_ppx.js b/jscomp/test/external_ppx.js
index c727881a0f..d7bcc73ac0 100644
--- a/jscomp/test/external_ppx.js
+++ b/jscomp/test/external_ppx.js
@@ -3,6 +3,17 @@
var External_ppxGen = require("./external_ppx.gen");
+function renamed(param) {
+ var tmp = {
+ type: "123",
+ normal: 12
+ };
+ if (param !== undefined) {
+ tmp.WIDTH = param;
+ }
+ return tmp;
+}
+
var u = {
hi: 2,
lo: 3,
@@ -15,6 +26,7 @@ function f(prim) {
return External_ppxGen.f(prim);
}
+exports.renamed = renamed;
exports.u = u;
exports.f = f;
/* ./external_ppx.gen Not a pure module */
diff --git a/jscomp/test/external_ppx.res b/jscomp/test/external_ppx.res
index 28665f702e..18473997d4 100644
--- a/jscomp/test/external_ppx.res
+++ b/jscomp/test/external_ppx.res
@@ -9,6 +9,15 @@ external make_config: (~length: 'a, ~width: int) => unit = ""
@obj external opt_make: (~length: int, ~width: int=?) => (_ as 'event) = ""
+@obj
+external renamed_make: (
+ @as("type") ~_type: string,
+ @as("WIDTH") ~width: int=?,
+ ~normal: float,
+) => (_ as 'event) = ""
+
+let renamed = renamed_make(~_type="123", ~normal=12.)
+
@obj
external ff: (
~hi: int,