Skip to content

[Bug]: semantic of function's this changes when calling function from other chunks from in cjs output #3073

@hi-ogawa

Description

@hi-ogawa

Reproduction link or steps

https://repl.rolldown.rs/#eNqtkE9rwzAMxb+K0CUNdF47BoOUHMbW0xg7dEfDyBKncZfYxXaWQfB3n5ysbfant4ExPEnv95B6LDHp0ei6LnSnWK5VKbdsZ0NVYfJXZ445NcTHXhsHhSiztnbQcwWgW7dvXTIKgFKbJiMZ5TsbhZLnih76OTaZVMtJzFGPcNkM8B5cZXS3NkYb8FAa3QBHdmmrzIiCxjlyw9VpaBaviCAwcaYVXzFXP2IG/b8xx8FDzqnw7Vhlq3IntZrkzWK6FsEB6MBW14LVejvjmKYpRK6SNgKprCxEUAdTRF2O8W9fMAzlc8jBzqzL8rdxzykVzmGV6EYnUe7Xj08vm+fbu4cNzY6oeBU8Pnzo6R7vtPKSLdji4lW4jF3foP8EzEfNtQ==

Reproduction: https://stackblitz.com/github/hi-ogawa/reproductions/tree/main/rolldown-esm-import-this?file=README.md

For cjs code spliting build of following code:

  • main1.js, main2.js (use two entries to create shared chunk)
import { throwError } from "./shared.js"
throwError();
  • shared.js
export function throwError() {
  console.log("=== 'this' inside 'throwError'===")
  console.log(this)

  console.log("=== Error.stack from 'throwError' ===")
  console.log(new Error("DEMO_STACKS").stack);
}

Rolldown produces:

// dist/main1.cjs
const require_shared = require('./shared.cjs');
require_shared.throwError();

where require_shared.throwError call has require_shared object as this context.

What is expected?

works like original esm code

$ node src/main1.js
=== 'this' inside 'throwError'===
undefined
=== Error.stack from 'throwError' ===
Error: DEMO_STACKS
    at throwError (file:///xxx/src/shared.js:6:15)

What is actually happening?

$ node dist/main1.cjs
== 'this' inside 'throwError'===
{ throwError: [Getter] }
=== Error.stack from 'throwError' ===
Error: DEMO_STACKS
    at Object.throwError (/xxx/dist/shared.cjs:8:14)

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.20.3 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    rolldown: 0.15.0-snapshot-64a831c-20241207003504 => 0.15.0-snapshot-64a831c-20241207003504

Any additional comments?

I was looking at webpack's output had a bunch of (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs) and I remembered the trick (0,...) is for avoiding this context. Vite SSR recently added this too vitejs/vite#18748

This may be not a big deal especially when users are explicitly choosing cjs build. I just found rollup doesn't handle this either rollup repl.

But, this might be relatively important for app format since users are not explicitly saying cjs in this case and rolldown needs to emulate esm as much as possible.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions