fix(compiler): generate safe access strictNullChecks compatible code (#12800)
fixes #12795
This commit is contained in:
parent
52be848f94
commit
a965d11cce
@ -32,7 +32,8 @@ export enum BuiltinTypeName {
|
|||||||
String,
|
String,
|
||||||
Int,
|
Int,
|
||||||
Number,
|
Number,
|
||||||
Function
|
Function,
|
||||||
|
Null
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BuiltinType extends Type {
|
export class BuiltinType extends Type {
|
||||||
@ -73,7 +74,7 @@ export var INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
|
|||||||
export var NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
|
export var NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
|
||||||
export var STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
|
export var STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
|
||||||
export var FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
|
export var FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
|
||||||
|
export var NULL_TYPE = new BuiltinType(BuiltinTypeName.Null);
|
||||||
|
|
||||||
export interface TypeVisitor {
|
export interface TypeVisitor {
|
||||||
visitBuiltintType(type: BuiltinType, context: any): any;
|
visitBuiltintType(type: BuiltinType, context: any): any;
|
||||||
@ -175,7 +176,8 @@ export abstract class Expression {
|
|||||||
}
|
}
|
||||||
isBlank(): Expression {
|
isBlank(): Expression {
|
||||||
// Note: We use equals by purpose here to compare to null and undefined in JS.
|
// Note: We use equals by purpose here to compare to null and undefined in JS.
|
||||||
return this.equals(NULL_EXPR);
|
// We use the typed null to allow strictNullChecks to narrow types.
|
||||||
|
return this.equals(TYPED_NULL_EXPR);
|
||||||
}
|
}
|
||||||
cast(type: Type): Expression { return new CastExpr(this, type); }
|
cast(type: Type): Expression { return new CastExpr(this, type); }
|
||||||
toStmt(): Statement { return new ExpressionStatement(this); }
|
toStmt(): Statement { return new ExpressionStatement(this); }
|
||||||
@ -451,6 +453,7 @@ export var SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super);
|
|||||||
export var CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError);
|
export var CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError);
|
||||||
export var CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack);
|
export var CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack);
|
||||||
export var NULL_EXPR = new LiteralExpr(null, null);
|
export var NULL_EXPR = new LiteralExpr(null, null);
|
||||||
|
export var TYPED_NULL_EXPR = new LiteralExpr(null, NULL_TYPE);
|
||||||
|
|
||||||
//// Statements
|
//// Statements
|
||||||
export enum StmtModifier {
|
export enum StmtModifier {
|
||||||
|
@ -69,7 +69,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||||||
|
|
||||||
visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any {
|
visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any {
|
||||||
const value = ast.value;
|
const value = ast.value;
|
||||||
if (isBlank(value)) {
|
if (isBlank(value) && ast.type != o.NULL_TYPE) {
|
||||||
ctx.print(`(${value} as any)`);
|
ctx.print(`(${value} as any)`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,7 @@ export function main() {
|
|||||||
it('should support blank literals', () => {
|
it('should support blank literals', () => {
|
||||||
expect(emitStmt(o.literal(null).toStmt())).toEqual('(null as any);');
|
expect(emitStmt(o.literal(null).toStmt())).toEqual('(null as any);');
|
||||||
expect(emitStmt(o.literal(undefined).toStmt())).toEqual('(undefined as any);');
|
expect(emitStmt(o.literal(undefined).toStmt())).toEqual('(undefined as any);');
|
||||||
|
expect(emitStmt(o.variable('a', null).isBlank().toStmt())).toEqual('(a == null);');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support external identifiers', () => {
|
it('should support external identifiers', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user