Skip to content

Commit

Permalink
chore(deps): upgrade to typescript 5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
alicewriteswrongs committed May 16, 2023
1 parent 9364b9f commit 3ac01d4
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 146 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'@stencil/core/mock-doc': '<rootDir>/mock-doc/index.cjs',
'@stencil/core/testing': '<rootDir>/testing/index.js',
'@utils': '<rootDir>/src/utils',
'^typescript$': '<rootDir>/scripts/build/typescript-modified-for-jest.js',
},
coverageDirectory: './coverage/',
coverageReporters: ['json', 'lcov', 'text', 'clover'],
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
"semver": "^7.3.7",
"sizzle": "^2.3.6",
"terser": "5.17.2",
"typescript": "4.9.5",
"typescript": "~5.0.4",
"webpack": "^5.75.0",
"ws": "8.13.0"
},
Expand Down
116 changes: 83 additions & 33 deletions scripts/bundles/plugins/typescript-source-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,57 +62,107 @@ async function bundleTypeScriptSource(tsPath: string, opts: BuildOptions): Promi

// remove the default ts.getDefaultLibFilePath because it uses some
// node apis and we'll be replacing it with our own anyways
code = removeFromSource(code, `ts.getDefaultLibFilePath = getDefaultLibFilePath;`);
// TODO(STENCIL-816): remove in-browser compilation
code = removeFromSource(code, `getDefaultLibFilePath: () => getDefaultLibFilePath,`);

// remove the CPUProfiler since it uses node apis
code = removeFromSource(code, `enableCPUProfiler: enableCPUProfiler,`);
code = removeFromSource(code, `disableCPUProfiler: disableCPUProfiler,`);
// TODO(STENCIL-816): remove in-browser compilation
code = removeFromSource(code, `enableCPUProfiler,`);
// TODO(STENCIL-816): remove in-browser compilation
code = removeFromSource(code, `disableCPUProfiler,`);

// As of 5.0, because typescript is now bundled with esbuild the structure of
// the file we're dealing with here (`lib/typescript.js`) has changed.
// Previously there was an iife which got an object as an argument and just
// stuck properties onto it, something like
//
// ```js
// var ts = (function (ts) {
// ts.someMethod = () => { ... };
// })(ts || ts = {});
// ```
//
// as of 5.0 it instead looks (conceptually) something like:
//
// ```js
// var ts = (function () {
// const ts = {}
// const define = (name, value) => {
// Object.defineProperty(ts, name, value, { enumerable: true })
// }
// define('someMethod', () => { ... })
// return ts;
// })();
// ```
//
// Note that the call to `Object.defineProperty` does not set `configurable` to `true`
// (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#description)
// which means that later calls to do something like
//
// ```ts
// import ts from 'typescript';
//
// ts.someMethod = function myReplacementForSomeMethod () {
// ...
// };
// ```
//
// will fail because without `configurable: true` you can't re-assign
// properties.
//
// All well and good, except for the fact that our patching of typescript to
// use for instance the in-memory file system depends on us being able to
// monkey-patch typescript in exactly this way. So in order to retain our
// current approach to patching TypeScript we need to edit this file in order
// to add `configurable: true` to the options passed to
// `Object.defineProperty`:
const TS_PROP_DEFINER = `__defProp(target, name, { get: all[name], enumerable: true });`;
const TS_PROP_DEFINER_RECONFIGURABLE = `__defProp(target, name, { get: all[name], enumerable: true, configurable: true });`;

code = code.replace(TS_PROP_DEFINER, TS_PROP_DEFINER_RECONFIGURABLE);

const jestTypesciptFilename = join(opts.scriptsBuildDir, 'typescript-modified-for-jest.js');
await fs.writeFile(jestTypesciptFilename, code);

// Here we transform the TypeScript source from a commonjs to an ES module.
// We do this so that we can add an import from the `@environment` module.

// trim off the last part that sets module.exports and polyfills globalThis since
// we don't want typescript to add itself to module.exports when in a node env
const tsEnding = `})(ts || (ts = {}));`;
const tsEnding = `if (typeof module !== "undefined" && module.exports) { module.exports = ts; }`;

if (!code.includes(tsEnding)) {
throw new Error(`"${tsEnding}" not found`);
}
const lastEnding = code.lastIndexOf(tsEnding);
code = code.slice(0, lastEnding + tsEnding.length);

// there's a billion unnecessary "var ts;" for namespaces
// but we'll be using the top level "const ts" instead
code = code.replace(/var ts;/g, '');
code = code.slice(0, lastEnding);

// minification is crazy better if it doesn't use typescript's
// namespace closures, like (function(ts) {...})(ts = ts || {});
code = code.replace(/ \|\| \(ts \= \{\}\)/g, '');

// make a nice clean default export
// "process.browser" is used by typescript to know if it should use the node sys or not
const o: string[] = [];
o.push(`// TypeScript ${opts.typescriptVersion}`);
o.push(`import { IS_NODE_ENV } from '@environment';`);
o.push(`process.browser = !IS_NODE_ENV;`);
o.push(`const ts = {};`);
o.push(code);
o.push(`export default ts;`);
code = o.join('\n');

const { minify } = await import('terser');

if (opts.isProd) {
const minified = await minify(code, {
ecma: 2018,
module: true,
compress: {
ecma: 2018,
passes: 2,
},
format: {
ecma: 2018,
comments: false,
},
});
code = minified.code;
}
// TODO(STENCIL-839): investigate minification issue w/ typescript 5.0
// const { minify } = await import('terser');

// if (opts.isProd) {
// const minified = await minify(code, {
// ecma: 2018,
// // module: true,
// compress: {
// ecma: 2018,
// passes: 2,
// },
// format: {
// ecma: 2018,
// comments: false,
// },
// });
// code = minified.code;
// }

await fs.writeFile(cacheFile, code);

Expand Down
13 changes: 12 additions & 1 deletion src/compiler/sys/typescript/typescript-sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,12 @@ export const getTypescriptPathFromUrl = (config: d.Config, tsExecutingUrl: strin
export const patchTypeScriptGetParsedCommandLineOfConfigFile = () => {
const orgGetParsedCommandLineOfConfigFile = ts.getParsedCommandLineOfConfigFile;

ts.getParsedCommandLineOfConfigFile = (configFileName, optionsToExtend, host, extendedConfigCache) => {
const patchedFunc = (
configFileName: string,
optionsToExtend: ts.CompilerOptions,
host: ts.ParseConfigFileHost,
extendedConfigCache: Map<string, ts.ExtendedConfigCacheEntry>
) => {
const results = orgGetParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host, extendedConfigCache);

// manually filter out any .spec or .e2e files
Expand All @@ -265,4 +270,10 @@ export const patchTypeScriptGetParsedCommandLineOfConfigFile = () => {

return results;
};

Object.defineProperty(ts, 'getParsedCommandLineOfConfigFile', {
get: () => patchedFunc,
enumerable: true,
configurable: true,
});
};
Loading

0 comments on commit 3ac01d4

Please sign in to comment.