Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swc transpiler does not set strictMode to match tsconfig #1531

Closed
Janpot opened this issue Oct 26, 2021 · 9 comments · Fixed by #1537
Closed

swc transpiler does not set strictMode to match tsconfig #1531

Janpot opened this issue Oct 26, 2021 · 9 comments · Fixed by #1537
Milestone

Comments

@Janpot
Copy link
Contributor

Janpot commented Oct 26, 2021

Search Terms

swc

Expected Behavior

Running

function defaultHello () {
  return ''
}

class X {
  constructor(x) {
    this.hello = () => (x.hello || defaultHello)()
  }
}

console.log(new X({
  hello () {
    return this.y || 'this works'
  }
}).hello())

using

  "ts-node": {
    "transpileOnly": true,
    "transpiler": "ts-node/transpilers/swc-experimental"
  },

will print

this works

(this is what is printed without using swc)

Actual Behavior

an error is printed:

/swctest/index.ts:13
    return this.y || 'this works'
                ^
TypeError: Cannot read property 'y' of undefined
    at hello (/swctest/index.ts:13:17)
    at X.hello (/swctest/index.ts:7:50)
    at Object.<anonymous> (/swctest/index.ts:15:4)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Module.m._compile (/swctest/node_modules/ts-node/src/index.ts:1371:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Object.require.extensions.<computed> [as .ts] (/swctest/node_modules/ts-node/src/index.ts:1374:12)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)

Specifications

ts-node v10.4.0
node v14.16.0
compiler v4.4.4
@swc/core 1.2.103 
  • tsconfig.json, if you're using one:
{
  "compilerOptions": {
    "target": "es5",                 
    "module": "commonjs",
    "esModuleInterop": true, 
    "forceConsistentCasingInFileNames": true, 
    "strict": false,  
    "skipLibCheck": true },

  "ts-node": {
    "transpileOnly": true,
    "transpiler": "ts-node/transpilers/swc-experimental"
  },
}
  • Operating system and version: MacOS 11.6
@cspotcode
Copy link
Collaborator

Do you think this is a strict mode issue? E.g swc is enabling strict mode when you expect it to be disabled, or vice versa? I'm referring specifically to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode, not to TypeScripts's "strict" option which is a different thing.

What does this do?

console.log(new X({
  hello () {
    console.dir(this); // figure out the `this` value.  Is it equal to `global`?
  }
}).hello())

@Janpot
Copy link
Contributor Author

Janpot commented Oct 27, 2021

Ah ofcourse, yes indeed, it's the global object, swc seems to add the use strict pragma. Manually adding it makes the behavior the same when I disable swc.
Aside, I've been trying to use the --emit flag to inspect the transpiler output, but it doesn't seem to have any effect. Am I misunderstanding the purpose of this flag?

@cspotcode
Copy link
Collaborator

Ok, looks we do not pass the strictMode flag to swc and it defaults to true.
https://swc.rs/docs/config-js-module#strictmode

module: moduleType
? ({
noInterop: !esModuleInterop,
type: moduleType,
} as swcTypes.ModuleConfig)
: undefined,

We should be explicitly setting this option to match whatever your typescript config indicates, so that you'll get the same behavior with both compilers.
https://www.typescriptlang.org/tsconfig#alwaysStrict

I've renamed this issue to describe the underlying problem, which helps keep track of implementing a fix.


Re the --emit flag, it is meant to write all compiled output into a .ts-node directory. But it's possibly non-functional when combined with transpilers / transpile-only? I'm not sure.

I also have this idea to add a flag that is specifically for inspecting the compiled output of a single file at a time, for debugging situations like this: #1366

@cspotcode cspotcode changed the title swc transpiler generates faulty behavior swc transpiler does not set strictMode to match tsconfig Oct 27, 2021
@cspotcode cspotcode added this to the next milestone Oct 27, 2021
@Janpot
Copy link
Contributor Author

Janpot commented Oct 27, 2021

Re the --emit flag, it is meant to write all compiled output into a .ts-node directory. But it's possibly non-functional when combined with transpilers / transpile-only? I'm not sure.

It never seems to emit for me, regardless of the options

I also have this idea to add a flag that is specifically for inspecting the compiled output of a single file at a time, for debugging situations like this: #1366

Personally, I think I'd still use just --emit

@cspotcode
Copy link
Collaborator

If you think --emit is not working correctly, feel free to submit a bug report. Please check for pre-existing reports first.

@cspotcode
Copy link
Collaborator

cspotcode commented Nov 3, 2021

@Janpot What is your tsconfig? There are various options which affect "use strict" and I want to make sure I understand your project configuration 100%. Thank you in advance.


I did a bit of research here. tsc, by default, will add "use strict" whenever you use any sort of import or export. Additionally, if strict: true is configured, it will always emit "use strict".

Your script above is a special case. I expect that most node scripts, even standalone ones, will have at least one import, for example import {} from 'fs'; TS is bending over backwards to allow scripts with zero imports or exports to run in non-strict mode. I suspect this behavior only exists for backwards compatibility, and you generally always want "use strict" enabled when working with node.

swc is not as nuanced as TS. We can either tell it to always emit use strict, or never emit.

Given this limitation of swc, I'm going to pragmatically assume that all node scripts have an import or export, and set swc's options accordingly.

If a user really really needs to avoid strict mode, they will likely have alwaysStrict: false, noImplicitUseStrict: true. We can detect this and tell swc not to emit "use strict"

@cspotcode
Copy link
Collaborator

Nevermind... of course you included your tsconfig at the top, doh!

@Janpot
Copy link
Contributor Author

Janpot commented Nov 3, 2021

This was originally discovered in a repo that was transitioning from js to ts. all the imports were require calls. not all files had a 'use strict' pragma. the original js files were not compiled before and after running them through ts-node, this issue came up.

@cspotcode
Copy link
Collaborator

Thanks, good to understand the context. I think the implementation we settled on is the best we can do, given that swc's configuration is a bit more limited than tsc's.

crapStone pushed a commit to Calciumdibromid/CaBr2 that referenced this issue Feb 16, 2022
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ts-node](https://typestrong.org/ts-node) ([source](https://github.com/TypeStrong/ts-node)) | devDependencies | minor | [`10.4.0` -> `10.5.0`](https://renovatebot.com/diffs/npm/ts-node/10.4.0/10.5.0) |

---

### Release Notes

<details>
<summary>TypeStrong/ts-node</summary>

### [`v10.5.0`](https://github.com/TypeStrong/ts-node/releases/v10.5.0)

[Compare Source](TypeStrong/ts-node@v10.4.0...v10.5.0)

<!--
  I don't make a discussion thread for every release.  Github has a button to make a discussion thread for a release.
  Then I update the discussion thread to remove the release notes and instead link to the release.
-->

Questions about this release? Ask in the official discussion thread: [#&#8203;1634](TypeStrong/ts-node#1634)

**Added**

-   Eliminate "Emit Skipped" errors ([#&#8203;693](TypeStrong/ts-node#693), [#&#8203;1345](TypeStrong/ts-node#1345), [#&#8203;1629](TypeStrong/ts-node#1629))
    -   Avoids all "Emit Skipped" errors by performing a fallback `transpileOnly`-style transformation.
    -   Does not affect typechecking.  Type errors are still detected and thrown.
    -   Fallback has the same limitations as `isolatedModules`. This will only affect rare cases such as using `const enums` with `preserveConstEnums` disabled.
    -   Fixes [#&#8203;693](TypeStrong/ts-node#693)
-   Graduate swc transpiler out of experimental; add `swc: true` convenience option ([docs](https://typestrong.org/ts-node/docs/transpilers)) ([#&#8203;1487](TypeStrong/ts-node#1487), [#&#8203;1536](TypeStrong/ts-node#1536), [#&#8203;1613](TypeStrong/ts-node#1613), [#&#8203;1627](TypeStrong/ts-node#1627))
    -   `"swc": true` or `--swc` will use swc for faster execution
    -   This feature is no longer marked "experimental."  Thank you to everyone who filed bugs!
-   swc transpiler attempts to load `@swc/core` or `@swc/wasm` dependencies from your project before falling-back to global installations ([#&#8203;1613](TypeStrong/ts-node#1613), [#&#8203;1627](TypeStrong/ts-node#1627))
    -   global fallback only occurs when using a global installation of ts-node
-   Add support for TypeScript's `traceResolution` output ([docs](https://www.typescriptlang.org/tsconfig/#traceResolution)) ([#&#8203;1128](TypeStrong/ts-node#1128), [#&#8203;1491](TypeStrong/ts-node#1491)) [@&#8203;TheUnlocked](https://github.com/TheUnlocked)
-   Support import assertions in ESM loader ([docs](https://nodejs.org/dist/latest-v17.x/docs/api/esm.html#import-assertions)) ([#&#8203;1557](TypeStrong/ts-node#1557), [#&#8203;1558](TypeStrong/ts-node#1558), [#&#8203;1559](TypeStrong/ts-node#1559), [#&#8203;1573](TypeStrong/ts-node#1573)) [@&#8203;Pokute](https://github.com/Pokute), [@&#8203;geigerzaehler](https://github.com/geigerzaehler)
    -   Allows importing JSON files from ESM with the requisite flag ([docs](https://nodejs.org/dist/latest-v17.x/docs/api/esm.html#json-modules))
-   `ts-node -vvv` also logs absolute paths to `ts-node` and `typescript`, to make it more obvious when you're accidentally using globally-installed versions ([#&#8203;1323](TypeStrong/ts-node#1323), [#&#8203;1620](TypeStrong/ts-node#1620))
-   Add swc target "es2022" ([#&#8203;1535](TypeStrong/ts-node#1535), [#&#8203;1540](TypeStrong/ts-node#1540))
    -   When you have target es2022 in tsconfig, will use swc's es2022 target

**Changed**

-   Initialize TypeScript compiler before starting REPL prompt ([#&#8203;1498](TypeStrong/ts-node#1498)) [@&#8203;TheUnlocked](https://github.com/TheUnlocked)
    -   Improves responsiveness for first line of REPL input
-   Use `v8-compile-cache-lib` to load typescript
    -   improves startup time ([#&#8203;1339](TypeStrong/ts-node#1339), [#&#8203;1603](TypeStrong/ts-node#1603))
-   Support both `--camelCase` and `--hyphen-case` for all CLI flags; update documentation to use `--camelCase` ([#&#8203;1598](TypeStrong/ts-node#1598), [#&#8203;1599](TypeStrong/ts-node#1599))
    -   Not a breaking change; CLI continues to accept both forms
-   Make `TSError` `diagnosticText` property non-enumerable to prevent it from being logged below the stack ([#&#8203;1632](TypeStrong/ts-node#1632))

**Fixed**

-   Fix [#&#8203;1538](TypeStrong/ts-node#1538): REPL inputs fail to transpile via swc ([#&#8203;1538](TypeStrong/ts-node#1538), [#&#8203;1541](TypeStrong/ts-node#1541), [#&#8203;1602](TypeStrong/ts-node#1602))
-   Fix [#&#8203;1478](TypeStrong/ts-node#1478): REPL erroneously logged `undefined` for all inputs after the first when using swc transpiler ([#&#8203;1478](TypeStrong/ts-node#1478), [#&#8203;1580](TypeStrong/ts-node#1580), [#&#8203;1602](TypeStrong/ts-node#1602))
-   Fix [#&#8203;1389](TypeStrong/ts-node#1389): In `--showConfig` output, emit accurate `moduleTypes` paths resolved relative to the `tsconfig.json` which declared them ([#&#8203;1389](TypeStrong/ts-node#1389), [#&#8203;1619](TypeStrong/ts-node#1619))
-   Fix: Remove indentation from `ts-node --help` output ([#&#8203;1597](TypeStrong/ts-node#1597), [#&#8203;1600](TypeStrong/ts-node#1600))
-   Fix [#&#8203;1425](TypeStrong/ts-node#1425): Merged definitions correctly into `tsconfig.schemastore-schema.json` ([#&#8203;1425](TypeStrong/ts-node#1425), [#&#8203;1618](TypeStrong/ts-node#1618))
-   Fix: Allow disabling `"use strict"` emit in SWC transpiler ([#&#8203;1531](TypeStrong/ts-node#1531), [#&#8203;1537](TypeStrong/ts-node#1537))
-   Fix: Add missing `ERR_UNKNOWN_FILE_EXTENSION` constructor; was throwing `ERR_UNKNOWN_FILE_EXTENSION is not a constructor` ([#&#8203;1562](TypeStrong/ts-node#1562)) [@&#8203;bluelovers](https://github.com/bluelovers)
-   Fix [#&#8203;1565](TypeStrong/ts-node#1565): entrypoint resolution failed on node v12.0.x and v12.1.x ([#&#8203;1565](TypeStrong/ts-node#1565), [#&#8203;1566](TypeStrong/ts-node#1566)) [@&#8203;davidmurdoch](https://github.com/davidmurdoch)

#### Docs

-   Explain `env -S` flag for shebangs ([docs](https://typestrong.org/ts-node/docs/usage#shebang)) ([#&#8203;1448](TypeStrong/ts-node#1448), [#&#8203;1545](TypeStrong/ts-node#1545)) [@&#8203;sheeit](https://github.com/sheeit), [@&#8203;chee](https://github.com/chee)
-   Suggest `skipIgnore` when you want to compile files in node_modules ([docs](https://typestrong.org/ts-node/docs/how-it-works)) ([#&#8203;1553](TypeStrong/ts-node#1553)) [@&#8203;webstrand](https://github.com/webstrand)
-   Fix typo in `moduleTypes` on options page ([docs](https://typestrong.org/ts-node/docs/options)) ([#&#8203;1630](TypeStrong/ts-node#1630), [#&#8203;1633](TypeStrong/ts-node#1633))

#### Misc

-   Adds experimental `experimentalResolverFeatures` option, but it does not do anything yet ([#&#8203;1514](TypeStrong/ts-node#1514), [#&#8203;1614](TypeStrong/ts-node#1614))

https://github.com/TypeStrong/ts-node/milestone/4

</details>

---

### Configuration

📅 **Schedule**: At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Co-authored-by: cabr2-bot <[email protected]>
Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1156
Reviewed-by: crapStone <[email protected]>
Co-authored-by: Calciumdibromid Bot <[email protected]>
Co-committed-by: Calciumdibromid Bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants