add expression watch for IDE <wanggang203@huawei.com>

Signed-off-by: Gavin1012 <wanggang203@huawei.com>
Change-Id: I0bbf40e5ec373ae3f80cc7a9930aa34cc0b49fa8
This commit is contained in:
Gavin1012
2022-04-20 16:31:05 +08:00
parent c83098b745
commit 1265a370a5
7 changed files with 963 additions and 15 deletions
+8 -1
View File
@@ -304,4 +304,11 @@ export function setPos(node: ts.Node) {
setPos(childNode);
});
return node;
}
}
export function isBase64Str(input: string): boolean {
if (input == '' || input.trim() == '') {
return false;
}
return Buffer.from(Buffer.from(input, 'base64').toString()).toString('base64') == input;
}
+19
View File
@@ -26,6 +26,7 @@ const ts2pandaOptions = [
{ name: 'debug-log', alias: 'l', type: Boolean, defaultValue: false, description: "show info debug log and generate the json file."},
{ name: 'dump-assembly', alias: 'a', type: Boolean, defaultValue: false, description: "dump assembly to file." },
{ name: 'debug', alias: 'd', type: Boolean, defaultValue: false, description: "compile with debug info." },
{ name: 'debug-add-watch', alias: 'w', type: String, lazyMultiple: true, defaultValue: [], description: "watch expression and abc file path in debug mode." },
{ name: 'show-statistics', alias: 's', type: String, lazyMultiple: true, defaultValue: "", description: "show compile statistics(ast, histogram, hoisting, all)." },
{ name: 'output', alias: 'o', type: String, defaultValue: "", description: "set output file." },
{ name: 'timeout', alias: 't', type: Number, defaultValue: 0, description: "js to abc timeout threshold(unit: seconds)." },
@@ -71,6 +72,24 @@ export class CmdOptions {
return this.options["debug"];
}
static getAddWatchArgs(): string[] {
if (!this.options) {
return [];
}
return this.options["debug-add-watch"];
}
static isWatchMode(): boolean {
if (!this.options) {
return false;
}
return this.options["debug-add-watch"].length != 0;
}
static setWatchArgs(watchArgs: string[]) {
this.options["debug-add-watch"] = watchArgs;
}
static isModules(): boolean {
if (!this.options) {
return false;
+7 -5
View File
@@ -327,7 +327,8 @@ export class Compiler {
this.funcBuilder.resolve(NodeKind.Invalid, getVregisterCache(pandaGen, CacheList.undefined));
pandaGen.return(NodeKind.Invalid);
} else {
pandaGen.returnUndefined(NodeKind.Invalid);
CmdOptions.isWatchMode() ? pandaGen.return(NodeKind.Invalid)
: pandaGen.returnUndefined(NodeKind.Invalid);
}
}
}
@@ -950,8 +951,8 @@ export class Compiler {
// typeof an undeclared variable will return undefined instead of throwing reference error
let parent = findOuterNodeOfParenthesis(id);
if ((parent.kind == ts.SyntaxKind.TypeOfExpression)) {
let obj = getVregisterCache(pandaGen, CacheList.Global);
pandaGen.loadObjProperty(id, obj, name);
CmdOptions.isWatchMode() ? pandaGen.loadByNameViaDebugger(id, name, CacheList.False)
: pandaGen.loadObjProperty(id, getVregisterCache(pandaGen, CacheList.Global), name);
} else {
pandaGen.tryLoadGlobalByName(id, name);
}
@@ -1555,8 +1556,9 @@ export class Compiler {
if (variable.v.isNone()) {
let parent = findOuterNodeOfParenthesis(node);
if ((parent.kind == ts.SyntaxKind.TypeOfExpression)) {
let obj = getVregisterCache(this.pandaGen, CacheList.Global);
this.pandaGen.loadObjProperty(node, obj, variable.v.getName());
CmdOptions.isWatchMode() ? this.pandaGen.loadByNameViaDebugger(node, variable.v.getName(),
CacheList.False) : this.pandaGen.loadObjProperty(node, getVregisterCache(this.pandaGen,
CacheList.Global), variable.v.getName());
} else {
this.pandaGen.tryLoadGlobalByName(node, variable.v.getName());
}
+39 -1
View File
@@ -23,7 +23,7 @@ import * as jshelpers from "./jshelpers";
import { LOGE } from "./log";
import { setGlobalDeclare, setGlobalStrict } from "./strictMode";
import { TypeChecker } from "./typeChecker";
import { setPos } from "./base/util";
import { setPos, isBase64Str } from "./base/util";
function checkIsGlobalDeclaration(sourceFile: ts.SourceFile) {
for (let statement of sourceFile.statements) {
@@ -154,6 +154,33 @@ function getDtsFiles(libDir: string): string[] {
return dtsFiles;
}
function parseWatch(files: string[]): string {
let watchArgs = CmdOptions.getAddWatchArgs();
let ideIputStr = watchArgs[0];
if (watchArgs.length != 2 || !isBase64Str(ideIputStr)) {
throw new Error("Incorrect args' format or not enter base64 string in watch mode.");
}
let fragmentSep = "\\n";
let originExpre = Buffer.from(ideIputStr, 'base64').toString();
let expressiones = originExpre.split(fragmentSep);
let jsFileName = watchArgs[1] + path.sep + "watch_expres.js";
let abcFileName = watchArgs[1] + path.sep + "watch_expres.abc";
let writeFlag: Boolean = false;
for (let index = 0; index < expressiones.length; index++) {
let expreLine = expressiones[index].trim();
if (expreLine != "") {
if (!writeFlag) {
fs.writeFileSync(jsFileName, expreLine + "\n");
writeFlag = true;
} else {
fs.appendFileSync(jsFileName, expreLine + "\n");
}
}
}
files.unshift(jsFileName);
return abcFileName;
}
namespace Compiler {
export namespace Options {
export let Default: ts.CompilerOptions = {
@@ -183,7 +210,18 @@ function run(args: string[], options?: ts.CompilerOptions): void {
}
try {
let files: string[] = parsed.fileNames;
let abcFileName: string = '';
if (CmdOptions.isWatchMode()) {
abcFileName = parseWatch(files);
}
main(files.concat(CmdOptions.getIncludedFiles()), parsed.options);
if (CmdOptions.isWatchMode() && !CmdOptions.isAssemblyMode()) {
process.on('exit', () => {
let base64data = fs.readFileSync(abcFileName);
let watchResStr = Buffer.from(base64data).toString('base64');
console.log(watchResStr);
});
}
} catch (err) {
if (err instanceof diag.DiagnosticError) {
let diagnostic = diag.getDiagnostic(err.code);
+31 -6
View File
@@ -614,17 +614,42 @@ export class PandaGen {
this.add(node, storeOwnByValue(obj, value, nameSetting));
}
loadByNameViaDebugger(node: ts.Node, string_id: string, boolVal: CacheList) {
this.loadObjProperty(node, getVregisterCache(this, CacheList.Global), "debuggerGetValue");
let getValueReg = this.getTemp();
this.storeAccumulator(node, getValueReg);
let variableReg = this.getTemp();
this.loadAccumulatorString(node, string_id);
this.storeAccumulator(node, variableReg);
let trueValueReg = this.getTemp();
this.moveVreg(node, trueValueReg, getVregisterCache(this, boolVal));
this.call(node, [getValueReg, variableReg, trueValueReg], false);
this.freeTemps(getValueReg, variableReg, trueValueReg);
}
// eg. print
tryLoadGlobalByName(node: ts.Node, string_id: string) {
this.add(
node,
tryLoadGlobalByName(string_id));
CmdOptions.isWatchMode() ? this.loadByNameViaDebugger(node, string_id, CacheList.True)
: this.add(node, tryLoadGlobalByName(string_id));
}
storeByNameViaDebugger(node: ts.Node, string_id: string) {
let valueReg = this.getTemp();
this.storeAccumulator(node, valueReg);
this.loadObjProperty(node, getVregisterCache(this, CacheList.Global), "debuggerSetValue");
let setValueReg = this.getTemp();
this.storeAccumulator(node, setValueReg);
let variableReg = this.getTemp();
this.loadAccumulatorString(node, string_id);
this.storeAccumulator(node, variableReg);
this.call(node, [setValueReg, variableReg, valueReg], false);
this.freeTemps(valueReg, setValueReg, variableReg);
}
// eg. a = 1
tryStoreGlobalByName(node: ts.Node, string_id: string) {
this.add(node,
tryStoreGlobalByName(string_id));
CmdOptions.isWatchMode() ? this.storeByNameViaDebugger(node, string_id)
: this.add(node, tryStoreGlobalByName(string_id));
}
// eg. var n; n;
@@ -1257,7 +1282,7 @@ export class PandaGen {
node,
stClassToGlobalRecord(string_id));
}
loadAccumulatorBigInt(node: ts.Node | NodeKind, str: string) {
this.add(
node,
+4 -2
View File
@@ -31,6 +31,7 @@ import {
import { setGlobalStrict } from "../../src/strictMode";
import { creatAstFromSnippet } from "./asthelper";
import { LiteralBuffer } from "../../src/base/literal";
import { CmdOptions } from "../../src/cmdOptions";
const compileOptions = {
outDir: "../tmp/build",
@@ -142,7 +143,8 @@ export function checkInstructions(actual: IRNode[], expected: IRNode[], checkFn?
export function compileAllSnippet(snippet: string, passes?: Pass[], literalBufferArray?: Array<LiteralBuffer>): PandaGen[] {
let sourceFile = creatAstFromSnippet(snippet);
jshelpers.bindSourceFile(sourceFile, {});
setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions));
CmdOptions.isWatchMode() ? setGlobalStrict(true)
: setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(sourceFile, compileOptions));
let compilerDriver = new CompilerDriver('UnitTest');
if (!passes) {
@@ -188,7 +190,7 @@ export function compileAfterSnippet(snippet: string, name:string) {
let compilerDriver = new CompilerDriver('UnitTest');
compilerDriver.setCustomPasses([]);
compilerDriver.compileUnitTest(sourceFile, []);
compileUnits = compilerDriver.getCompilationUnits();
compileUnits = compilerDriver.getCompilationUnits();
return sourceFile;
}
}
@@ -0,0 +1,855 @@
/*
* Copyright (c) 2022 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.
*/
import {
expect
} from 'chai';
import 'mocha';
import { CmdOptions } from '../../src/cmdOptions';
import {
EcmaAdd2dyn,
EcmaAsyncfunctionawaituncaught,
EcmaAsyncfunctionenter,
EcmaAsyncfunctionreject,
EcmaAsyncfunctionresolve,
EcmaCallarg0dyn,
EcmaCallarg1dyn,
EcmaCallargs2dyn,
EcmaCreatearraywithbuffer,
EcmaCreateemptyarray,
EcmaCreategeneratorobj,
EcmaCreateiterresultobj,
EcmaCreateobjectwithbuffer,
EcmaCreateregexpwithliteral,
EcmaDecdyn,
EcmaDefineclasswithbuffer,
EcmaDefinefuncdyn,
EcmaEqdyn,
EcmaGetresumemode,
EcmaIstrue,
EcmaLdobjbyindex,
EcmaLdobjbyname,
EcmaNegdyn,
EcmaNewobjdynrange,
EcmaResumegenerator,
EcmaStownbyindex,
EcmaStricteqdyn,
EcmaSuspendgenerator,
EcmaThrowdyn,
EcmaTonumber,
EcmaTypeofdyn,
FldaiDyn,
Imm,
Jeqz,
Jmp,
Label,
LdaDyn,
LdaStr,
LdaiDyn,
MovDyn,
ReturnDyn,
StaDyn,
VReg
} from "../../src/irnodes";
import { LocalVariable } from "../../src/variable";
import { checkInstructions, compileMainSnippet, compileAllSnippet, SnippetCompiler } from "../utils/base";
describe("WatchExpressions", function () {
it("watch NumericLiteral", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a=-123.212
`);
let expected = [
new FldaiDyn(new Imm(123.212)),
new StaDyn(new VReg()),
new EcmaNegdyn(new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerSetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch StringLiteral", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
y = 'He is called \'Johnny\''
`);
let expected = [
new LdaStr('He is called '),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerSetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('y'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('Johnny'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new LdaStr(''),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch RegularExpressionLiteral", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a = /abc/
`);
let expected = [
new EcmaCreateregexpwithliteral('abc', new Imm(0)),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerSetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch Identifier", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
_awef
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('_awef'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch TrueKeyword", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
b === true
`);
let isTrueLabel = new Label();
let isFalseLabel = new Label();
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('b'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new EcmaStricteqdyn(new VReg()),
new Jeqz(isTrueLabel),
new LdaDyn(new VReg()),
new Jmp(isFalseLabel),
isTrueLabel,
new LdaDyn(new VReg()),
isFalseLabel,
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch FalseKeyword", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
b === false
`);
let ifFalseLabel = new Label(); //lable0
let ifTrueLabel = new Label(); //label1
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('b'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new EcmaStricteqdyn(new VReg()),
new Jeqz(ifFalseLabel),
new LdaDyn(new VReg()),
new Jmp(ifTrueLabel),
ifFalseLabel,
new LdaDyn(new VReg()), //lda.dyn v10
ifTrueLabel,
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch CallExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
BigInt(10.2)
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('BigInt'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new FldaiDyn(new Imm(10.2)),
new StaDyn(new VReg()),
new EcmaCallarg1dyn(new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch NullKeyword", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
b === null
`);
let isTrueLabel = new Label();
let isFalseLabel = new Label();
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('b'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new EcmaStricteqdyn(new VReg()),
new Jeqz(isTrueLabel),
new LdaDyn(new VReg()),
new Jmp(isFalseLabel),
isTrueLabel,
new LdaDyn(new VReg()),
isFalseLabel,
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch ThisKeyword", function () {
let snippetCompiler = new SnippetCompiler();
snippetCompiler.compile("this");
let globalScope = snippetCompiler.getGlobalScope();
let insns = snippetCompiler.getGlobalInsns();
let expected = [
new LdaDyn(new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
let thisVar = globalScope!.findLocal("this");
expect(thisVar instanceof LocalVariable).to.be.true;
});
it("watch MetaProperty", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let pandaGens = compileAllSnippet(`
function (){
b = new.target;
}
`);
let expected = [
new LdaDyn(new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname("debuggerSetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr("b"),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
pandaGens.forEach((pg) => {
if (pg.internalName == "#1#") {
expect(checkInstructions(pg.getInsns(), expected)).to.be.true;
}
});
});
it("watch ArrayLiteralExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
[1,2]
`);
let expected = [
new EcmaCreatearraywithbuffer(new Imm(1)),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch ObjectLiteralExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a = {key:1,value:1}
`);
let expected = [
new EcmaCreateobjectwithbuffer(new Imm(1)),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerSetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch PropertyAccessExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a.b
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('b', new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch ElementAccessExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a[0]
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue',new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyindex(new VReg(), new Imm(0)),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch NewExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
new Function()
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('Function'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaNewobjdynrange(new Imm(2), [new VReg(), new VReg()]),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch ParenthesizedExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
(a,b,c)
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('b'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('c'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch FunctionExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let pandaGens = compileAllSnippet(`
a = function () {}
`);
let expected = [
new EcmaDefinefuncdyn('a', new Imm(0), new VReg()),
new StaDyn(new VReg),
new EcmaLdobjbyname('debuggerSetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
pandaGens.forEach((pg) => {
if (pg.internalName == "func_main_0") {
expect(checkInstructions(pg.getInsns(), expected)).to.be.true;
}
});
});
it("watch DeleteExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
delete[abc]
`);
let expected = [
new EcmaCreateemptyarray(),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('abc'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new EcmaStownbyindex(new VReg(), new Imm(0)),
new LdaDyn(new VReg()),
new LdaDyn(new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch TypeOfExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
typeof(a)
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new EcmaTypeofdyn(),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch VoidExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
void doSomething()
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('doSomething'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaCallarg0dyn(new VReg()),
new LdaDyn(new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch AwaitExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let pandaGens = compileAllSnippet(
`async function a(){
await abc;
}`
);
let beginLabel = new Label();
let endLabel = new Label();
let nextLabel = new Label();
let expected = [
new EcmaAsyncfunctionenter(),
new StaDyn(new VReg()),
beginLabel,
new EcmaLdobjbyname("debuggerGetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr('abc'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaAsyncfunctionawaituncaught(new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaSuspendgenerator(new VReg(), new VReg()),
new EcmaResumegenerator(new VReg()),
new StaDyn(new VReg()),
new EcmaGetresumemode(new VReg()),
new StaDyn(new VReg()),
new LdaiDyn(new Imm(1)),
new EcmaEqdyn(new VReg()),
new Jeqz(nextLabel),
new LdaDyn(new VReg()),
new EcmaThrowdyn(),
nextLabel,
new LdaDyn(new VReg()),
new EcmaAsyncfunctionresolve(new VReg(), new VReg(), new VReg()),
new ReturnDyn(),
endLabel,
new StaDyn(new VReg()),
new EcmaAsyncfunctionreject(new VReg(), new VReg(), new VReg()),
new ReturnDyn(),
];
pandaGens.forEach((pg) => {
if (pg.internalName == "a") {
expect(checkInstructions(pg.getInsns(), expected)).to.be.true;
}
});
});
it("watch PrefixUnaryExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
--a
`);
let expected = [
new EcmaLdobjbyname("debuggerGetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaDecdyn(new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname("debuggerSetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch PostfixUnaryExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a--
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaDecdyn(new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('debuggerSetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new EcmaTonumber(new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch BinaryExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a+b
`);
let expected = [
new EcmaLdobjbyname("debuggerGetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr("a"),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname("debuggerGetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr("b"),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new EcmaAdd2dyn(new VReg()),
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch ConditionalExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let insns = compileMainSnippet(`
a?4:2
`);
let ifTrueLabel = new Label();
let ifFalseLabel = new Label();
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new EcmaIstrue(),
new Jeqz(ifTrueLabel),
new LdaiDyn(new Imm(4)),
new Jmp(ifFalseLabel),
ifTrueLabel,
new LdaiDyn(new Imm(2)),
ifFalseLabel,
new ReturnDyn()
];
expect(checkInstructions(insns, expected)).to.be.true;
});
it("watch YieldExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let pandaGens = compileAllSnippet(`
function* func(){
yield a;
}`);
let startLabel = new Label();
let thenLabel = new Label();
let nextLabel = new Label();
let endLabel = new Label();
let expected = [
new EcmaCreategeneratorobj(new VReg()),
new StaDyn(new VReg()),
new EcmaSuspendgenerator(new VReg(), new VReg()),
new EcmaResumegenerator(new VReg()),
new StaDyn(new VReg()),
new EcmaGetresumemode(new VReg()),
new StaDyn(new VReg()),
new LdaiDyn(new Imm(0)),
new EcmaEqdyn(new VReg()),
new Jeqz(startLabel),
new LdaDyn(new VReg()),
new ReturnDyn(),
startLabel,
new LdaiDyn(new Imm(1)),
new EcmaEqdyn(new VReg()),
new Jeqz(thenLabel),
new LdaDyn(new VReg()),
new EcmaThrowdyn(),
thenLabel,
new LdaDyn(new VReg()),
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('a'),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new StaDyn(new VReg()),
new EcmaCreateiterresultobj(new VReg(),new VReg()),
new StaDyn(new VReg()),
new EcmaSuspendgenerator(new VReg(), new VReg()),
new EcmaResumegenerator(new VReg()),
new StaDyn(new VReg()),
new EcmaGetresumemode(new VReg()),
new StaDyn(new VReg()),
new LdaiDyn(new Imm(0)),
new EcmaEqdyn(new VReg()),
new Jeqz(nextLabel),
new LdaDyn(new VReg()),
new ReturnDyn(),
nextLabel,
new LdaiDyn(new Imm(1)),
new EcmaEqdyn(new VReg()),
new Jeqz(endLabel),
new LdaDyn(new VReg()),
new EcmaThrowdyn(),
endLabel,
new LdaDyn(new VReg()),
new ReturnDyn()
];
pandaGens.forEach((pg) => {
if (pg.internalName == "func") {
expect(checkInstructions(pg.getInsns(), expected)).to.be.true;
}
});
});
it("watch ArrowFunction", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let pandaGens = compileAllSnippet(`
a => b.length
`);
let expected = [
new EcmaLdobjbyname('debuggerGetValue', new VReg()),
new StaDyn(new VReg()),
new LdaStr('b'),
new StaDyn(new VReg()),
new MovDyn(new VReg(),new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(),new VReg()),
new StaDyn(new VReg()),
new EcmaLdobjbyname('length', new VReg()),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new ReturnDyn()
];
pandaGens.forEach((pg) => {
if (pg.internalName == "#1#") {
expect(checkInstructions(pg.getInsns(), expected)).to.be.true;
}
});
});
it("watch ClassExpression", function () {
CmdOptions.parseUserCmd([""]);
CmdOptions.setWatchArgs(['','']);
let pandaGens = compileAllSnippet(`
a = new class{};
`);
let expected = [
new MovDyn(new VReg(), new VReg()),
new EcmaDefineclasswithbuffer("#1#", new Imm(1), new Imm(0), new VReg(), new VReg()),
new StaDyn(new VReg()),
new LdaDyn(new VReg()),
new StaDyn(new VReg()),
new MovDyn(new VReg(), new VReg()),
new EcmaNewobjdynrange(new Imm(2), [new VReg(), new VReg()]),
new StaDyn(new VReg()),
new EcmaLdobjbyname("debuggerSetValue", new VReg()),
new StaDyn(new VReg()),
new LdaStr("a"),
new StaDyn(new VReg()),
new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()),
new ReturnDyn()
];
pandaGens.forEach((pg) => {
if (pg.internalName == "func_main_0") {
expect(checkInstructions(pg.getInsns(), expected)).to.be.true;
}
});
});
});