-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathsetup-ts-execution.js
134 lines (112 loc) Β· 3.82 KB
/
setup-ts-execution.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const crypto = require(`crypto`);
const esbuild = require(`esbuild-wasm`);
const fs = require(`fs`);
const path = require(`path`);
const pirates = require(`pirates`);
const v8 = require(`v8`);
const zlib = require(`zlib`);
/**
* There is an issue on Windows with Node.js v14 (tested v14.19.2 and v14.21.2) where
* ```sh
* node esbuild-wasm\bin\esbuild --service=0.17.5 --ping
* ```
* uses up to 400% CPU and 3.62 GB RAM for a while when an ESM loader is enabled.
*
* ```console
* $ time NODE_OPTIONS="--require ./.pnp.cjs --loader ./.pnp.loader.mjs" node -p "require('esbuild-wasm').transformSync('let foo = 0;')"
* {
* warnings: [],
* code: 'let foo = 0;\n',
* map: '',
* mangleCache: undefined,
* legalComments: undefined
* }
*
* ________________________________________________________
* Executed in 54.99 secs fish external
* usr time 0.00 micros 0.00 micros 0.00 micros
* sys time 0.00 micros 0.00 micros 0.00 micros
* ```
*
* Reported upstream in https://github.com/evanw/esbuild/issues/2888 and seems to boil down to https://github.com/nodejs/node/issues/36616.
*
* To workaround this issue we remove the loader from the NODE_OPTIONS since it's not needed in this case.
*/
if (process.env.NODE_OPTIONS) {
const esmLoaderExpression = /\s*--experimental-loader\s+\S*\.pnp\.loader\.mjs\s*/;
process.env.NODE_OPTIONS = process.env.NODE_OPTIONS.replace(esmLoaderExpression, ` `);
}
// Needed by the worker spawned by esbuild
if (process.versions.pnp)
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ``} -r ${JSON.stringify(require.resolve(`pnpapi`))}`;
const resolveVirtual = process.versions.pnp
? require(`pnpapi`).resolveVirtual
: undefined;
// esbuild only supports major.minor.patch, no pre-release (nightly) specifier is allowed
// so we reduce the version down to major.minor
const NODE_VERSION = process.versions.node.split(`.`, 2).join(`.`);
const cache = {
version: `${esbuild.version}\0${NODE_VERSION}`,
files: new Map(),
isDirty: false,
};
const cachePath = path.join(__dirname, `../node_modules/.cache/yarn/esbuild-transpile-cache.bin`);
try {
const cacheData = v8.deserialize(zlib.brotliDecompressSync(fs.readFileSync(cachePath)));
if (cacheData.version === cache.version) {
cache.files = cacheData.files;
}
} catch {}
function persistCache() {
if (!cache.isDirty)
return;
cache.isDirty = false;
const data = v8.serialize({
version: cache.version,
files: cache.files,
});
fs.mkdirSync(path.dirname(cachePath), {recursive: true});
const tmpPath = cachePath + crypto.randomBytes(8).toString(`hex`);
fs.writeFileSync(tmpPath, zlib.brotliCompressSync(data, {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 4,
},
}));
fs.renameSync(tmpPath, cachePath);
}
process.once(`exit`, persistCache);
process.nextTick(persistCache);
process.setSourceMapsEnabled?.(true);
function compileFile(sourceCode, filename) {
filename = resolveVirtual?.(filename) ?? filename;
const cacheEntry = cache.files.get(filename);
if (cacheEntry?.source === sourceCode)
return cacheEntry.code;
const res = esbuild.transformSync(sourceCode, {
target: `node${NODE_VERSION}`,
loader: path.extname(filename).slice(1),
sourcefile: filename,
sourcemap: `inline`,
platform: `node`,
format: `cjs`,
supported: {
'dynamic-import': false,
},
});
cache.isDirty = true;
cache.files.set(filename, {
source: sourceCode,
code: res.code,
});
return res.code;
}
pirates.addHook(compileFile, {
extensions: [`.tsx`, `.ts`, `.js`],
matcher(p) {
if (p?.endsWith(`.js`)) {
const normalizedP = p.replace(/\\/g, `/`);
return normalizedP.includes(`packages/yarnpkg-pnp/sources/node`) || normalizedP.endsWith(`packages/yarnpkg-pnp/sources/loader/node-options.js`);
}
return true;
},
});