swc-project / swc

Rust-based platform for the Web
https://swc.rs
Apache License 2.0
30.93k stars 1.21k forks source link

@swc/wasm-typescript exits on Windows arm64 when fed with certain syntax #9520

Open wojtekmaj opened 2 weeks ago

wojtekmaj commented 2 weeks ago

Describe the bug

After investigation in https://github.com/nodejs/node/issues/54645 I finally came to conclusion that on Windows arm64 (this particular configuration, not Windows other than arm64, not arm64 other than Windows), swc fails to transform certain syntax and just silently exits instead.

Input code

export function foo() {
    if (false) {
    }
    return 'foo';
};

Config

n/a

Playground link (or link to the minimal reproduction)

https://gist.github.com/wojtekmaj/c37e1eb07676cde83e5201ade8b7f02f

SWC Info output

Operating System:
    Platform: win32
    Arch: arm64
    Machine Type: unknown
    Version: Windows 11 Home
    CPU: (12 cores)
        Models: Snapdragon(R) X 12-core X1E80100 @ 3.40 GHz

Binaries:
    Node: 22.7.0
    npm: N/A
    Yarn: N/A
    pnpm: N/A

Relevant Packages:
    @swc/core: N/A
    @swc/helpers: N/A
    @swc/types: N/A

SWC Config:
    output: N/A
    .swcrc path: N/A

Next.js info:
    output: N/A

Expected behavior

Code should be transformed, types should be stripped, swc should not silently exit.

Actual behavior

swc silently exists, and neither the output, nor "End 2" console.log (see playground link) never appears on the screen.

Version

1.7.22

Additional context

No response

magic-akari commented 1 week ago

Is this issue only related to the strip-only? You can check it by adding the option mode: "transform" as shown below:

import { transformSync } from "@swc/wasm-typescript";

const options = {
    mode: "transform",
    transform: {
        verbatimModuleSyntax: true,
        nativeClassProperties: true,
        noEmptyExport: true,
        importNotUsedAsValues: "preserve",
    }
}

console.log("Begin 1");
console.log(
    transformSync(`
export function foo() {
    return 'foo';
};
`, options).code,
);
console.log("End 1");

console.log("Begin 2");
console.log(
    transformSync(`
export function foo() {
    if (false) {
    }
    return 'foo';
};
`, options).code,
);
console.log("End 2");
wojtekmaj commented 1 week ago

@magic-akari No luck:

PS C:\test> node swc.js 
Begin 1
export function foo() {
    return 'foo';
}

End 1
Begin 2
magic-akari commented 1 week ago

It's suspected that the issue arises at an earlier stage, possibly in the parser.

wojtekmaj commented 1 week ago

It's my first encounter with swc, so apologies if my diagnosis so far aren't the best, but I'll do my best to help out. The hardware is yours to experiment on :D

magic-akari commented 1 week ago

let's do more experiments to pinpoint this issue.

  1. Test the strip-only mode in your browser by clicking this link: https://play.swc.rs/?version=1.7.23&code=H4sIAAAAAAAAA0utKMgvKlFIK81LLsnMz1NIy8%2FX0FSo5uLMTFPQSEvMKU4F82q5OItSS0qL8hTUgSrUrblqrQGZRHv4OgAAAA%3D%3D&config=H4sIAAAAAAAAA6vmUlBQyipOVrJSqAYygZyCxKLi1CI4HyhSXJlXklgBFFFKTc5NLE4uyiwoUQJL1nKBcC0ABwZxP0UAAAA%3D&strip-types=

  2. Check the parser's functionality in your browser using this link: https://swc-ast.vercel.app/#code/KYDwDg9gTgLgBAMwK4DsDGMCWEWIhACgEo4BvAKAEhME4CEBDAGwGdgSLKBfKqYGJFFwByBPmEBuclwlA

  3. Run this command to verify the parser's functionality in Node:

npx swc_ast_viewer path/to/your_file.js
wojtekmaj commented 5 days ago

@magic-akari

Ad 1 - This worked perfectly fine, on latest Microsoft Edge, arm64 build. input === output. Ad 2 - This resulted in the following output (no crash):

Output Module( Module { span: 1..59, body: [ ModuleDecl( ExportDecl( ExportDecl { span: 1..58, decl: Fn( FnDecl { ident: Ident { span: 17..20, ctxt: #2, sym: "foo", optional: false, }, declare: false, function: Function { params: [], decorators: [], span: 8..58, ctxt: #3, body: Some( BlockStmt { span: 23..58, ctxt: #3, stmts: [ If( IfStmt { span: 26..41, test: Lit( Bool( Bool { span: 30..35, value: false, }, ), ), cons: Block( BlockStmt { span: 37..41, ctxt: #4, stmts: [], }, ), alt: None, }, ), Return( ReturnStmt { span: 43..56, arg: Some( Lit( Str( Str { span: 50..55, value: "foo", raw: Some( "'foo'", ), }, ), ), ), }, ), ], }, ), is_generator: false, is_async: false, type_params: None, return_type: None, }, }, ), }, ), ), Stmt( Empty( EmptyStmt { span: 58..59, }, ), ), ], shebang: None, }, )

Ad 3 - This just prints the version number, regardless of the file I'm feeding it (!):

PS C:\test> npx swc_ast_viewer ./simple-file.ts
swc@0.103.1
magic-akari commented 5 days ago

It seems that our WASM version parser isn't working on Windows ARM64 with Node.js. The lack of error messages from WASM, which just exits quietly, complicates debugging.

Moreover, there are no methods in WASM that trigger process.exit, and I think that exiting silently is an unexpected behavior in Node.js.

What are your thoughts? @kdy1

marco-ippolito commented 5 days ago

My feeling is that there is no crash/error, it simply exits the transpilation early with an empty output. Github recently released arm64 windows runner, we could use that to reproduce.

kdy1 commented 5 days ago

@magic-akari I think we can use the CI of SWC. You can add some node.js tests and run the publish action with only nightly enabled. I'll do it soon.

kdy1 commented 5 days ago

Let's try with @swc/core first. I made https://github.com/swc-project/swc/pull/9547 and triggered https://github.com/swc-project/swc/actions/runs/10810667484

marco-ippolito commented 9 hours ago

Let's try with @swc/core first. I made https://github.com/swc-project/swc/pull/9547 and triggered https://github.com/swc-project/swc/actions/runs/10810667484

I see the CI is green, might be related to WASM?

kdy1 commented 9 hours ago

I got an arm64 windows device. My mother had one 👍 I'll fix this issue after Chuseok holiday(through Wednesday)