build: add ts support in core modules#62146
build: add ts support in core modules#62146marco-ippolito wants to merge 2 commits intonodejs:mainfrom
Conversation
|
Review requested:
|
7a1197a to
f42cbf2
Compare
|
@marco-ippolito do you know what steps are needed to run and expose Rust code just like C++? |
its already done in this PR, see d9ee95f basically add the crate in the deps/crates cargo.toml, create a header file if doesnt come with the crate and add it to the node gyp |
|
Will this type strip at runtime? Or will it do it at build time? |
Build time |
|
How does this interact with the --node-builtin-modules-path flag? will it still type strip at runtime in that case? |
Yes, I tested it, it works fine. it plugs in the js2c module |
|
I'm relatively concerned about adding 1 million and 300 hundred thousand lines of code, even if they are just dependencies. Is there a solution that does not require this much? |
|
I dont think so since we are vendoring dependencies. I think the only solution is to have an automation generate them but its kinda impossible to review anyways. (The temporal PR from @legendecas had the same problem) |
|
I think the question should be is it necessary to have every swc dependencies to be included? I listed the newly added dependencies, and the followings are the biggest deps that I doubt if they are required: Additionally, crates like I think technically many of these deps can be stripped down. |
|
Can I just like delete them and see if it builds? |
fa87310 to
499c817
Compare
|
I tried to remove those crates but it seems they are all required to build. Idk if there is a way to know exactly which ones are unused or how to remove them, I'm no rust expert |
499c817 to
e9d6146
Compare
|
This is blocked by nodejs/build#4245 |
41e67c1 to
9a90466
Compare
|
@marco-ippolito this works on pure v8 cli: Without bundling, with v8 CLI (async function() {
class TextEncoder {} // only constructed, not actually used
class TextDecoder {
constructor(encoding = "utf-8", options = {}) {
if (encoding !== 'utf-8' || !options.ignoreBOM) throw new Error('Unexpected')
}
decode(input = new Uint8Array(), options) {
if (!(input instanceof Uint8Array) || options) throw new Error('Unexpected')
return decodeURIComponent(escape(String.fromCharCode.apply(String, input)));
}
};
const Amaro = globalThis.module = {}
globalThis.require = (arg) => {
if (arg === 'util') return { TextEncoder, TextDecoder }
if (arg === 'node:buffer') return {
Buffer: {
from: (x, encoding) => {
if (encoding === 'base64') return Uint8Array.fromBase64(x)
throw new Error('Unexpected')
}
}
}
throw new Error('Unexpected')
}
await import('./node_modules/amaro/dist/index.js')
const { code } = Amaro.exports.transformSync("const foo: string = 'bar';", { mode: "strip-only" });
console.log(code);
})();chalker@macbook-air _test % ~/.jsvu/bin/v8 tempout.cjs
const foo = 'bar'; |
If we could run this in the js2c.cc, we could skip completely the rust dependency |
The blast radius of this would be way too great to justify the effort on the ecosystem side. There is a lot of code that depends on this pattern, and updating it all is going to be problematic: even if we deprecate, most developers won't know how to deal with it because it's buried under 10 levels on dependencies on a module that hasn't been updated since 2016. Unless there is a clear reason (like security in the case of |
Note that this would not work on cross compiled jobs without setting up emulation - this was the reason why releases on a couple of platforms didn’t have code cache or snapshots, as building those require setting up emulation. Not impossible to do, just needs more work on the build side, though I imagine for experimental architectures like RISC-V it might be even harder. |
Apart from the breakage, until all supported release lines can assume rust toolchain support, moving the files can create a lot of conflicts for backports. e.g. here we changed a .js file to .ts file, it means all subsequent changes to that .ts file on main may require manual backports for releases that do not have support for this, and new files authored in .ts all need manual backports too. If the toolchain requirement needs to be semver-major, it would be safer to only touch existing files until all supported release lines can compile them, and take care with the semverness of all ts-related changes on main. |
Still better than importing over a million LoC I think? This just needs v8 to run, anywhere, at build time. Not necessary on target platform.
The proposed solution with using v8 + amaro does not need rust toolchain support. |
5c971a2 to
de79302
Compare
02b1b1e to
7c56d2a
Compare
|
Please take a look again, removed the rust dependency, it uses v8 to load amaro and strip types. |
7c56d2a to
8f4277b
Compare
|
Is this full typescript or type-erasible typescript? I'm +1 on supporting the type-erasible typescript subset but somewhat -1 on using full typescript syntax in core. I don't block if folks really insist on it but I generally believe the erasible syntax approach to be by far the safer option. |
|
|
||
| class TextEncoder { | ||
| encode(input = '') { | ||
| return encodeUtf8(input); |
There was a problem hiding this comment.
It should be noted that unlike TextEncoder API this implementation expects an actual USVString and throws otherwise
While TextEncoder accepts DOMString which it silently converts to USVString
It adds a throw but it's ok for internal usage
Erasable syntax, it will throw on transformation |
|
This is unfortunately going down an X-Y problem path. The objective behind this proposal is to facilitate typechecking in core modules. Absolutely no objection here! However, the proposed change itself relies on the assumption that the TypeScript language service treats TS the same as JS, just with typechecking. This is not correct. TypeScript can work with both
Any module in core renamed to This can be seen with the
As previously mentioned, we have access to typechecking with the TypeScript language service in |
|
Did |
It's the same deal. It still necessitates |
|
What benefits are we getting from |
|
Having typescript syntax is worth even if we cannot typecheck everything. @Renegade334 if you feel strongly please request changes. |
The primary goal is the typechecking, not TS syntax in of itself. Renegade334/node@main...typed-core would be the alternative route, providing typechecking via the TypeScript compiler without the pitfalls associated with
I was rather hoping to sway the consensus without having to reach for the red X 🙂 |
Let's try again.
This PR allows Node.js source code to be written in TS.
This is semver major because the build now always requires rust to be installed.
This adds swc as a rust crate dependency and it's only use during build time.
Technically we could replace amaro wasm with this for type stripping but it's not the goal of this PR and in needs other considerations.
I moved an internal from .js and .ts to showcase
Also added a flag so that the transpiled code can be writte on the fs for debugging.
A lot of the addition are vendored crates sorry for the massive PR
I used AI to help me out with things I dont know (rust) so please review carefully
I had to bump the rustc from 1.82 to 1.85, obviously this cannot land if we dont update that on the CI machines nodejs/build#4245