Skip to content

export default function/class live binding doesn't work on Vite SSR #19834

@hi-ogawa

Description

@hi-ogawa

Describe the bug

  • main.js
import * as lib from './lib.js';
lib.default();

setTimeout(() => {
  lib.default();
}, 200);
  • lib.js
export default function f() {
  console.log('a');
}

f = () => {
  console.log('b');
};

setTimeout(() => {
  f = () => {
    console.log('c');
  };
}, 100);

On Node:

❯ node src/main.js
b
c

On Vite module runner

❯ node repro.js
b
b

Spec explains live binding as "ExportEntry Record [[LocalName]]", for example, this table https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#table-export-forms-mapping-to-exportentry-records

This is a fairly stretched edge case, but just found that Oxc uses Object.defineProperty(..., { get: ... }) while Vite uses Object.defineProperty(..., { value: ... }) and Oxc's implementation seems to be actually correct one.

Reproduction

https://stackblitz.com/edit/vitejs-vite-b63hinxr?file=src%2Flib.js

Steps to reproduce

open stackblitz

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: 20.19.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.8.2 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    vite: ^6.2.2 => 6.2.5

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    feat: ssrp2-edge-caseBug, but has workaround or limited in scope (priority)

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions