ember-cli-typescript
ember-cli-typescript copied to clipboard
Type errors crash the build on Ember CLI 3.15+
Edit by @chriskrycho:* original title was "Does not appear to work with Ember 3.27". Updated to reflect the actual underlying issue in Ember CLI.
Please paste the output of ember -v
here
β― ember -v
ember-cli: 3.27.0
node: 12.20.2
os: linux x64
Please paste the output of tsc -v
here
β― yarn tsc -v
Version 4.3.5
Please paste the version of ember-cli-typescript
and ember-cli-typescript-blueprints
here
4.2.1 blueprints package removed
Please paste your tsconfig.json
and tslint.json
or eslint.json
(if applicable) below
default w/ 4.2.1
What are instructions we can follow to reproduce the issue?
Repro is these changes: https://github.com/NullVoxPopuli/ember-play/pull/5/commits/8dcf53e06fd9f40182dd29e0a99aeb8fe8e5a94b
git clone [email protected]:NullVoxPopuli/ember-play.git
git checkout 8dcf53e06fd9f40182dd29e0a99aeb8fe8e5a94b
yarn
ember s
# error! (ember-cli crashes)
Inverse reproduction (fix?): Remove ember-cli-typescript: https://github.com/NullVoxPopuli/ember-play/pull/5/commits/689c0ee0777c6e57e9714f319f8f04bb8c356c63
- Downside: no more type checking working in ember-cli terminal
Now about that bug. What did you expect to see?
This is a WIP PR / Library, but, I expect to still be able to run /tests
while I iterate on implementation and not have to continually restart ec-ts whenever there is an error.
I tried it again after working through the type errors, and it looks like the prepare command also doesn't work
For what it's worth, our app & addons work with ember-source 3.27.5 & latest ember-cli-typescript. So I do not think it is a general issue, but probably some combination of another addon or so.
We also have CI running against stable, beta, and canary as well as all supported LTS releases, and I'm using it in multiple addons which are on 3.27 as well. It'd be helpful if you can get to a minimal reproduction!
Alrighty, I'll do some digging. Thanks!
You didn't include this in the error report, but assuming this is the same as what you're describing in Discord, this log message is relevant:
Stack Trace and Error Report: /tmp/error.dump.f54b0c0bb56928ce98080855828d851b.log
internal/process/promises.js:194
triggerUncaughtException(err, true /* fromPromise */);
^
Error: Typechecking failed
at Class.postBuild (/home/me/Development/NullVoxPopuli/ember-play/node_modules/ember-cli-typescript/js/addon.js:73:19)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async Promise.all (index 0)
at async Builder.build (/home/me/Development/NullVoxPopuli/ember-play/node_modules/ember-cli/lib/models/builder.js:209:7)
That exception is us rejecting the promise we return from postBuild
, which we do by design when noEmitOnError
is enabled. This is how we fail the build for type errors, and hasn't changed since 2.0 iirc.
It's possible something has changed in ember-cli such that promise rejections from that hook aren't being handled, or the rejection handler isn't being immediately set. If it's the latter, we might be able to work around that by artifically delaying when we report a failure, but ultimately it seems like a rejected promise in postBuild
shouldn't cause the whole process to shut down. When Node 15 was first released and unhandled rejections began being treated like uncaught exceptions, I remember this (or something similar) coming up briefly, but I'd thought that was taken care of pretty quickly on the CLI side.
here is a reproduction: https://github.com/NullVoxPopuli/ec-typescript-repro-1439
all I did was add a file with const two: number = 'two';
Log / error file
=================================================================================
ENV Summary:
TIME: Sun Jul 11 2021 08:03:41 GMT-0400 (Eastern Daylight Time)
TITLE: ember
ARGV:
- π /.volta/tools/image/node/16.2.0/bin/node
- /βοΈ/ec-typescript-repro-1439/node_modules/.bin/ember
- s
EXEC_PATH: π /.volta/tools/image/node/16.2.0/bin/node
TMPDIR: /tmp
SHELL: /bin/bash
PATH:
- π /.volta/tools/image/npm/7.7.5/bin
- π /.volta/tools/image/yarn/1.22.5/bin
- π /.volta/tools/image/node/16.2.0/bin
- π /.volta/bin
- π /.pythons/Python-3.6.3/bin
- π /.cargo/bin
- π /Applications
- π /apps/phantomjs/bin
- π /scripts/system-utils
- π /scripts/git
- π /scripts/rails
- π /scripts
- π /.volta/bin
- /usr/local/sbin
- /usr/local/bin
- /usr/sbin
- /usr/bin
- /sbin
- /bin
- /usr/games
- /usr/local/games
- /snap/bin
- π /.dotnet/tools
- π /.dotnet/tools
- π /.fzf/bin
PLATFORM: linux x64
FREEMEM: 281653248
TOTALMEM: 17388208128
UPTIME: 131706.37
LOADAVG: 1.59,0.61,0.31
CPUS:
- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz - 3192
ENDIANNESS: LE
VERSIONS:
- ares: 1.17.1
- brotli: 1.0.9
- cldr: 39.0
- icu: 69.1
- llhttp: 6.0.1
- modules: 93
- napi: 8
- nghttp2: 1.42.0
- nghttp3: 0.1.0-DEV
- ngtcp2: 0.1.0-DEV
- node: 16.2.0
- openssl: 1.1.1k+quic
- tz: 2021a
- unicode: 13.0
- uv: 1.41.0
- v8: 9.0.257.25-node.16
- zlib: 1.2.11
ERROR Summary:
- broccoliBuilderErrorStack: [undefined]
- code: [undefined]
- codeFrame: [undefined]
- errorMessage: Typechecking failed
- errorType: [undefined]
- location:
- column: [undefined]
- file: [undefined]
- line: [undefined]
- message: Typechecking failed
- name: Error
- nodeAnnotation: [undefined]
- nodeName: [undefined]
- originalErrorMessage: [undefined]
- stack: Error: Typechecking failed
at Class.postBuild (/βοΈ/ec-typescript-repro-1439/node_modules/ember-cli-typescript/js/addon.js:73:19)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 0)
at async Builder.build (/βοΈ/ec-typescript-repro-1439/node_modules/ember-cli/lib/models/builder.js:209:7)
=================================================================================
Tangentially, I made a script to make the paths in my error logs a little nicer, in case anyone is interested in doing that (like if you decided to use your full name as your computer's username without realizing how it affects paths in error logs π ) https://github.com/NullVoxPopuli/dotfiles/blob/75ad3987e4eaa550e7dfb70a37ffe2b756594bd9/home/scripts/unme
Things I've tried so far
- deleting the postBuild function in node_modules/ember-cli-typescript/js/addon.js
-
ember s
- let's the build complete without crashing ember-cli
- type error is still reported to the terminal
-
yarn prepack
- errors (expected, because type error)
-
yarn postpack
- succeeds (expected)
-
I went hunting and it looks like the situation is pretty much what I was speculating above. I spun up fresh app with an in-repo addon that returns Promise.reject('uh oh')
from postBuild()
after each even-numbered (re)build.
Here's the output for an initial build and three subsequent rebuilds (so in total, success -> fail -> success -> fail):
[email protected]
, Node 12/16
$ ember serve
Build successful (3376ms) β Serving on http://localhost:7020/
Slowest Nodes (totalTime >= 5%) | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
BroccoliRollup (6) | 693ms (115 ms)
Bundler (1) | 660ms
Babel: @ember/test-helpers (1) | 395ms
Package /assets/vendor.js (1) | 299ms
Babel: ember-source (5) | 254ms (50 ms)
ember-auto-import-analyzer (4) | 216ms (54 ms)
file changed templates/application.hbs
file changed templates/application.hbs
uh oh
file changed templates/application.hbs
Build successful (232ms) β Serving on http://localhost:7020/
Slowest Nodes (totalTime >= 5%) | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
Babel: ember-source (5) | 33ms (6 ms)
ember.js (1) | 30ms
BroccoliMergeTrees (22) | 27ms (1 ms)
Funnel (60) | 22ms (0 ms)
file changed templates/application.hbs
uh oh
[email protected]
, Node 12
$ ember serve
Build successful (3573ms) β Serving on http://localhost:7020/
Slowest Nodes (totalTime >= 5%) | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
Bundler (1) | 777ms
BroccoliRollup (6) | 680ms (113 ms)
Babel: @ember/test-helpers (1) | 379ms
Package /assets/vendor.js (1) | 337ms
Babel: ember-source (5) | 284ms (56 ms)
ember-auto-import-analyzer (4) | 207ms (51 ms)
file changed templates/application.hbs
(node:22890) UnhandledPromiseRejectionWarning: uh oh
(Use `node --trace-warnings ...` to show where the warning was created)
(node:22890) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:22890) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
file changed templates/application.hbs
Build successful (229ms) β Serving on http://localhost:7020/
Slowest Nodes (totalTime >= 5%) | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
Babel: ember-source (5) | 35ms (7 ms)
ember.js (1) | 30ms
BroccoliMergeTrees (22) | 27ms (1 ms)
Funnel (60) | 23ms (0 ms)
file changed templates/application.hbs
(node:22890) UnhandledPromiseRejectionWarning: uh oh
(node:22890) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 6)
[email protected]
, Node 16
$ ember serve WARNING: Node v16.4.2 is not tested against Ember CLI on your platform. We recommend that you use the most-recent "Active LTS" version of Node.js. See https://git.io/v7S5n for details.
Build successful (3616ms) β Serving on http://localhost:7020/
Slowest Nodes (totalTime >= 5%) | Total (avg)
----------------------------------------------------------------------------------------------------------------------------+------------------------------------
BroccoliRollup (6) | 729ms (121 ms)
Bundler (1) | 726ms
Babel: @ember/test-helpers (1) | 444ms
Package /assets/vendor.js (1) | 268ms
Babel: ember-source (5) | 258ms (51 ms)
ember-auto-import-analyzer (4) | 221ms (55 ms)
file changed templates/application.hbs
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "uh oh".] {
code: 'ERR_UNHANDLED_REJECTION'
}
Prior to 3.15, the CLI treated promise rejections in postBuild
as failing the build, so in both older and newer versions of Node, everything works as expected.
Starting in 3.15, a promise returned from postBuild
doesn't get .catch()
ed, meaning the rejection goes unhandled. In older versions of Node, this emits a warning (and seemingly still does fail the build, which is interesting), but in more recent Node versions, that unhandled rejection warning terminates the process.
Like I said above, given that ember-cli does wait for postBuild
promises (i.e. it doesn't just ignore the postBuild
return value), it seems like a bug there that the rejection goes unhandled, and I think the behavior prior to 3.15 was correct.
So is this something that needs to be fixed here or in ember-cli?
This would have to be a change in ember-cli.
it seems this is still broken.
would it not be easier to flip noEmitOnError to false until ember-cli is fixed?
Today, everyone starting a new project will not be able to successfully run ember s
if there exists a type error.
I have this problem and noEmitOnError
is true
.
@dfreeman's comment above suggests that this is intentional when noEmitOnError
is true which feels like exact opposite of what that flag means...
which we do by design when noEmitOnError is enabled.
I think we got the confusion sorted out in Discord, but for anyone else reading along in this thread: noEmitOnError
is a TypeScript configuration option (not something we invented!) that means "do not emit transpiled code when there's a type error."
Since the tsconfig from the blueprint still has noEmitOnError: true
, and this (with current ember-cli) still leads to the build crashing whenever there is a type error, would it make sense to set this to false
in the blueprint? IMHO as it is now, it is not really an acceptable dev experience to have noEmitOnError: true
(I understand why it would be nice to have it, but as long as ember-cli simply kills the server it is not really useful at all).
Also related sidenote, I think there is part of the comment missing there: https://github.com/typed-ember/ember-cli-typescript/blob/master/blueprint-files/ember-cli-typescript/tsconfig.json#L43 it simply ends on "when" ;)
I think weβve stated our position clearly enough before, but Iβm going to state it one more time for the record and then lock the thread:
Disabling that feature in ember-cli-typescript would break many existing users' assumptions, and the bug is not here but upstream. We are not changing the behavior of ember-cli-typescript on this front.
For extra clarity here: the main thing that adding ember-cli-typescript
to your project does is add type checking integration into your build. If you donβt want that, then you can just opt into the corresponding babel config and run tsc
manually yourself!
Added this to the above, but wanted to add it as a comment so folks following via email etc. see it:
For extra clarity here: the main thing that adding
ember-cli-typescript
to your project does is add type checking integration into your build. If you donβt want that, then you can just opt into the corresponding babel config and runtsc
manually yourself!