Skip to content
Draft
3 changes: 2 additions & 1 deletion scripts/build/options.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import os from "os";
const ci = ["1", "true"].includes(process.env.CI ?? "");

const parsed = minimist(process.argv.slice(2), {
boolean: ["dirty", "light", "colors", "lkg", "soft", "fix", "failed", "keepFailed", "force", "built", "ci", "bundle", "typecheck", "lint", "coverage"],
boolean: ["dirty", "light", "colors", "lkg", "soft", "fix", "failed", "keepFailed", "force", "built", "ci", "bundle", "typecheck", "lint", "coverage", "bail"],
string: ["browser", "tests", "break", "host", "reporter", "stackTraceLimit", "timeout", "shards", "shardId"],
alias: {
b: "browser",
Expand Down Expand Up @@ -66,6 +66,7 @@ export default options;
* @property {boolean} built
* @property {boolean} soft
* @property {boolean} fix
* @property {boolean} bail
* @property {string} browser
* @property {string} tests
* @property {boolean} skipSysTests
Expand Down
1 change: 1 addition & 0 deletions scripts/build/tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export async function runConsoleTests(runJs, defaultReporter, runInParallel, opt
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
if (!runInParallel) {
args.push(mochaJs);
if (cmdLineOptions.bail) args.push("--bail");
args.push("-R", findUpFile("scripts/failed-tests.cjs"));
args.push("-O", '"reporter=' + reporter + (keepFailed ? ",keepFailed=true" : "") + '"');
if (tests) {
Expand Down
110 changes: 83 additions & 27 deletions scripts/dtsBundler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -307,33 +307,61 @@ function symbolsConflict(s1, s2) {
*/
function verifyMatchingSymbols(decl, isInternal) {
ts.visitEachChild(decl, /** @type {(node: ts.Node) => ts.Node} */ function visit(node) {
if (ts.isIdentifier(node) && ts.isPartOfTypeNode(node)) {
if (ts.isQualifiedName(node.parent) && node !== node.parent.left) {
return node;
}
if (ts.isParameter(node.parent) && node === node.parent.name) {
return node;
if (ts.isIdentifier(node)) {
let meaning = ts.SymbolFlags.None;
if (ts.isPartOfTypeNode(node)) {
if (ts.isQualifiedName(node.parent) && node !== node.parent.left) {
return node;
}
if (ts.isParameter(node.parent) && node === node.parent.name) {
return node;
}
if (ts.isNamedTupleMember(node.parent) && node === node.parent.name) {
return node;
}
meaning = ts.SymbolFlags.Type;
}
if (ts.isNamedTupleMember(node.parent) && node === node.parent.name) {
return node;
else if (ts.isExpressionWithTypeArguments(node.parent) &&
ts.isHeritageClause(node.parent.parent) &&
ts.isClassLike(node.parent.parent.parent)) {
meaning = ts.SymbolFlags.Value;
}

const symbolOfNode = typeChecker.getSymbolAtLocation(node);
if (!symbolOfNode) {
fail(`No symbol for node at ${nodeToLocation(node)}`);
}
const symbolInScope = findInScope(symbolOfNode.name);
if (!symbolInScope) {
if (symbolOfNode.declarations?.every(d => isLocalDeclaration(d) && d.getSourceFile() === decl.getSourceFile()) && !isSelfReference(node, symbolOfNode)) {
// The symbol is a local that needs to be copied into the scope.
scopeStack[scopeStack.length - 1].locals.set(symbolOfNode.name, { symbol: symbolOfNode, writeTarget: isInternal ? WriteTarget.Internal : WriteTarget.Both });
if (meaning) {
const symbolOfNode = typeChecker.getSymbolAtLocation(node);
if (!symbolOfNode) {
fail(`No symbol for node at ${nodeToLocation(node)}`);
}
const symbolInScope = findInScope(symbolOfNode.name);
if (!symbolInScope) {
/** @type {ts.Declaration[]} */
const declarations = [];
if (meaning === ts.SymbolFlags.Type && symbolOfNode.declarations) {
declarations.push(...symbolOfNode.declarations);
}
else if (meaning === ts.SymbolFlags.Value && symbolOfNode.valueDeclaration) {
declarations.push(symbolOfNode.valueDeclaration);
}
if (declarations.every(d => isLocalDeclaration(d) && d.getSourceFile() === decl.getSourceFile()) && !isSelfReference(node, symbolOfNode)) {
// The symbol is a local that needs to be copied into the scope.
const locals = scopeStack[scopeStack.length - 1].locals;
if (!locals.has(symbolOfNode.name)) {
locals.set(symbolOfNode.name, { symbol: symbolOfNode, writeTarget: isInternal ? WriteTarget.Internal : WriteTarget.Both });
if (symbolOfNode.valueDeclaration) {
const statement = getDeclarationStatement(symbolOfNode.valueDeclaration);
if (statement) {
verifyMatchingSymbols(statement, isInternal);
}
}
}
}
// We didn't find the symbol in scope at all. Just allow it and we'll fail at test time.
return node;
}

if (symbolsConflict(symbolOfNode, symbolInScope)) {
fail(`Declaration at ${nodeToLocation(decl)}\n references ${symbolOfNode.name} at ${symbolOfNode.declarations && nodeToLocation(symbolOfNode.declarations[0])},\n but containing scope contains a symbol with the same name declared at ${symbolInScope.declarations && nodeToLocation(symbolInScope.declarations[0])}`);
}
// We didn't find the symbol in scope at all. Just allow it and we'll fail at test time.
return node;
}

if (symbolsConflict(symbolOfNode, symbolInScope)) {
fail(`Declaration at ${nodeToLocation(decl)}\n references ${symbolOfNode.name} at ${symbolOfNode.declarations && nodeToLocation(symbolOfNode.declarations[0])},\n but containing scope contains a symbol with the same name declared at ${symbolInScope.declarations && nodeToLocation(symbolInScope.declarations[0])}`);
}
}

Expand All @@ -345,9 +373,10 @@ function verifyMatchingSymbols(decl, isInternal) {
* @param {ts.Declaration} decl
*/
function isLocalDeclaration(decl) {
return ts.canHaveModifiers(decl)
&& !ts.getModifiers(decl)?.some(m => m.kind === ts.SyntaxKind.ExportKeyword)
&& !!getDeclarationStatement(decl);
const statement = getDeclarationStatement(decl);
return !!statement
&& ts.canHaveModifiers(statement)
&& !ts.getModifiers(statement)?.some(m => m.kind === ts.SyntaxKind.ExportKeyword);
}

/**
Expand Down Expand Up @@ -456,7 +485,34 @@ function emitAsNamespace(name, parent, moduleSymbol, needExportModifier) {
symbol.declarations?.forEach(decl => {
// We already checked that getDeclarationStatement(decl) works for each declaration.
const statement = getDeclarationStatement(decl);
writeNode(/** @type {ts.Statement} */ (statement), decl.getSourceFile(), writeTarget);
if (!statement) return;

if (writeTarget & WriteTarget.Public) {
if (!ts.isInternalDeclaration(statement)) {
const publicStatement = ts.visitEachChild(statement, node => {
// No @internal comments in the public API.
if (ts.isInternalDeclaration(node)) {
return undefined;
}
// TODO: remove after https://github.com/microsoft/TypeScript/pull/58187 is released
if (ts.canHaveModifiers(node)) {
for (const modifier of ts.getModifiers(node) ?? []) {
if (modifier.kind === ts.SyntaxKind.PrivateKeyword) {
removeAllComments(node);
break;
}
}
}
return removeDeclareConstExport(node, /*needExportModifier*/ false);
}, /*context*/ undefined);
writeNode(/** @type {ts.Statement} */ (publicStatement), decl.getSourceFile(), WriteTarget.Public);
}
}

if (writeTarget & WriteTarget.Internal) {
const updated = ts.visitEachChild(statement, node => removeDeclareConstExport(node, childrenNeedExportModifier), /*context*/ undefined);
writeNode(/** @type {ts.Statement} */ (updated), decl.getSourceFile(), WriteTarget.Internal);
}
});
});

Expand Down
12 changes: 12 additions & 0 deletions src/compiler/_namespaces/ts.ast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// /** @internal */
// export * from "../nodes.js";
/** @internal */
export * from "../ast.js";
/** @internal */
export * from "../factory/astNodeTests.js";
/** @internal */
export * from "../factory/astNodeFactory.js";
/** @internal */
export * from "../factory/astParenthesizerRules.js";
/** @internal */
export * from "../astForEachChild.js";
7 changes: 6 additions & 1 deletion src/compiler/_namespaces/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,28 @@ export * from "../semver.js";
export * from "../performanceCore.js";
export * from "../tracing.js";
export * from "../types.js";
export * from "../ast.js";
export * from "../sys.js";
export * from "../path.js";
export * from "../diagnosticInformationMap.generated.js";
export * from "../scanner.js";
export * from "../utilitiesPublic.js";
export * from "../utilities.js";
export * from "../factory/baseNodeFactory.js";
export * from "../factory/parenthesizerRules.js";
export * from "../factory/astParenthesizerRules.js";
export * from "../factory/nodeConverters.js";
export * from "../factory/nodeFactory.js";
export * from "../factory/astNodeFactory.js";
export * from "../factory/emitNode.js";
export * from "../factory/astNodeTests.js";
export * from "../factory/emitHelpers.js";
export * from "../factory/nodeTests.js";
export * from "../factory/nodeChildren.js";
export * from "../factory/utilities.js";
export * from "../factory/utilitiesPublic.js";
export * from "../parser.js";
export * from "../forEachChild.js";
export * from "../astForEachChild.js";
export * from "../commandLineParser.js";
export * from "../moduleNameResolver.js";
export * from "../binder.js";
Expand Down
Loading
Loading