diff --git a/test262/config.py b/test262/config.py index c521b973dd530584ae87c384f91dde836def4731..20e874022987e9c14e5d4c3b15055d7ebeb0f9ce 100755 --- a/test262/config.py +++ b/test262/config.py @@ -32,6 +32,7 @@ CODE_ROOT = os.path.abspath(os.path.join(CUR_FILE_DIR, "../../..")) ARK_DIR = f"{CODE_ROOT}/out/ohos-arm-release/clang_x64/ark/ark" ICUI_DIR = f"{CODE_ROOT}/out/ohos-arm-release/clang_x64/global/i18n_standard" LLVM_DIR = f"{CODE_ROOT}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/" +ARK_JS_RUNTIME_DIR = f"{CODE_ROOT}/out/ohos-arm-release/clang_x64/ark/ark_js_runtime" # " mode_type": { # "1": "only default", @@ -45,8 +46,8 @@ TEST_ES2015_DIR = os.path.join(DATA_DIR, "test_es2015") TEST_CI_DIR = os.path.join(DATA_DIR, "test_CI") DEFAULT_ARK_FRONTEND_TOOL = os.path.join(ARK_DIR, "build", "src", "index.js") -DEFAULT_ARK_TOOL = os.path.join(ARK_DIR, "..", "ark_js_runtime", "ark_js_vm") -DEFAULT_LIBS_DIR = f"{ARK_DIR}:{ICUI_DIR}:{LLVM_DIR}" +DEFAULT_ARK_TOOL = os.path.join(ARK_JS_RUNTIME_DIR, "ark_js_vm") +DEFAULT_LIBS_DIR = f"{ARK_DIR}:{ICUI_DIR}:{LLVM_DIR}:{ARK_JS_RUNTIME_DIR}" DEFAULT_HOST_TYPE = "panda" DEFAULT_HOST_PATH = "python3" diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 97752ef074164566fb3186cad224d9c84d6cc53e..7f9bce461f465f4b0e9774aae94e6b0be02f3254 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -31,14 +31,23 @@ from config import * def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--ark-tool', + default=DEFAULT_ARK_TOOL, + required=False, help="ark's binary tool") parser.add_argument('--ark-frontend-tool', + default=DEFAULT_ARK_FRONTEND_TOOL, + required=False, help="ark frontend conversion tool") parser.add_argument("--libs-dir", + default=DEFAULT_LIBS_DIR, + required=False, help="The path collection of dependent so has been divided by':'") parser.add_argument("--js-file", + required=True, help="js file") parser.add_argument('--ark-frontend', + default=DEFAULT_ARK_FRONTEND, + required=False, nargs='?', choices=ARK_FRONTEND_LIST, type=str, help="Choose one of them") arguments = parser.parse_args() @@ -155,7 +164,7 @@ class ArkProgram(): return retcode def execute(self): - + os.environ["LD_LIBRARY_PATH"] = self.libs_dir file_name_pre = os.path.splitext(self.js_file)[0] diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 212e144a548b4ae7a797b8351eb932668596d26a..f002aae0e77d9e64e650300c634cb7443c06442f 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -25,9 +25,17 @@ ohos_copy("ts2abc_src") { module_install_name = "" } +action("npm_install") { + visibility = [ ":*" ] + script = "scripts/npm-install.sh" + args = [ rebase_path(node_path) ] + outputs = [ target_out_dir + "/$target_name/node_modules" ] + inputs = [ "${ts2abc_root}/package.json" ] +} + ohos_copy("node_modules") { sources = [ rebase_path("${node_modules}") ] - + deps = [ ":npm_install" ] outputs = [ target_out_dir + "/node_modules" ] module_install_name = "" } diff --git a/ts2panda/package-lock.json b/ts2panda/package-lock.json old mode 100644 new mode 100755 index e18acb061b27108ec6cbaa58cb9e2cb1e6dc877d..646821ba8881cb3f9add02ae06249b613d902356 --- a/ts2panda/package-lock.json +++ b/ts2panda/package-lock.json @@ -2319,9 +2319,9 @@ "dev": true }, "typescript": { - "version": "3.9.10", - "resolved": "https://repo.huaweicloud.com/repository/npm/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/typescript/download/typescript-4.4.3.tgz?cache=0&sync_timestamp=1632381565165&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ftypescript%2Fdownload%2Ftypescript-4.4.3.tgz", + "integrity": "sha1-vcVAfKorEJ79T4L+EwZW+XeikyQ=", "dev": true }, "typical": { diff --git a/ts2panda/package.json b/ts2panda/package.json index 2fc7bed3c1bea20b335152cec5b95574d1ef154e..f37f0d41b643c30529a895a3837a4db118232e35 100755 --- a/ts2panda/package.json +++ b/ts2panda/package.json @@ -33,7 +33,7 @@ "mocha": "^8.1.1", "sinon": "^9.0.3", "ts-sinon": "^1.2.1", - "typescript": "^3.9.7" + "typescript": "^4.1.3" }, "dependencies": { "@babel/core": "^7.12.10", diff --git a/ts2panda/scripts/npm-install.sh b/ts2panda/scripts/npm-install.sh new file mode 100755 index 0000000000000000000000000000000000000000..f806d55df01d96557ff8b668c4090dc52b11d790 --- /dev/null +++ b/ts2panda/scripts/npm-install.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +set -e + +script_path=$(cd $(dirname $0);pwd) +ts2panda_dir=$(dirname ${script_path}) +code_dir=${ts2panda_dir}/../../.. + +nodejs_dir=$1 + +cd ${ts2panda_dir} +export PATH=${nodejs_dir}:$PATH +npm config set registry http://registry.npm.taobao.org +if [ "X${SKIP_SSL}" == "XYES" ];then + npm config set strict-ssl false +fi +npm cache clean -f +npm install + +cd ${code_dir} +if [ -d "${code_dir}/prebuilts/build-tools/common/ts2abc" ]; then + echo -e "\n" + echo "${code_dir}/prebuilts/build-tools/common/ts2abc already exist, it will be replaced" + /bin/rm -rf ${code_dir}/prebuilts/build-tools/common/ts2abc + echo -e "\n" +fi + +mkdir -p ${code_dir}/prebuilts/build-tools/common/ts2abc +/bin/cp -rf ${code_dir}/ark/ts2abc/ts2panda/node_modules ${code_dir}/prebuilts/build-tools/common/ts2abc/ \ No newline at end of file diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index b87ad4cc6a300f0aacccc882a40714e3d05e25dd..2b2e39a916b56cdb8f962019fb8fa7b95e750908 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -83,7 +83,9 @@ import { import { checkValidUseSuperBeforeSuper, compileClassDeclaration, - compileConstructor + compileConstructor, + compileDefaultConstructor, + isContainConstruct } from "./statement/classStatement"; import { compileForOfStatement } from "./statement/forOfStatement"; import { LabelTarget } from "./statement/labelTarget"; @@ -336,6 +338,14 @@ export class Compiler { let pandaGen = this.pandaGen; this.compileFunctionParameterDeclaration(decl); + if (ts.isConstructorDeclaration(decl)) { + let classNode = decl.parent; + if (jshelpers.getClassExtendsHeritageElement(classNode) && !isContainConstruct(classNode)) { + compileDefaultConstructor(this, decl); + return; + } + } + if (decl.kind == ts.SyntaxKind.FunctionExpression) { if (decl.name) { let funcName = jshelpers.getTextOfIdentifierOrLiteral(decl.name); @@ -554,7 +564,7 @@ export class Compiler { compileFinallyBeforeCFC(endTry: TryStatement | undefined, cfc: ControlFlowChange, continueTargetLabel: Label | undefined) {// compile finally before control flow change let startTry = TryStatement.getCurrentTryStatement(); let originTry = startTry; - for (; startTry != endTry; startTry = startTry ?.getOuterTryStatement()) { + for (; startTry != endTry; startTry = startTry?.getOuterTryStatement()) { if (startTry && startTry.trybuilder) { let inlineFinallyBegin = new Label(); @@ -616,7 +626,7 @@ export class Compiler { // try-catch-finally statements must have been transformed into // two nested try statements with only "catch" or "finally" each. if (stmt.catchClause && stmt.finallyBlock) { - transformTryCatchFinally(stmt, this.recorder); + stmt = transformTryCatchFinally(stmt, this.recorder); } let tryBuilder = new TryBuilder(this, this.pandaGen, stmt); diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts index 527b8f0d50b933fcff00b9dff70631f05455dbf1..6d05c0aa04a32363819f109951a8f95cb0fc5430 100644 --- a/ts2panda/src/debuginfo.ts +++ b/ts2panda/src/debuginfo.ts @@ -171,6 +171,9 @@ export class DebugInfo { let firstStmt = pandaGen.getFirstStmt(); if (firstStmt) { let file = jshelpers.getSourceFileOfNode(firstStmt); + if (!file) { + return; + } let loc = file.getLineAndCharacterOfPosition(firstStmt.getStart()); let wholeLineText = firstStmt.getText(); posInfo.setSourecLineNum(loc.line); @@ -199,7 +202,7 @@ export class DebugInfo { let wholeLineText = ""; if (DebugInfo.isNode(node)) { let tsNode = (node); - let file = jshelpers.getSourceFileOfNode(node); + let file = jshelpers.getSourceFileOfNode(tsNode); if (!file) { return; } diff --git a/ts2panda/src/jshelpers.d.ts b/ts2panda/src/jshelpers.d.ts index 5e4203d763b9c1b65c72a2f0fd558f8a7bad91da..7138633f30c10086bc2a3b57ff16ae3391172ba3 100644 --- a/ts2panda/src/jshelpers.d.ts +++ b/ts2panda/src/jshelpers.d.ts @@ -13,6 +13,8 @@ * limitations under the License. */ +import ts from "typescript"; + export function getSymbol(node: ts.Node): ts.Symbol; export function tsStringToString(str: ts.__String): string; export function getTextOfIdentifierOrLiteral(node: ts.Node): string; @@ -22,7 +24,6 @@ export function getFlowNode(stmt: ts.Statement): ts.Node; export function bindSourceFile(sourceFile: ts.SourceFile, options: ts.CompilerOptions); export function createDiagnosticForNode(node: ts.Node, message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.DiagnosticWithLocation; export function createCompilerDiagnostic(message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.Diagnostic; -export function createCompilerDiagnostic(message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.Diagnostic; export function createFileDiagnostic(file: ts.SourceFile, start: number, length: number, message: ts.DiagnosticMessage, ...args: (string | number | undefined)[]): ts.DiagnosticWithLocation; export function isEffectiveStrictModeSourceFile(node: ts.SourceFile, compilerOptions: ts.CompilerOptions): boolean; export function getErrorSpanForNode(sourceFile: ts.SourceFile, node: ts.Node): ts.TextSpan; @@ -70,5 +71,5 @@ export function skipOuterExpressions(node: ts.Node, kinds?: ts.OuterExpressionKi export function isSuperCall(n: ts.Node); export function isThisProperty(node: ts.Node): boolean; export function isThisIdentifier(node: ts.Node | undefined): boolean; -export function getClassExtendsHeritageElement(node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration); -export function isSuperProperty(node: ts.Node); \ No newline at end of file +export function isSuperProperty(node: ts.Node); +export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined; \ No newline at end of file diff --git a/ts2panda/src/jshelpers.js b/ts2panda/src/jshelpers.js index a958271e22bad6749ab86f42f2d5b206e8e343c9..e3c2960d8d8a8f3201a57ba2e2f9638f0cf0dacc 100755 --- a/ts2panda/src/jshelpers.js +++ b/ts2panda/src/jshelpers.js @@ -103,10 +103,6 @@ function getTextOfNode(node, includeTrivia) { return ts.getTextOfNode(node, includeTrivia); } -function getContainingClass(node) { - return ts.getContainingClass(node); -} - function nodePosToString(node) { return ts.nodePosToString(node); } @@ -247,8 +243,8 @@ function isSuperProperty(node) { return ts.isSuperProperty(node); } -function getClassExtendsHeritageElement(node) { - return ts.getClassExtendsHeritageElement(node); +function setParent(child, parent) { + return ts.setParent(child, parent); } module.exports = { @@ -274,7 +270,6 @@ module.exports = { getSourceFileOfNode: getSourceFileOfNode, isIterationStatement: isIterationStatement, getTextOfNode: getTextOfNode, - getContainingClass: getContainingClass, nodePosToString: nodePosToString, getContainingFunctionDeclaration: getContainingFunctionDeclaration, tokenToString: tokenToString, @@ -310,5 +305,5 @@ module.exports = { isThisIdentifier: isThisIdentifier, isThisProperty: isThisProperty, isSuperProperty: isSuperProperty, - getClassExtendsHeritageElement: getClassExtendsHeritageElement, + setParent: setParent, }; diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index d74afb9d1c3378feb0bff1e318a1e1610b83215a..9f2b726696f7bb58f905db59cd2d99cfd2c1ef0c 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -217,7 +217,7 @@ export class Recorder { let tmp: Scope | undefined = nearestRefVariableScope.getNearestLexicalScope(); let needCreateLoopEnv: boolean = false; if (nearestDefLexicalScope instanceof LoopScope) { - while(tmp) { + while (tmp) { if (tmp == nearestDefLexicalScope) { needCreateLoopEnv = true; break; @@ -236,7 +236,7 @@ export class Recorder { if (name == "arguments") { let varialbeScope = scope.getNearestVariableScope(); - varialbeScope ?.setUseArgs(true); + varialbeScope?.setUseArgs(true); } } @@ -493,8 +493,11 @@ export class Recorder { // if variable share a same name with the parameter of its contained function, it should not be hoisted if (scope instanceof FunctionScope) { - let nearestFunc = jshelpers.getContainingFunction(node); - let functionParameters = this.getParametersOfFunction(nearestFunc); + let nearestFunc = jshelpers.getContainingFunctionDeclaration(node); + if (!nearestFunc) { + return; + } + let functionParameters = this.getParametersOfFunction(nearestFunc); if (functionParameters) { for (let i = 0; i < functionParameters.length; i++) { if (functionParameters[i].name == declName) { diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index 1163c9e0b86aadac244721c152ca0e0f6375d031..a694437b44a2f502a18cfb8897e9f0f20b17d43f 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -132,41 +132,23 @@ export function compileClassDeclaration(compiler: Compiler, stmt: ts.ClassLikeDe export function AddCtor2Class(recorder: Recorder, classNode: ts.ClassLikeDeclaration, scope: Scope) { let ctorNode; - let hasHeritage = classNode.heritageClauses && classNode.heritageClauses.length; - let statement: ts.Statement | undefined; - let superCallNode = ts.createSuper(); - if (hasHeritage) { - let parameter = ts.createParameter(undefined, undefined, ts.createToken(ts.SyntaxKind.DotDotDotToken), "args"); - ctorNode = ts.createConstructor(undefined, undefined, [parameter], undefined); - let callNode = ts.createCall( - superCallNode, - undefined, - [ts.createSpread(ts.createIdentifier("args"))] - ); - superCallNode.parent = callNode; - superCallNode.pos = classNode.pos; - superCallNode.end = classNode.pos; - statement = ts.createExpressionStatement(callNode); - callNode.parent = statement; - callNode.pos = classNode.pos; - callNode.end = classNode.pos; + if (jshelpers.getClassExtendsHeritageElement(classNode)) { + let parameter = ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), "args"); + ctorNode = ts.factory.createConstructorDeclaration(undefined, undefined, [parameter], undefined); } else { - ctorNode = ts.createConstructor(undefined, undefined, [], undefined); + ctorNode = ts.factory.createConstructorDeclaration(undefined, undefined, [], undefined); } - if (statement) { - ctorNode.body = ts.createBlock([statement]); - statement.parent = ctorNode; - statement.pos = classNode.pos; - statement.end = classNode.pos; - } else { - ctorNode.body = ts.createBlock([]); - } + ctorNode = jshelpers.setParent(ctorNode, classNode)!; + ctorNode = ts.setTextRange(ctorNode, classNode); + + let body = ts.factory.createBlock([]); + body = jshelpers.setParent(body, ctorNode)!; + body = ts.setTextRange(body, classNode)!; - ctorNode.parent = classNode; - ctorNode.pos = classNode.pos; - ctorNode.end = classNode.pos; - ctorNode.body!.parent = ctorNode; + ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, undefined, undefined, ctorNode.parameters, body); + ctorNode = jshelpers.setParent(ctorNode, classNode)!; + ctorNode = ts.setTextRange(ctorNode, classNode); let parentScope = recorder.getScopeOfNode(classNode); recorder.compilerDriver.getFuncId(classNode); @@ -183,6 +165,17 @@ export function AddCtor2Class(recorder: Recorder, classNode: ts.ClassLikeDeclara recorder.recordFunctionParameters(ctorNode); } +export function compileDefaultConstructor(compiler: Compiler, ctrNode: ts.ConstructorDeclaration) { + let callNode = ts.factory.createCallExpression(ts.factory.createSuper(), undefined, + [ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))]); + + callNode = jshelpers.setParent(callNode, ctrNode)!; + callNode = ts.setTextRange(callNode, ctrNode)! + + compileSuperCall(compiler, callNode, [], true); + compileConstructor(compiler, ctrNode, false); +} + function compileUnCompiledProperty(compiler: Compiler, properties: Property[], classReg: VReg) { let pandaGen = compiler.getPandaGen(); for (let propertyIndex = 0; propertyIndex < properties.length; propertyIndex++) { @@ -248,7 +241,7 @@ function createClassLiteralBuf(compiler: Compiler, classBuffer: LiteralBuffer, export function compileConstructor(compiler: Compiler, node: ts.ConstructorDeclaration, unreachableFlag: boolean) { let pandaGen = compiler.getPandaGen(); - let members = node.parent.members; + let members = node.parent!.members; for (let index = 0; index < members.length; index++) { let decl = members[index]; @@ -325,19 +318,23 @@ export function compileSuperCall(compiler: Compiler, node: ts.CallExpression, ar function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { let recorder = compiler.getRecorder(); let pandaGen = compiler.getPandaGen(); - let nearestFunc = jshelpers.getContainingFunction(node); + let nearestFunc = jshelpers.getContainingFunctionDeclaration(node); + if (!nearestFunc) { + return; + } + let nearestFuncScope = recorder.getScopeOfNode(nearestFunc); if (ts.isConstructorDeclaration(nearestFunc)) { let funcObj = nearestFuncScope.findLocal("4funcObj"); pandaGen.loadAccumulator(node, pandaGen.getVregForVariable(funcObj)); } else { - let outerFunc = jshelpers.getContainingFunction(nearestFunc); - let outerFuncScope = recorder.getScopeOfNode(outerFunc); + let outerFunc = jshelpers.getContainingFunctionDeclaration(nearestFunc); + let outerFuncScope = recorder.getScopeOfNode(outerFunc!); outerFuncScope.pendingCreateEnv(); let level = 1; - while (!ts.isConstructorDeclaration(outerFunc)) { - outerFunc = jshelpers.getContainingFunction(outerFunc); + while (!ts.isConstructorDeclaration(outerFunc!)) { + outerFunc = jshelpers.getContainingFunctionDeclaration(outerFunc!); outerFuncScope.pendingCreateEnv(); level++; } @@ -424,7 +421,7 @@ export function getClassNameForConstructor(classNode: ts.ClassLikeDeclaration) { let className = ""; if (!isAnonymousClass(classNode)) { - className = jshelpers.getTextOfIdentifierOrLiteral(classNode.name); + className = jshelpers.getTextOfIdentifierOrLiteral(classNode.name!); } else { let outerNode = findOuterNodeOfParenthesis(classNode); @@ -646,7 +643,7 @@ function scalarArrayEquals(node1: ts.Node | undefined, node2: ts.Node | undefine let val1Modifs = node1.modifiers; let val2Modifs = node2.modifiers; if (val1Modifs && val2Modifs) { - return val1Modifs.length == val2Modifs.length && val1Modifs.every(function(v, i) { return v === val2Modifs![i] });; + return val1Modifs.length == val2Modifs.length && val1Modifs.every(function (v, i) { return v === val2Modifs![i] });; } if (!val1Modifs && !val2Modifs) { diff --git a/ts2panda/src/statement/returnStatement.ts b/ts2panda/src/statement/returnStatement.ts index 221db0bb2ea960d4c493bc41513e150f2f13867e..90510ba9b302d69ed5beac92d4b79c98e2a3bfe0 100644 --- a/ts2panda/src/statement/returnStatement.ts +++ b/ts2panda/src/statement/returnStatement.ts @@ -134,8 +134,8 @@ function compileNormalReturn(stmt: ts.ReturnStatement, returnValue: VReg, compil } function isReturnInDerivedCtor(stmt: ts.ReturnStatement) { - let funcNode = jshelpers.getContainingFunction(stmt); - if (!ts.isConstructorDeclaration(funcNode)) { + let funcNode = jshelpers.getContainingFunctionDeclaration(stmt); + if (!funcNode || !ts.isConstructorDeclaration(funcNode)) { return false; } diff --git a/ts2panda/src/statement/tryStatement.ts b/ts2panda/src/statement/tryStatement.ts index 6107c014533de7d417e574d15db0263670f81620..d720e5420da8226cb338697f6cb146f30bf40d77 100644 --- a/ts2panda/src/statement/tryStatement.ts +++ b/ts2panda/src/statement/tryStatement.ts @@ -28,9 +28,10 @@ import { import { IteratorType, IteratorRecord } from "./forOfStatement"; import * as astutils from "../astutils"; import { VarDeclarationKind } from "../variable"; +import jshelpers from "../jshelpers"; // adjust the try...catch...finally into nested try(try...catch) finally -export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Recorder) { +export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Recorder): ts.TryStatement { // after create new try block node, mapped with new scope, and adjust parent node let tryStmtScope = recorder.getScopeOfNode(tryStmt); let newTryBlockScope = new LocalScope(tryStmtScope); @@ -38,18 +39,16 @@ export function transformTryCatchFinally(tryStmt: ts.TryStatement, recorder: Rec (recorder.getScopeOfNode(tryStmt.tryBlock)).setParent(newTryStmtScope); (recorder.getScopeOfNode(tryStmt.catchClause!)).setParent(newTryStmtScope); - const newTryStmt = ts.createTry(tryStmt.tryBlock, tryStmt.catchClause, undefined); + const newTryStmt = ts.factory.createTryStatement(tryStmt.tryBlock, tryStmt.catchClause, undefined); recorder.setScopeMap(newTryStmt, newTryStmtScope); const newTryBlock = [newTryStmt]; - newTryBlock[0].pos = tryStmt.tryBlock.pos; - newTryBlock[0].end = tryStmt.tryBlock.end; - tryStmt.tryBlock = ts.updateBlock(tryStmt.tryBlock, newTryBlock); - newTryBlock[0].parent = tryStmt.tryBlock; - + newTryBlock[0] = jshelpers.setParent(newTryBlock[0], tryStmt)!; + newTryBlock[0] = ts.setTextRange(newTryBlock[0], tryStmt.tryBlock)!; + let tryBlock = ts.factory.updateBlock(tryStmt.tryBlock, newTryBlock); + tryStmt = ts.factory.updateTryStatement(tryStmt, tryBlock, undefined, tryStmt.finallyBlock); recorder.setScopeMap(tryStmt.tryBlock, newTryBlockScope); - tryStmt.catchClause = undefined; - tryStmt = ts.updateTry(tryStmt, tryStmt.tryBlock, undefined, tryStmt.finallyBlock); + return tryStmt; } export class LabelPair { @@ -359,7 +358,7 @@ function compileCatchClauseVariableDeclaration(compiler: Compiler, param: ts.Var } export function updateCatchTables(inlinedTry: TryStatement | undefined, targetTry: TryStatement, inlinedLabelPair: LabelPair) { - for (; inlinedTry != targetTry; inlinedTry = inlinedTry ?.getOuterTryStatement()) { + for (; inlinedTry != targetTry; inlinedTry = inlinedTry?.getOuterTryStatement()) { inlinedTry!.getCatchTable().splitLabelPair(inlinedLabelPair); } targetTry.getCatchTable().splitLabelPair(inlinedLabelPair); diff --git a/ts2panda/src/syntaxChecker.ts b/ts2panda/src/syntaxChecker.ts index a9fe751ddab39b9e7381d23f1d016fc1a18b7791..185e3a2df366f5fa3369b44b7e2d68d8dd127b38 100644 --- a/ts2panda/src/syntaxChecker.ts +++ b/ts2panda/src/syntaxChecker.ts @@ -21,7 +21,7 @@ import { } from "./diagnostic"; import { hasExportKeywordModifier } from "./base/util"; import { findInnerExprOfParenthesis } from "./expression/parenthesizedExpression"; -import jshelpers, { getContainingFunction, getSourceFileOfNode } from "./jshelpers"; +import jshelpers, { getContainingFunction, getContainingFunctionDeclaration, getSourceFileOfNode } from "./jshelpers"; import { LOGE } from "./log"; import { Recorder } from "./recorder"; import { @@ -73,7 +73,7 @@ export function checkDuplicateDeclaration(recorder: Recorder) { } // implement catchParameter-related duplicate-entry check - if ((node.kind == ts.SyntaxKind.Block) && (node.parent.kind == ts.SyntaxKind.CatchClause)) { + if ((node.kind == ts.SyntaxKind.Block) && (node.parent != undefined && node.parent.kind == ts.SyntaxKind.CatchClause)) { let catchScope = scopeMap.get(node.parent); checkDuplicateInCatch(scope, catchScope); } @@ -355,12 +355,11 @@ function checkMetaProperty(node: ts.MetaProperty) { if (!getContainingFunction(node)) { throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); } else { - let func = getContainingFunction(node); - while (getContainingFunction(func)) { - func = getContainingFunction(func); + let func = getContainingFunctionDeclaration(node); + while (getContainingFunctionDeclaration(func!)) { + func = getContainingFunctionDeclaration(func!); } - - if (ts.isArrowFunction(func)) { + if (func && ts.isArrowFunction(func)) { throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); } } @@ -1051,7 +1050,7 @@ function getPropertieDeclaration(node: ts.Node, name: ts.Node) { function checkDisallowedTrailingComma(list: ts.NodeArray | undefined) { if (list && list.hasTrailingComma) { - let file = jshelpers.getSourceFileOfNode(list); + let file = jshelpers.getSourceFileOfNode(list[0]); throw new DiagnosticError(list[0], DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, file); } } @@ -1059,10 +1058,10 @@ function checkDisallowedTrailingComma(list: ts.NodeArray | undefined) { function checkParameters(parameters: ts.NodeArray) { let count = parameters.length; let optionalParameter = false; - let file = jshelpers.getSourceFileOfNode(parameters); for (let i = 0; i < count; i++) { let parameter = parameters[i]; + let file = jshelpers.getSourceFileOfNode(parameter); if (parameter.dotDotDotToken) { if (i != count - 1) { throw new DiagnosticError(parameter.dotDotDotToken, DiagnosticCode.A_rest_parameter_must_be_last_in_a_parameter_list, file); @@ -1205,6 +1204,12 @@ function checkRegularExpression(regexp: ts.RegularExpressionLiteral) { new regexpParse().parseLiteral(regexpText); } +function checkThrowStatement(node: ts.ThrowStatement) { + if (ts.isIdentifier(node.expression) && (node.expression).text === '') { + throw new DiagnosticError(node, DiagnosticCode.Line_break_not_permitted_here, jshelpers.getSourceFileOfNode(node)); + } +} + function checkSyntaxErrorForSloppyAndStrictMode(node: ts.Node) { switch (node.kind) { case ts.SyntaxKind.BreakStatement: @@ -1270,6 +1275,9 @@ function checkSyntaxErrorForSloppyAndStrictMode(node: ts.Node) { case ts.SyntaxKind.RegularExpressionLiteral: checkRegularExpression(node); break; + case ts.SyntaxKind.ThrowStatement: + checkThrowStatement(node); + break; default: break; } diff --git a/ts2panda/templates/diagnostic.ts.erb b/ts2panda/templates/diagnostic.ts.erb index a6df2d57301a1cf1c44f7573d347b324f96101de..795fda099aa820287af95bc61ec1e981a6c8638a 100755 --- a/ts2panda/templates/diagnostic.ts.erb +++ b/ts2panda/templates/diagnostic.ts.erb @@ -17,10 +17,10 @@ import { LOGE } from "./log" export class DiagnosticError { irnode:ts.Node | undefined; code:number; - file: ts.Node | undefined; + file: ts.SourceFile | undefined; args: (string | number | undefined)[]; - constructor(irnode:ts.Node | undefined, code:number,file?:ts.Node | undefined ,args?:(string | number | undefined)[]) { + constructor(irnode:ts.Node | undefined, code:number, file?:ts.SourceFile | undefined, args?:(string | number | undefined)[]) { this.code = code this.irnode = irnode this.file = file ? file : undefined @@ -40,13 +40,13 @@ export function printDiagnostic(diagnostic: ts.Diagnostic) { } -export function createDiagnosticOnFirstToken(file:ts.Node | undefined,node: ts.Node ,message: ts.DiagnosticMessage|ts.DiagnosticMessageChain,...args:(string | number | undefined)[]) { +export function createDiagnosticOnFirstToken(file:ts.SourceFile, node: ts.Node ,message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { let span = jshelpers.getSpanOfTokenAtPosition(file, node.pos); let diagnostic = jshelpers.createFileDiagnostic(file,span.start,span.length,message,...args); return diagnostic; } -export function createFileDiagnostic(file:ts.Node|undefined,node: ts.Node , message: ts.DiagnosticMessage|ts.DiagnosticMessageChain,...args:(string | number | undefined)[]) { +export function createFileDiagnostic(file:ts.SourceFile, node: ts.Node, message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { let diagnostic; let span = jshelpers.getErrorSpanForNode(file, node); @@ -68,7 +68,7 @@ export function createFileDiagnostic(file:ts.Node|undefined,node: ts.Node , mess return diagnostic; } -export function createDiagnostic(file:ts.Node|undefined, location: ts.Node | undefined, message: ts.DiagnosticMessage|ts.DiagnosticMessageChain,...args:(string | number | undefined)[]) { +export function createDiagnostic(file:ts.SourceFile | undefined, location: ts.Node | undefined, message: ts.DiagnosticMessage,...args:(string | number | undefined)[]) { var diagnostic; if (!location) { @@ -76,7 +76,7 @@ export function createDiagnostic(file:ts.Node|undefined, location: ts.Node | und } if (file) { - diagnostic = createFileDiagnostic(file,location,message,...args); + diagnostic = createFileDiagnostic(file, location, message, ...args); } else { diagnostic = jshelpers.createDiagnosticForNode(location, message, ...args) }