Skip to content

Commit

Permalink
Enable noCheck for JS emit
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Apr 30, 2024
1 parent dc316af commit 6e919ad
Show file tree
Hide file tree
Showing 28 changed files with 823 additions and 455 deletions.
760 changes: 501 additions & 259 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/compiler/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
ModifierFlags,
Node,
NodeArray,
NodeCheckFlags,
NodeFlags,
nodeIsSynthesized,
noop,
Expand Down Expand Up @@ -455,6 +456,10 @@ export namespace Debug {
return formatEnum(flags, (ts as any).NodeFlags, /*isFlags*/ true);
}

export function formatNodeCheckFlags(flags: NodeCheckFlags | undefined): string {
return formatEnum(flags, (ts as any).NodeCheckFlags, /*isFlags*/ true);
}

export function formatModifierFlags(flags: ModifierFlags | undefined): string {
return formatEnum(flags, (ts as any).ModifierFlags, /*isFlags*/ true);
}
Expand Down
17 changes: 16 additions & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ import {
isGeneratedPrivateIdentifier,
isIdentifier,
isImportAttributes,
isImportEqualsDeclaration,
isIncrementalCompilation,
isInJsonFile,
isJSDocLikeText,
Expand Down Expand Up @@ -793,6 +794,11 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
emitSkipped = true;
return;
}

if (compilerOptions.noCheck) {
(isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : filter(sourceFileOrBundle.sourceFiles, isSourceFileNotJson)).forEach(markLinkedReferences);
}

// Transform the source files
const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);

Expand Down Expand Up @@ -924,6 +930,14 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
forEachChild(node, collectLinkedAliases);
}

function markLinkedReferences(file: SourceFile) {
ts.forEachChildRecursively(file, n => {
if (isImportEqualsDeclaration(n) && !(ts.getSyntacticModifierFlags(n) & ts.ModifierFlags.Export)) return "skip"; // These are deferred and marked in a chain when referenced
if (ts.isImportDeclaration(n)) return "skip"; // likewise, these are ultimately what get marked by calls on other nodes - we want to skip them
resolver.markLinkedReferences(n);
});
}

function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, transform: TransformationResult<SourceFile | Bundle>, printer: Printer, mapOptions: SourceMapOptions) {
const sourceFileOrBundle = transform.transformed[0];
const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined;
Expand Down Expand Up @@ -1090,10 +1104,11 @@ export const notImplementedResolver: EmitResolver = {
isValueAliasDeclaration: notImplemented,
isReferencedAliasDeclaration: notImplemented,
isTopLevelValueImportEqualsWithEntityName: notImplemented,
getNodeCheckFlags: notImplemented,
hasNodeCheckFlag: notImplemented,
isDeclarationVisible: notImplemented,
isLateBound: (_node): _node is LateBoundDeclaration => false,
collectLinkedAliases: notImplemented,
markLinkedReferences: notImplemented,
isImplementationOfOverload: notImplemented,
requiresAddingImplicitUndefined: notImplemented,
isExpandoFunctionDeclaration: notImplemented,
Expand Down
3 changes: 0 additions & 3 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4429,9 +4429,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
if (options.noEmit) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noCheck", "noEmit");
}
if (!options.emitDeclarationOnly) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "noCheck", "emitDeclarationOnly");
}
}

if (
Expand Down
15 changes: 7 additions & 8 deletions src/compiler/transformers/classFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1755,7 +1755,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
}
else if (isPrivateIdentifierClassElementDeclaration(member)) {
containsInstancePrivateElements = true;
if (resolver.getNodeCheckFlags(member) & NodeCheckFlags.ContainsConstructorReference) {
if (resolver.hasNodeCheckFlag(member, NodeCheckFlags.ContainsConstructorReference)) {
facts |= ClassFacts.NeedsClassConstructorReference;
}
}
Expand Down Expand Up @@ -1889,7 +1889,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
getClassLexicalEnvironment().classThis = node.emitNode.classThis;
}

const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsConstructorReference;
const isClassWithConstructorReference = resolver.hasNodeCheckFlag(node, NodeCheckFlags.ContainsConstructorReference);
const isExport = hasSyntacticModifier(node, ModifierFlags.Export);
const isDefault = hasSyntacticModifier(node, ModifierFlags.Default);
let modifiers = visitNodes(node.modifiers, modifierVisitor, isModifier);
Expand Down Expand Up @@ -1965,8 +1965,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
// these statements after the class expression variable statement.
const isDecoratedClassDeclaration = !!(facts & ClassFacts.ClassWasDecorated);
const staticPropertiesOrClassStaticBlocks = getStaticPropertiesAndClassStaticBlock(node);
const classCheckFlags = resolver.getNodeCheckFlags(node);
const isClassWithConstructorReference = classCheckFlags & NodeCheckFlags.ContainsConstructorReference;
const isClassWithConstructorReference = resolver.hasNodeCheckFlag(node, NodeCheckFlags.ContainsConstructorReference);

let temp: Identifier | undefined;
function createClassTempVar() {
Expand All @@ -1983,7 +1982,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
return getClassLexicalEnvironment().classConstructor = node.emitNode.classThis;
}

const requiresBlockScopedVar = classCheckFlags & NodeCheckFlags.BlockScopedBindingInLoop;
const requiresBlockScopedVar = resolver.hasNodeCheckFlag(node, NodeCheckFlags.BlockScopedBindingInLoop);
const temp = factory.createTempVariable(requiresBlockScopedVar ? addBlockScopedVariable : hoistVariableDeclaration, /*reservedInNestedScopes*/ true);
getClassLexicalEnvironment().classConstructor = factory.cloneNode(temp);
return temp;
Expand Down Expand Up @@ -2712,7 +2711,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
const alreadyTransformed = !!cacheAssignment || isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left);
if (!alreadyTransformed && !inlinable && shouldHoist) {
const generatedName = factory.getGeneratedNameForNode(name);
if (resolver.getNodeCheckFlags(name) & NodeCheckFlags.BlockScopedBindingInLoop) {
if (resolver.hasNodeCheckFlag(name, NodeCheckFlags.BlockScopedBindingInLoop)) {
addBlockScopedVariable(generatedName);
}
else {
Expand Down Expand Up @@ -2960,7 +2959,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
typeof name === "string" ? factory.createUniqueName(name, GeneratedIdentifierFlags.Optimistic, prefix, suffix) :
factory.createTempVariable(/*recordTempVariable*/ undefined, /*reservedInNestedScopes*/ true, prefix, suffix);

if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BlockScopedBindingInLoop) {
if (resolver.hasNodeCheckFlag(node, NodeCheckFlags.BlockScopedBindingInLoop)) {
addBlockScopedVariable(identifier);
}
else {
Expand Down Expand Up @@ -3295,7 +3294,7 @@ export function transformClassFields(context: TransformationContext): (x: Source

function trySubstituteClassAlias(node: Identifier): Expression | undefined {
if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReference) {
if (resolver.hasNodeCheckFlag(node, NodeCheckFlags.ConstructorReference)) {
// Due to the emit for class decorators, any reference to the class from inside of the class body
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
// behavior of class names in ES6.
Expand Down
15 changes: 7 additions & 8 deletions src/compiler/transformers/es2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2867,9 +2867,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile
// * Why loop initializer is excluded?
// - Since we've introduced a fresh name it already will be undefined.

const flags = resolver.getNodeCheckFlags(node);
const isCapturedInFunction = flags & NodeCheckFlags.CapturedBlockScopedBinding;
const isDeclaredInLoop = flags & NodeCheckFlags.BlockScopedBindingInLoop;
const isCapturedInFunction = resolver.hasNodeCheckFlag(node, NodeCheckFlags.CapturedBlockScopedBinding);
const isDeclaredInLoop = resolver.hasNodeCheckFlag(node, NodeCheckFlags.BlockScopedBindingInLoop);
const emittedAsTopLevel = (hierarchyFacts & HierarchyFacts.TopLevel) !== 0
|| (isCapturedInFunction
&& isDeclaredInLoop
Expand Down Expand Up @@ -3373,7 +3372,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile
}

function shouldConvertPartOfIterationStatement(node: Node) {
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsCapturedBlockScopeBinding) !== 0;
return resolver.hasNodeCheckFlag(node, NodeCheckFlags.ContainsCapturedBlockScopeBinding);
}

function shouldConvertInitializerOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleInitializer {
Expand All @@ -3394,7 +3393,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile
}

function shouldConvertBodyOfIterationStatement(node: IterationStatement): boolean {
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0;
return resolver.hasNodeCheckFlag(node, NodeCheckFlags.LoopWithCapturedBlockScopedBinding);
}

/**
Expand Down Expand Up @@ -4057,11 +4056,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile
}
else {
loopParameters.push(factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name));
const checkFlags = resolver.getNodeCheckFlags(decl);
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter || hasCapturedBindingsInForHead) {
const needsOutParam = resolver.hasNodeCheckFlag(decl, NodeCheckFlags.NeedsLoopOutParameter);
if (needsOutParam || hasCapturedBindingsInForHead) {
const outParamName = factory.createUniqueName("out_" + idText(name));
let flags = LoopOutParameterFlags.None;
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter) {
if (needsOutParam) {
flags |= LoopOutParameterFlags.Body;
}
if (isForStatement(container)) {
Expand Down
18 changes: 9 additions & 9 deletions src/compiler/transformers/es2017.ts
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile
// This step isn't needed if we eventually transform this to ES5.
const originalMethod = getOriginalNode(node, isFunctionLikeDeclaration);
const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 &&
resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync) &&
(resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) || resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAccessInAsync)) &&
(getFunctionFlags(originalMethod) & FunctionFlags.AsyncGenerator) !== FunctionFlags.AsyncGenerator;

if (emitSuperHelpers) {
Expand All @@ -675,10 +675,10 @@ export function transformES2017(context: TransformationContext): (x: SourceFile

if (hasSuperElementAccess) {
// Emit helpers for super element access expressions (`super[x]`).
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) {
if (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync)) {
addEmitHelper(updated, advancedAsyncSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAccessInAsync) {
else if (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAccessInAsync)) {
addEmitHelper(updated, asyncSuperHelper);
}
}
Expand Down Expand Up @@ -743,7 +743,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile
const promiseConstructor = languageVersion < ScriptTarget.ES2015 ? getPromiseConstructor(nodeType) : undefined;
const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
const savedLexicalArgumentsBinding = lexicalArgumentsBinding;
const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;
const hasLexicalArguments = resolver.hasNodeCheckFlag(node, NodeCheckFlags.CaptureArguments);
const captureLexicalArguments = hasLexicalArguments && !lexicalArgumentsBinding;
if (captureLexicalArguments) {
lexicalArgumentsBinding = factory.createUniqueName("arguments");
Expand Down Expand Up @@ -816,7 +816,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile

// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync);
const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) || resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAccessInAsync));

if (emitSuperHelpers) {
enableSubstitutionForAsyncMethodsWithSuper();
Expand All @@ -836,10 +836,10 @@ export function transformES2017(context: TransformationContext): (x: SourceFile

if (emitSuperHelpers && hasSuperElementAccess) {
// Emit helpers for super element access expressions (`super[x]`).
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) {
if (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync)) {
addEmitHelper(block, advancedAsyncSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAccessInAsync) {
else if (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAccessInAsync)) {
addEmitHelper(block, asyncSuperHelper);
}
}
Expand Down Expand Up @@ -926,7 +926,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAccessInAsync | NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync);
const superContainerFlags = (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAccessInAsync) ? NodeCheckFlags.MethodWithSuperPropertyAccessInAsync : 0) | (resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) ? NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync : 0);
if (superContainerFlags !== enclosingSuperContainerFlags) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = superContainerFlags;
Expand Down Expand Up @@ -1058,7 +1058,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile
export function createSuperAccessVariableStatement(factory: NodeFactory, resolver: EmitResolver, node: FunctionLikeDeclaration, names: Set<__String>) {
// Create a variable declaration with a getter/setter (if binding) definition for each name:
// const _super = Object.create(null, { x: { get: () => super.x, set: (v) => super.x = v }, ... });
const hasBinding = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) !== 0;
const hasBinding = resolver.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync);
const accessors: PropertyAssignment[] = [];
names.forEach((_, key) => {
const name = unescapeLeadingUnderscores(key);
Expand Down

0 comments on commit 6e919ad

Please sign in to comment.