Skip to content

Commit 754c6c2

Browse files
committed
Merge branch 'main' into fewer-files
2 parents b993aca + 021fd20 commit 754c6c2

File tree

295 files changed

+11357
-10252
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

295 files changed

+11357
-10252
lines changed

.eslintrc.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"es6": true
1212
},
1313
"plugins": [
14-
"@typescript-eslint", "jsdoc", "no-null", "import", "eslint-plugin-local"
14+
"@typescript-eslint", "no-null", "import", "eslint-plugin-local"
1515
],
1616
"ignorePatterns": [
1717
"**/node_modules/**",
@@ -107,9 +107,6 @@
107107
// eslint-plugin-no-null
108108
"no-null/no-null": "error",
109109

110-
// eslint-plugin-jsdoc
111-
"jsdoc/check-alignment": "error",
112-
113110
// eslint
114111
"constructor-super": "error",
115112
"curly": ["error", "multi-line"],

.github/workflows/ci.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,66 @@ jobs:
8686
- name: Build src
8787
run: npx hereby build-src
8888

89+
smoke:
90+
runs-on: ubuntu-latest
91+
92+
steps:
93+
- uses: actions/checkout@v3
94+
- uses: actions/setup-node@v3
95+
with:
96+
node-version: "*"
97+
check-latest: true
98+
- run: npm ci
99+
100+
- run: npx hereby lkg
101+
- run: |
102+
npm pack
103+
mv typescript*.tgz typescript.tgz
104+
echo "PACKAGE=$PWD/typescript.tgz" >> $GITHUB_ENV
105+
106+
- name: Smoke test
107+
run: |
108+
cd "$(mktemp -d)"
109+
npm init --yes
110+
npm install $PACKAGE tslib
111+
112+
npx tsc --version
113+
echo '{"seq": 1, "command": "status"}' | npx tsserver
114+
115+
cat > smoke.js << EOF
116+
const { __importDefault, __importStar } = require("tslib");
117+
const ts = require(process.argv[2]);
118+
119+
// See: https://github.com/microsoft/TypeScript/pull/51474#issuecomment-1310871623
120+
const fns = [
121+
[() => ts.version, true],
122+
[() => ts.default.version, false],
123+
[() => __importDefault(ts).version, false],
124+
[() => __importDefault(ts).default.version, true],
125+
[() => __importStar(ts).version, true],
126+
[() => __importStar(ts).default.version, true],
127+
];
128+
129+
for (const [fn, shouldSucceed] of fns) {
130+
let success = false;
131+
try {
132+
success = !!fn();
133+
}
134+
catch {}
135+
if (success !== shouldSucceed) {
136+
if (success) {
137+
console.error(`${fn.toString()} unexpectedly succeeded.`);
138+
}
139+
else {
140+
console.error(`${fn.toString()} did not succeed.`);
141+
}
142+
process.exitCode = 1;
143+
}
144+
}
145+
EOF
146+
147+
node ./smoke.js typescript
148+
node ./smoke.js typescript/lib/tsserverlibrary
89149
90150
misc:
91151
runs-on: ubuntu-latest

Herebyfile.mjs

Lines changed: 145 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ import { task } from "hereby";
66
import _glob from "glob";
77
import util from "util";
88
import chalk from "chalk";
9-
import { exec, readJson, getDiffTool, getDirSize, memoize, needsUpdate } from "./scripts/build/utils.mjs";
10-
import { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } from "./scripts/build/tests.mjs";
9+
import { exec, readJson, getDiffTool, getDirSize, memoize, needsUpdate, Debouncer, Deferred } from "./scripts/build/utils.mjs";
10+
import { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline, cleanTestDirs } from "./scripts/build/tests.mjs";
1111
import { buildProject as realBuildProject, cleanProject, watchProject } from "./scripts/build/projects.mjs";
1212
import { localizationDirectories } from "./scripts/build/localization.mjs";
1313
import cmdLineOptions from "./scripts/build/options.mjs";
1414
import esbuild from "esbuild";
15+
import chokidar from "chokidar";
16+
import { EventEmitter } from "events";
17+
import { CancelToken } from "@esfx/canceltoken";
1518

1619
const glob = util.promisify(_glob);
1720

@@ -141,7 +144,7 @@ const localize = task({
141144
dependencies: [generateDiagnostics],
142145
run: async () => {
143146
if (needsUpdate(diagnosticMessagesGeneratedJson, generatedLCGFile)) {
144-
return exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.mjs", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true });
147+
await exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.mjs", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true });
145148
}
146149
}
147150
});
@@ -191,6 +194,7 @@ async function runDtsBundler(entrypoint, output) {
191194
* @property {string[]} [external]
192195
* @property {boolean} [exportIsTsObject]
193196
* @property {boolean} [treeShaking]
197+
* @property {esbuild.WatchMode} [watchMode]
194198
*/
195199
function createBundler(entrypoint, outfile, taskOptions = {}) {
196200
const getOptions = memoize(async () => {
@@ -269,7 +273,7 @@ function createBundler(entrypoint, outfile, taskOptions = {}) {
269273

270274
return {
271275
build: async () => esbuild.build(await getOptions()),
272-
watch: async () => esbuild.build({ ...await getOptions(), watch: true, logLevel: "info" }),
276+
watch: async () => esbuild.build({ ...await getOptions(), watch: taskOptions.watchMode ?? true, logLevel: "info" }),
273277
};
274278
}
275279

@@ -320,7 +324,7 @@ function entrypointBuildTask(options) {
320324
const outDir = path.dirname(options.output);
321325
await fs.promises.mkdir(outDir, { recursive: true });
322326
const moduleSpecifier = path.relative(outDir, options.builtEntrypoint);
323-
await fs.promises.writeFile(options.output, `module.exports = require("./${moduleSpecifier}")`);
327+
await fs.promises.writeFile(options.output, `module.exports = require("./${moduleSpecifier.replace(/[\\/]/g, "/")}")`);
324328
},
325329
});
326330

@@ -354,7 +358,7 @@ function entrypointBuildTask(options) {
354358
}
355359

356360

357-
const { main: tsc, watch: watchTsc } = entrypointBuildTask({
361+
const { main: tsc, build: buildTsc, watch: watchTsc } = entrypointBuildTask({
358362
name: "tsc",
359363
description: "Builds the command-line compiler",
360364
buildDeps: [generateDiagnostics],
@@ -386,13 +390,13 @@ export const dtsServices = task({
386390
dependencies: [buildServices],
387391
run: async () => {
388392
if (needsUpdate("./built/local/typescript/tsconfig.tsbuildinfo", ["./built/local/typescript.d.ts", "./built/local/typescript.internal.d.ts"])) {
389-
runDtsBundler("./built/local/typescript/typescript.d.ts", "./built/local/typescript.d.ts");
393+
await runDtsBundler("./built/local/typescript/typescript.d.ts", "./built/local/typescript.d.ts");
390394
}
391395
},
392396
});
393397

394398

395-
const { main: tsserver, watch: watchTsserver } = entrypointBuildTask({
399+
const { main: tsserver, build: buildTsserver, watch: watchTsserver } = entrypointBuildTask({
396400
name: "tsserver",
397401
description: "Builds the language server",
398402
buildDeps: [generateDiagnostics],
@@ -410,10 +414,15 @@ const { main: tsserver, watch: watchTsserver } = entrypointBuildTask({
410414
export { tsserver, watchTsserver };
411415

412416

417+
const buildMin = task({
418+
name: "build-min",
419+
dependencies: [buildTsc, buildTsserver],
420+
});
421+
413422
export const min = task({
414423
name: "min",
415424
description: "Builds only tsc and tsserver",
416-
dependencies: [tsc, tsserver],
425+
dependencies: [tsc, tsserver].concat(cmdLineOptions.typecheck ? [buildMin] : []),
417426
});
418427

419428
export const watchMin = task({
@@ -456,7 +465,7 @@ export const dts = task({
456465

457466

458467
const testRunner = "./built/local/run.js";
459-
468+
const watchTestsEmitter = new EventEmitter();
460469
const { main: tests, watch: watchTests } = entrypointBuildTask({
461470
name: "tests",
462471
description: "Builds the test infrastructure",
@@ -477,6 +486,11 @@ const { main: tests, watch: watchTests } = entrypointBuildTask({
477486
"mocha",
478487
"ms",
479488
],
489+
watchMode: {
490+
onRebuild() {
491+
watchTestsEmitter.emit("rebuild");
492+
}
493+
}
480494
},
481495
});
482496
export { tests, watchTests };
@@ -577,10 +591,15 @@ export const watchOtherOutputs = task({
577591
dependencies: [watchCancellationToken, watchTypingsInstaller, watchWatchGuard, generateTypesMap, copyBuiltLocalDiagnosticMessages],
578592
});
579593

594+
const buildLocal = task({
595+
name: "build-local",
596+
dependencies: [buildTsc, buildTsserver, buildServices, buildLssl]
597+
});
598+
580599
export const local = task({
581600
name: "local",
582601
description: "Builds the full compiler and services",
583-
dependencies: [localize, tsc, tsserver, services, lssl, otherOutputs, dts, buildSrc],
602+
dependencies: [localize, tsc, tsserver, services, lssl, otherOutputs, dts].concat(cmdLineOptions.typecheck ? [buildLocal] : []),
584603
});
585604
export default local;
586605

@@ -591,11 +610,12 @@ export const watchLocal = task({
591610
dependencies: [localize, watchTsc, watchTsserver, watchServices, watchLssl, watchOtherOutputs, dts, watchSrc],
592611
});
593612

613+
const runtestsDeps = [tests, generateLibs].concat(cmdLineOptions.typecheck ? [dts, buildSrc] : []);
594614

595615
export const runTests = task({
596616
name: "runtests",
597617
description: "Runs the tests using the built run.js file.",
598-
dependencies: [tests, generateLibs, dts, buildSrc],
618+
dependencies: runtestsDeps,
599619
run: () => runConsoleTests(testRunner, "mocha-fivemat-progress-reporter", /*runInParallel*/ false),
600620
});
601621
// task("runtests").flags = {
@@ -614,10 +634,121 @@ export const runTests = task({
614634
// " --shardId": "1-based ID of this shard (default: 1)",
615635
// };
616636

637+
export const runTestsAndWatch = task({
638+
name: "runtests-watch",
639+
dependencies: [watchTests],
640+
run: async () => {
641+
if (!cmdLineOptions.tests && !cmdLineOptions.failed) {
642+
console.log(chalk.redBright(`You must specifiy either --tests/-t or --failed to use 'runtests-watch'.`));
643+
return;
644+
}
645+
646+
let watching = true;
647+
let running = true;
648+
let lastTestChangeTimeMs = Date.now();
649+
let testsChangedDeferred = /** @type {Deferred<void>} */(new Deferred());
650+
let testsChangedCancelSource = CancelToken.source();
651+
652+
const testsChangedDebouncer = new Debouncer(1_000, endRunTests);
653+
const testCaseWatcher = chokidar.watch([
654+
"tests/cases/**/*.*",
655+
"tests/lib/**/*.*",
656+
"tests/projects/**/*.*",
657+
], {
658+
ignorePermissionErrors: true,
659+
alwaysStat: true
660+
});
661+
662+
process.on("SIGINT", endWatchMode);
663+
process.on("SIGKILL", endWatchMode);
664+
process.on("beforeExit", endWatchMode);
665+
watchTestsEmitter.on("rebuild", onRebuild);
666+
testCaseWatcher.on("all", onChange);
667+
668+
while (watching) {
669+
const promise = testsChangedDeferred.promise;
670+
const token = testsChangedCancelSource.token;
671+
if (!token.signaled) {
672+
running = true;
673+
try {
674+
await runConsoleTests(testRunner, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, { token, watching: true });
675+
}
676+
catch {
677+
// ignore
678+
}
679+
running = false;
680+
}
681+
if (watching) {
682+
console.log(chalk.yellowBright(`[watch] test run complete, waiting for changes...`));
683+
await promise;
684+
}
685+
}
686+
687+
function onRebuild() {
688+
beginRunTests(testRunner);
689+
}
690+
691+
/**
692+
* @param {'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'} eventName
693+
* @param {string} path
694+
* @param {fs.Stats | undefined} stats
695+
*/
696+
function onChange(eventName, path, stats) {
697+
switch (eventName) {
698+
case "change":
699+
case "unlink":
700+
case "unlinkDir":
701+
break;
702+
case "add":
703+
case "addDir":
704+
// skip files that are detected as 'add' but haven't actually changed since the last time tests were
705+
// run.
706+
if (stats && stats.mtimeMs <= lastTestChangeTimeMs) {
707+
return;
708+
}
709+
break;
710+
}
711+
beginRunTests(path);
712+
}
713+
714+
/**
715+
* @param {string} path
716+
*/
717+
function beginRunTests(path) {
718+
if (testsChangedDebouncer.empty) {
719+
console.log(chalk.yellowBright(`[watch] tests changed due to '${path}', restarting...`));
720+
if (running) {
721+
console.log(chalk.yellowBright("[watch] aborting in-progress test run..."));
722+
}
723+
testsChangedCancelSource.cancel();
724+
testsChangedCancelSource = CancelToken.source();
725+
}
726+
727+
testsChangedDebouncer.enqueue();
728+
}
729+
730+
function endRunTests() {
731+
lastTestChangeTimeMs = Date.now();
732+
testsChangedDeferred.resolve();
733+
testsChangedDeferred = /** @type {Deferred<void>} */(new Deferred());
734+
}
735+
736+
function endWatchMode() {
737+
if (watching) {
738+
watching = false;
739+
console.log(chalk.yellowBright("[watch] exiting watch mode..."));
740+
testsChangedCancelSource.cancel();
741+
testCaseWatcher.close();
742+
watchTestsEmitter.off("rebuild", onRebuild);
743+
}
744+
}
745+
},
746+
});
747+
617748
export const runTestsParallel = task({
618749
name: "runtests-parallel",
619750
description: "Runs all the tests in parallel using the built run.js file.",
620-
dependencies: [tests, generateLibs, dts, buildSrc],
751+
dependencies: runtestsDeps,
621752
run: () => runConsoleTests(testRunner, "min", /*runInParallel*/ cmdLineOptions.workers > 1),
622753
});
623754
// task("runtests-parallel").flags = {
@@ -715,7 +846,7 @@ export const importDefinitelyTypedTests = task({
715846
export const produceLKG = task({
716847
name: "LKG",
717848
description: "Makes a new LKG out of the built js files",
718-
dependencies: [localize, tsc, tsserver, services, lssl, otherOutputs, dts],
849+
dependencies: [local],
719850
run: async () => {
720851
if (!cmdLineOptions.bundle) {
721852
throw new Error("LKG cannot be created when --bundle=false");

0 commit comments

Comments
 (0)