• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}