Skip to content

Commit

Permalink
Forbid super in static class methods with server function directives
Browse files Browse the repository at this point in the history
Static class methods that are annotated with `"use cache"` or `"use
server"` must not call `super`.
  • Loading branch information
unstubbable committed Nov 21, 2024
1 parent 2575927 commit 989f733
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 10 deletions.
21 changes: 21 additions & 0 deletions crates/next-custom-transforms/src/transforms/server_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2287,6 +2287,16 @@ impl<C: Comments> VisitMut for ServerActions<C> {
}
}

fn visit_mut_super(&mut self, n: &mut Super) {
if let ThisStatus::Forbidden { directive } = &self.this_status {
emit_error(ServerActionsErrorKind::ForbiddenExpression {
span: n.span,
expr: "super".into(),
directive: directive.clone(),
});
}
}

fn visit_mut_ident(&mut self, n: &mut Ident) {
if n.sym == *"arguments" {
if let ThisStatus::Forbidden { directive } = &self.this_status {
Expand Down Expand Up @@ -2735,6 +2745,17 @@ impl VisitMut for ClosureReplacer<'_> {
fn visit_mut_expr(&mut self, e: &mut Expr) {
e.visit_mut_children_with(self);

if let Expr::Call(CallExpr {
callee: Callee::Expr(box Expr::SuperProp(SuperPropExpr { .. })),
..
}) = e
{
// Replace super calls in hoisted static class methods with a dummy
// `null` expression to ensure that the resulting JS is still valid.
// Before this, we have already emitted an error for the super call.
*e = Expr::Lit(Lit::Null(Null::dummy()));
}

if let Some(index) = self.index(e) {
*e = Expr::Ident(Ident::new(
// $$ACTION_ARG_0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
export class MyClass {
import { BaseClass } from './base'

export class MyClass extends BaseClass {
static async foo() {
// super is allowed here
super.foo()

return fetch('https://example.com').then((res) => res.json())
}
static async bar() {
'use cache'

// super is not allowed here
super.bar()
// arguments is not allowed here
console.log(arguments)
// this is not allowed here
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* __next_internal_action_entry_do_not_use__ {"803128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0"} */ import { registerServerReference } from "private-next-rsc-server-reference";
import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption";
import { cache as $$cache__ } from "private-next-rsc-cache-wrapper";
import { BaseClass } from './base';
export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "803128060c414d59f8552e4788b846c0d2b7f74743", 0, /*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/ async function bar() {
// super is not allowed here
null;
// arguments is not allowed here
console.log(arguments);
// this is not allowed here
Expand All @@ -11,8 +14,10 @@ Object.defineProperty($$RSC_SERVER_CACHE_0, "name", {
"value": "bar",
"writable": false
});
export class MyClass {
export class MyClass extends BaseClass {
static async foo() {
// super is allowed here
super.foo();
return fetch('https://example.com').then((res)=>res.json());
}
static bar = registerServerReference($$RSC_SERVER_CACHE_0, "803128060c414d59f8552e4788b846c0d2b7f74743", null);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
x "use cache" functions can not use `super`.
|
,-[input.js:14:1]
13 | // super is not allowed here
14 | super.bar()
: ^^^^^
15 | // arguments is not allowed here
`----
x "use cache" functions can not use `arguments`.
|
,-[input.js:9:1]
8 | // arguments is not allowed here
9 | console.log(arguments)
,-[input.js:16:1]
15 | // arguments is not allowed here
16 | console.log(arguments)
: ^^^^^^^^^
10 | // this is not allowed here
17 | // this is not allowed here
`----
x "use cache" functions can not use `this`.
|
,-[input.js:11:1]
10 | // this is not allowed here
11 | return this.foo()
,-[input.js:18:1]
17 | // this is not allowed here
18 | return this.foo()
: ^^^^
12 | }
19 | }
`----

0 comments on commit 989f733

Please sign in to comment.