1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import * as ts from "typescript"; 17import * as jshelpers from "./jshelpers"; 18 19let globalStrict = true; 20let globalDeclare = false; 21 22export function checkStrictModeStatementList(node: ts.Node): boolean { 23 let statements; 24 if (node.kind == ts.SyntaxKind.SourceFile) { 25 statements = (<ts.SourceFile>node).statements; 26 } else { 27 let decl = <ts.FunctionLikeDeclaration>node; 28 if (decl && decl.body) { 29 if (decl.body.kind == ts.SyntaxKind.Block) { 30 statements = (<ts.Block>decl.body).statements; 31 } 32 } else { 33 return false; 34 } 35 } 36 37 if (statements == undefined) { 38 return false; 39 } 40 41 for (const statement of statements) { 42 if (!jshelpers.isPrologueDirective(statement)) { 43 return false; 44 } 45 46 if (isUseStrictPrologueDirective(<ts.ExpressionStatement>statement)) { 47 return true; 48 } 49 } 50 51 return false; 52} 53 54/// Should be called only on prologue directives (isPrologueDirective(node) should be true) 55function isUseStrictPrologueDirective(node: ts.ExpressionStatement): boolean { 56 let file = jshelpers.getSourceFileOfNode(node); 57 const nodeText = jshelpers.getSourceTextOfNodeFromSourceFile(file, node.expression); 58 59 // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the 60 // string to contain unicode escapes (as per ES5). 61 return nodeText === '"use strict"' || nodeText === "'use strict'"; 62} 63 64function checkStrictMode(node: ts.Node): boolean { 65 while (node && node.parent && node.parent.kind != ts.SyntaxKind.SourceFile) { 66 let func = jshelpers.getContainingFunctionDeclaration(node); 67 if (!func) { 68 return false; 69 } 70 if (checkStrictModeStatementList(func)) { 71 return true; 72 } 73 node = <ts.FunctionLikeDeclaration>func; 74 } 75 76 return false; 77} 78 79function getGlobalStrict(): boolean { 80 return globalStrict; 81} 82 83export function setGlobalStrict(flag: boolean) { 84 globalStrict = flag; 85} 86 87export function isStrictMode(node: ts.Node): boolean { 88 if (getGlobalStrict()) { 89 return true; 90 } 91 92 return checkStrictMode(node); 93} 94 95export function setGlobalDeclare(flag: boolean) { 96 globalDeclare = flag; 97} 98 99export function isGlobalDeclare() { 100 return globalDeclare; 101}