Skip to content

Commit

Permalink
fix: workaround for TS bug in Object.defineProperty (#75944)
Browse files Browse the repository at this point in the history
This PR changes the server action generated code a bit to work around a
typescript bug and remove some false positives we got while
typechecking: microsoft/TypeScript#61165

The trick is that typescript seems to look for *exactly*
`Object.defineProperty(obj, 'literal', { value: ... })`, and changing
any part of the expression bypasses the bug, so we can just use
`Object['defineProperty']` instead.
  • Loading branch information
lubieowoce authored Feb 25, 2025
1 parent 35eb671 commit 03a600c
Show file tree
Hide file tree
Showing 29 changed files with 125 additions and 159 deletions.
56 changes: 14 additions & 42 deletions crates/next-custom-transforms/src/transforms/server_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use swc_core::{
utils::{private_ident, quote_ident, ExprFactory},
visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith},
},
quote,
};
use turbo_rcstr::RcStr;

Expand Down Expand Up @@ -2272,48 +2273,19 @@ fn create_var_declarator(ident: &Ident, extra_items: &mut Vec<ModuleItem>) {

fn assign_name_to_ident(ident: &Ident, name: &str, extra_items: &mut Vec<ModuleItem>) {
// Assign a name with `Object.defineProperty($$ACTION_0, 'name', {value: 'default'})`
extra_items.push(ModuleItem::Stmt(Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(Ident::new(
"Object".into(),
DUMMY_SP,
ident.ctxt,
))),
prop: MemberProp::Ident(IdentName::new("defineProperty".into(), DUMMY_SP)),
}))),
args: vec![
ExprOrSpread {
spread: None,
expr: Box::new(Expr::Ident(ident.clone())),
},
ExprOrSpread {
spread: None,
expr: Box::new("name".into()),
},
ExprOrSpread {
spread: None,
expr: Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: vec![
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Str("value".into()),
value: Box::new(name.into()),
}))),
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Str("writable".into()),
value: Box::new(false.into()),
}))),
],
})),
},
],
..Default::default()
})),
})));
extra_items.push(quote!(
// WORKAROUND for https://github.com/microsoft/TypeScript/issues/61165
// This should just be
//
// "Object.defineProperty($action, \"name\", { value: $name, writable: false });"
//
// but due to the above typescript bug, `Object.defineProperty` calls are typechecked incorrectly
// in js files, and it can cause false positives when typechecking our fixture files.
"Object[\"defineProperty\"]($action, \"name\", { value: $name, writable: false });"
as ModuleItem,
action: Ident = ident.clone(),
name: Expr = name.into(),
));
}

fn assign_arrow_expr(ident: &Ident, expr: Expr) -> Expr {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
export default /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_ACTION_0 = ()=>{};
var $$RSC_SERVER_ACTION_0;
Object.defineProperty($$RSC_SERVER_ACTION_0, "name", {
"value": "default",
"writable": false
Object["defineProperty"]($$RSC_SERVER_ACTION_0, "name", {
value: "default",
writable: false
});
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
ensureServerEntryExports([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import inter from '@next/font/google/target.css?{"path":"app/test.tsx","import":
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "c0dd5bb6fef67f5ab84327f5164ac2c3111a159337", 0, async function Cached({ children }) {
return <div className={inter.className}>{children}</div>;
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "Cached",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "Cached",
writable: false
});
export var Cached = registerServerReference($$RSC_SERVER_CACHE_0, "c0dd5bb6fef67f5ab84327f5164ac2c3111a159337", null);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* __next_internal_action_entry_do_not_use__ {"00c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default"} */ import { registerServerReference } from "private-next-rsc-server-reference";
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
export default /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ async function $$RSC_SERVER_ACTION_0() {}
Object.defineProperty($$RSC_SERVER_ACTION_0, "name", {
"value": "default",
"writable": false
Object["defineProperty"]($$RSC_SERVER_ACTION_0, "name", {
value: "default",
writable: false
});
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
ensureServerEntryExports([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ export default /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_ACTION_0 =
console.log(a, b);
};
var $$RSC_SERVER_ACTION_0;
Object.defineProperty($$RSC_SERVER_ACTION_0, "name", {
"value": "default",
"writable": false
Object["defineProperty"]($$RSC_SERVER_ACTION_0, "name", {
value: "default",
writable: false
});
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
ensureServerEntryExports([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { validator } from 'auth';
export const /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ action = validator(async ()=>{});
export default /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_ACTION_0 = validator(async ()=>{});
var $$RSC_SERVER_ACTION_0;
Object.defineProperty($$RSC_SERVER_ACTION_0, "name", {
"value": "default",
"writable": false
Object["defineProperty"]($$RSC_SERVER_ACTION_0, "name", {
value: "default",
writable: false
});
import { ensureServerEntryExports } from "private-next-rsc-action-validate";
ensureServerEntryExports([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ const v = 'world';
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function fn() {
return 'hello, ' + v;
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "fn",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "fn",
writable: false
});
var fn = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
export async function Component() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper";
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function() {
return 'foo';
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "foo",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "foo",
writable: false
});
const foo = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
export { bar };
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_1 = $$cache__("default", "80951c375b4a6a6e89d67b743ec5808127cfde405d", 0, async function bar() {
return 'bar';
});
Object.defineProperty($$RSC_SERVER_CACHE_1, "name", {
"value": "bar",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_1, "name", {
value: "bar",
writable: false
});
var bar = registerServerReference($$RSC_SERVER_CACHE_1, "80951c375b4a6a6e89d67b743ec5808127cfde405d", null);
// Should not be wrapped in $$cache__.
Expand All @@ -25,17 +25,17 @@ const qux = async function qux() {
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_2 = $$cache__("default", "8069348c79fce073bae2f70f139565a2fda1c74c74", 0, async function baz() {
return qux() + 'baz';
});
Object.defineProperty($$RSC_SERVER_CACHE_2, "name", {
"value": "baz",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_2, "name", {
value: "baz",
writable: false
});
const baz = registerServerReference($$RSC_SERVER_CACHE_2, "8069348c79fce073bae2f70f139565a2fda1c74c74", null);
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_3 = $$cache__("default", "8012a8d21b6362b4cc8f5b15560525095bc48dba80", 0, async function() {
return 'quux';
});
Object.defineProperty($$RSC_SERVER_CACHE_3, "name", {
"value": "quux",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_3, "name", {
value: "quux",
writable: false
});
const quux = registerServerReference($$RSC_SERVER_CACHE_3, "8012a8d21b6362b4cc8f5b15560525095bc48dba80", null);
export { foo, baz };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper";
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function() {
return 'data';
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "my_fn",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "my_fn",
writable: false
});
export const my_fn = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,32 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper";
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function foo() {
return 'data A';
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "foo",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "foo",
writable: false
});
export var foo = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_1 = $$cache__("default", "80951c375b4a6a6e89d67b743ec5808127cfde405d", 0, async function bar() {
return 'data B';
});
Object.defineProperty($$RSC_SERVER_CACHE_1, "name", {
"value": "bar",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_1, "name", {
value: "bar",
writable: false
});
export var bar = registerServerReference($$RSC_SERVER_CACHE_1, "80951c375b4a6a6e89d67b743ec5808127cfde405d", null);
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_2 = $$cache__("default", "c069348c79fce073bae2f70f139565a2fda1c74c74", 0, async function Cached({ children }) {
return children;
});
Object.defineProperty($$RSC_SERVER_CACHE_2, "name", {
"value": "Cached",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_2, "name", {
value: "Cached",
writable: false
});
export default registerServerReference($$RSC_SERVER_CACHE_2, "c069348c79fce073bae2f70f139565a2fda1c74c74", null);
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_3 = $$cache__("default", "8012a8d21b6362b4cc8f5b15560525095bc48dba80", 0, async function baz() {
return 'data C';
});
Object.defineProperty($$RSC_SERVER_CACHE_3, "name", {
"value": "baz",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_3, "name", {
value: "baz",
writable: false
});
export const baz = registerServerReference($$RSC_SERVER_CACHE_3, "8012a8d21b6362b4cc8f5b15560525095bc48dba80", null);
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper";
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function fn() {
return 'foo';
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "fn",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "fn",
writable: false
});
var fn = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
async function Component() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper";
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("x", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function foo() {
return 'data';
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "foo",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "foo",
writable: false
});
export var foo = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$ca
foo: $$ACTION_ARG_1
};
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "fn",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "fn",
writable: false
});
async function Component({ foo }) {
const a = 123;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$ca
}
];
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "cache",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "cache",
writable: false
});
export const /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_ACTION_2 = async function action($$ACTION_CLOSURE_BOUND, c) {
var [$$ACTION_ARG_0, $$ACTION_ARG_1] = await decryptActionBoundArgs("601c36b06e398c97abe5d5d7ae8c672bfddf4e1b91", $$ACTION_CLOSURE_BOUND);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_1 = $$ca
// @ts-expect-error: data is not a valid react child
return <div>{data}</div>;
});
Object.defineProperty($$RSC_SERVER_CACHE_1, "name", {
"value": "Component",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_1, "name", {
value: "Component",
writable: false
});
export var Component = registerServerReference($$RSC_SERVER_CACHE_1, "c0951c375b4a6a6e89d67b743ec5808127cfde405d", null);
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$ca
foo: $$ACTION_ARG_1
};
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "fn",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "fn",
writable: false
});
async function Component({ foo }) {
const a = 123;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_1 = $$ca
r: children
};
});
Object.defineProperty($$RSC_SERVER_CACHE_1, "name", {
"value": "getCachedRandom",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_1, "name", {
value: "getCachedRandom",
writable: false
});
var getCachedRandom = registerServerReference($$RSC_SERVER_CACHE_1, "e0951c375b4a6a6e89d67b743ec5808127cfde405d", null);
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ function Foo() {
export var /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, async function bar() {
return <Foo/>;
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "bar",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "bar",
writable: false
});
export var bar = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "e03128060c414d59f8552e47
b
];
});
Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "f1",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_0, "name", {
value: "f1",
writable: false
});
var f1 = registerServerReference($$RSC_SERVER_CACHE_0, "e03128060c414d59f8552e4788b846c0d2b7f74743", null);
export const // Should be 0 110000 0, which is "60" in hex.
Expand All @@ -30,9 +30,9 @@ export var // Should be 1 111111 1, which is "ff" in hex.
rest
];
});
Object.defineProperty($$RSC_SERVER_CACHE_2, "name", {
"value": "f3",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_2, "name", {
value: "f3",
writable: false
});
var f3 = registerServerReference($$RSC_SERVER_CACHE_2, "ff69348c79fce073bae2f70f139565a2fda1c74c74", null);
export const // Should be 0 111110 0, which is "7c" in hex.
Expand Down Expand Up @@ -70,8 +70,8 @@ export var // Should be 1 111111 1, which is "ff" in hex.
g
];
});
Object.defineProperty($$RSC_SERVER_CACHE_5, "name", {
"value": "f6",
"writable": false
Object["defineProperty"]($$RSC_SERVER_CACHE_5, "name", {
value: "f6",
writable: false
});
var f6 = registerServerReference($$RSC_SERVER_CACHE_5, "ff471a5eb0be1c31686dd4ba938a80328b80b1615d", null);
Loading

0 comments on commit 03a600c

Please sign in to comment.