From 452f121486181299ae7cdf055ae2606ae9ca6eb2 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Thu, 25 Apr 2019 10:41:45 -0700 Subject: [PATCH] fix: ensure strict mode when evaluating in JIT (#30122) PR Close #30122 --- packages/compiler/src/output/output_jit.ts | 12 +++++++ .../compiler/test/output/output_jit_spec.ts | 31 +++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/compiler/src/output/output_jit.ts b/packages/compiler/src/output/output_jit.ts index c6ad4abd55..1d3d2670b0 100644 --- a/packages/compiler/src/output/output_jit.ts +++ b/packages/compiler/src/output/output_jit.ts @@ -31,6 +31,13 @@ export class JitEvaluator { createSourceMaps: boolean): {[key: string]: any} { const converter = new JitEmitterVisitor(reflector); const ctx = EmitterVisitorContext.createRoot(); + // Ensure generated code is in strict mode + if (statements.length > 0 && !isUseStrictStatement(statements[0])) { + statements = [ + o.literal('use strict').toStmt(), + ...statements, + ]; + } converter.visitAllStatements(statements, ctx); converter.createReturnStmt(ctx); return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps); @@ -150,3 +157,8 @@ export class JitEmitterVisitor extends AbstractJsEmitterVisitor { ctx.print(ast, this._evalArgNames[id]); } } + + +function isUseStrictStatement(statement: o.Statement): boolean { + return statement.isEquivalent(o.literal('use strict').toStmt()); +} diff --git a/packages/compiler/test/output/output_jit_spec.ts b/packages/compiler/test/output/output_jit_spec.ts index ccdeed559f..5ec18c3eb5 100644 --- a/packages/compiler/test/output/output_jit_spec.ts +++ b/packages/compiler/test/output/output_jit_spec.ts @@ -8,7 +8,8 @@ import {EmitterVisitorContext} from '@angular/compiler/src/output/abstract_emitter'; import * as o from '@angular/compiler/src/output/output_ast'; -import {JitEmitterVisitor} from '@angular/compiler/src/output/output_jit'; +import {JitEmitterVisitor, JitEvaluator} from '@angular/compiler/src/output/output_jit'; +import {R3JitReflector} from '@angular/compiler/src/render3/r3_jit'; import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector'; const anotherModuleUrl = 'somePackage/someOtherPath'; @@ -32,5 +33,31 @@ const anotherModuleUrl = 'somePackage/someOtherPath'; expect(Object.keys(args).length).toBe(20); }); }); + + it('should use strict mode', () => { + const evaluator = new JitEvaluator(); + expect(() => { + evaluator.evaluateStatements( + 'http://angular.io/something.ts', + [ + // Set an undeclared variable + // foo = "bar"; + o.variable('foo').equals(o.literal('bar')).toStmt(), + ], + new R3JitReflector({}), false); + }).toThrowError(); + }); + + it('should not add more than one strict mode statement if there is already one present', () => { + const converter = new JitEmitterVisitor(new JitReflector()); + const ctx = EmitterVisitorContext.createRoot(); + converter.visitAllStatements( + [ + o.literal('use strict').toStmt(), + ], + ctx); + const matches = ctx.toSource().match(/'use strict';/g) !; + expect(matches.length).toBe(1); + }); }); -} \ No newline at end of file +}