Skip to content
This repository has been archived by the owner on Jul 3, 2019. It is now read-only.

Commit

Permalink
ability to evaluate documents classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximilian Wehrstedt committed Sep 17, 2018
1 parent a007d4f commit 06d9419
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,5 @@ jspm_packages

# Coverage report
coverage

out
4 changes: 0 additions & 4 deletions out/.gitignore

This file was deleted.

3 changes: 0 additions & 3 deletions out/src/.gitignore

This file was deleted.

7 changes: 4 additions & 3 deletions src/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,8 @@ export class JanusDebugSession extends DebugSession {
// different for each scope
// the frameId itself is not used in variablesMap
const frameRef = frame.frameId + 1;
locals.forEach(variable => {
this.variablesMap.createVariable(variable.name, variable.value, contextId, frameRef);
locals.forEach(async variable => {
await this.variablesMap.createVariable(variable.name, variable.value, contextId, context, frameRef);
});
log.debug(`stackTraceRequest succeeded`);
response.success = true;
Expand Down Expand Up @@ -1072,10 +1072,11 @@ export class JanusDebugSession extends DebugSession {
// Request the variable and insert it to the variables map
const evaluateName = collapsedVariable.evaluateName.replace(".___jsrdbg_collapsed___", "");
const variable = await context.evaluate(evaluateName);
this.variablesMap.createVariable(
await this.variablesMap.createVariable(
evaluateName.substr(evaluateName.lastIndexOf('.')),
JSON.parse(variable.value),
variablesContainer.contextId,
context,
args.variablesReference,
evaluateName
);
Expand Down
65 changes: 53 additions & 12 deletions src/variablesMap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Logger } from 'node-file-log';
import { DebugProtocol } from 'vscode-debugprotocol';
import { cantorPairing, reverseCantorPairing } from './cantor';

import { Context } from "./context";
const log = Logger.create('VariablesMap');

export type VariablesReference = number;
Expand Down Expand Up @@ -69,7 +69,7 @@ export class VariablesMap {
* @param {number} frameId The frame id.
* @param {string} [evaluateName] This param is need for evaluate variables that are properties of object or elements of arrays. For this variables we need also the name of their parent to access the value.
*/
public createVariable(variableName: string, variableValue: any, contextId: number, frameId: number, evaluateName?: string) {
public async createVariable(variableName: string, variableValue: any, contextId: number, context: Context, frameId: number, evaluateName?: string) {
if (typeof evaluateName === 'undefined') {
evaluateName = '';
}
Expand All @@ -78,7 +78,7 @@ export class VariablesMap {
const variablesContainer: VariablesContainer = this.variablesMap.get(frameId) || new VariablesContainer(contextId);

// If the container already contains a variable with this name => update
const variable = this._createVariable(variableName, variableValue, contextId, frameId, evaluateName);
const variable = await this._createVariable(variableName, variableValue, contextId, context, frameId, evaluateName);

if (variablesContainer.variables.length > 0) {
const filterResult = variablesContainer.variables.filter((element) => {
Expand Down Expand Up @@ -109,7 +109,7 @@ export class VariablesMap {
* @param {string} [evaluateName=variableName] This param is need for evaluate variables that are properties of object or elements of arrays. For this variables we need also the name of their parent to access the value.
* @returns {Variable} A full qualified variable object
*/
private _createVariable(variableName: string, variableValue: any, contextId: number, frameId: number, evaluateName?: string): DebugProtocol.Variable {
private async _createVariable(variableName: string, variableValue: any, contextId: number, context: Context, frameId: number, evaluateName?: string): Promise<DebugProtocol.Variable> {
if (typeof evaluateName === 'undefined' || evaluateName === '') {
evaluateName = variableName;
}
Expand Down Expand Up @@ -183,9 +183,9 @@ export class VariablesMap {
if (variableValue === null) {
return this.createPrimitiveVariable(variableName, variableValue, evaluateName);
} else if (variableValue.hasOwnProperty("length")) {
return this.createArrayVariable(variableName, variableValue, contextId, frameId, evaluateName);
return await this.createArrayVariable(variableName, variableValue, contextId, context, frameId, evaluateName);
} else {
return this.createObjectVariable(variableName, variableValue, contextId, frameId, evaluateName);
return await this.createObjectVariable(variableName, variableValue, contextId, context, frameId, evaluateName);
}

default:
Expand Down Expand Up @@ -232,7 +232,7 @@ export class VariablesMap {
* @param {string} evaluateName This param is need for evaluate variables that are properties of object or elements of arrays. For this variables we need also the name of their parent to access the value.
* @returns {Variable} A full qualified variables object.
*/
private createArrayVariable(variableName: string, variableValue: any[], contextId: number, frameId: number, evaluateName: string): DebugProtocol.Variable {
private async createArrayVariable(variableName: string, variableValue: any[], contextId: number, context: Context, frameId: number, evaluateName: string): Promise<DebugProtocol.Variable> {
if (variableName === '') {
throw new Error('Variables name cannot be empty.');
}
Expand All @@ -249,7 +249,7 @@ export class VariablesMap {
const _evaluateName = (key === 'length') ? `${evaluateName}.length` : `${evaluateName}[${index.toString()}]`;

variablesContainer.variables.push(
this._createVariable(_variableName, variableValue[key], contextId, frameId, _evaluateName)
await this._createVariable(_variableName, variableValue[key], contextId, context, frameId, _evaluateName)
);

index++;
Expand Down Expand Up @@ -277,25 +277,66 @@ export class VariablesMap {
* @param {string} evaluateName This param is need for evaluate variables that are properties of object or elements of arrays. For this variables we need also the name of their parent to access the value.
* @returns {Variable} A full qualified variables object.
*/
private createObjectVariable(variableName: string, variableValue: any, contextId: number, frameId: number, evaluateName: string): DebugProtocol.Variable {
private async createObjectVariable(variableName: string, variableValue: any, contextId: number, context: Context, frameId: number, evaluateName: string): Promise<DebugProtocol.Variable> {
if (variableName === '') {
throw new Error('Variables name cannot be empty.');
}

const variablesContainer: VariablesContainer = new VariablesContainer(contextId);

// if it's an object, request the string representation to parse it
const stringifyFunctionsReplacer = (key: any, value: any) => {
if (typeof value === "function") {
return "function " + value.toString().match(/(\([^\)]*\))/)[1] + "{ ... }";
} else {
return value;
}
};
const evaluateExpression = `(function () {
if (${variableName}) {
if (typeof ${variableName} === "object") {
if (${variableName} instanceof DocFile) {
return ${variableName}.asJSON();
} else if (${variableName} instanceof Date) {
return "new Date(" + ${variableName}.getTime() + ")";
} else if (${variableName} instanceof FileResultset) {
return JSON.stringify({
getIds: ${variableName}.getIds(),
size: ${variableName}.size()
});
} else if (${variableName} instanceof HitResultset) {
return JSON.stringify({
getHitIds: (typeof ${variableName}.getHitIds === "function") ? ${variableName}.getHitIds() : null,
size: ${variableName}.size()
});
}
}
}
return JSON.stringify(${variableName}, ${stringifyFunctionsReplacer.toString()});
}`.replace(/\r?\n|\t/g, "") + ")()";

try {
let _variableValue = await context.evaluate2(evaluateExpression);
/* tslint:disable-next-line */
_variableValue = eval("_variableValue = " + _variableValue + ";");
variableValue = _variableValue;
} catch (err) {
log.debug(`evaluate failed: ${JSON.stringify(err)} => ${err.message}`);
}

if (variableValue.hasOwnProperty('___jsrdbg_function_desc___')) {
// Functions will be recognized as objects because of the way the debugger evaluate functions
let functionParams = variableValue.___jsrdbg_function_desc___.parameterNames;
functionParams = functionParams.toString().replace(/,/, ', ');

return this.createPrimitiveVariable(variableName, 'function (' + functionParams + ') { ... }', `${evaluateName}.${variableName}`);
} else {
} else if (!(variableValue instanceof Date)) {
// Create a new variable for each property on this object and chain them together with the reference property
for (const key in variableValue) {
if (variableValue.hasOwnProperty(key)) {
variablesContainer.variables.push(
this._createVariable(key, variableValue[key], contextId, frameId, `${evaluateName}.${key}`)
await this._createVariable(key, variableValue[key], contextId, context, frameId, `${evaluateName}.${key}`)
);
}
}
Expand All @@ -308,7 +349,7 @@ export class VariablesMap {
name: variableName,
evaluateName,
type: 'object',
value: '[Object]',
value: (variableValue.constructor.name === "Date") ? variableValue : variableValue.constructor.name,
variablesReference: reference
};
}
Expand Down
9 changes: 5 additions & 4 deletions test/variablesMap.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as assert from 'assert';
import { Context } from "../src/context";
import { VariablesContainer, VariablesMap } from '../src/variablesMap';

suite('variables map tests', () => {
Expand All @@ -12,7 +13,7 @@ suite('variables map tests', () => {
});

test('createStringVariable', () => {
variablesMap.createVariable('stringVariable', 'myValue', 1, 1);
variablesMap.createVariable('stringVariable', 'myValue', 1, null as any, 1);
const variablesContainer: VariablesContainer = variablesMap.getVariables(1);

assert.equal(variablesContainer.variables.length, 1);
Expand All @@ -24,7 +25,7 @@ suite('variables map tests', () => {
});

test('createIntVariable', () => {
variablesMap.createVariable('intVariable', 666, 1, 2);
variablesMap.createVariable('intVariable', 666, 1, null as any, 2);
const variablesContainer: VariablesContainer = variablesMap.getVariables(2);

assert.equal(variablesContainer.variables.length, 1);
Expand All @@ -36,7 +37,7 @@ suite('variables map tests', () => {
});

test('createBooleanVariable', () => {
variablesMap.createVariable('booleanVariable', true, 1, 3);
variablesMap.createVariable('booleanVariable', true, 1, null as any, 3);
const variablesContainer: VariablesContainer = variablesMap.getVariables(3);

assert.equal(variablesContainer.variables.length, 1);
Expand All @@ -48,7 +49,7 @@ suite('variables map tests', () => {
});

test('createUndefinedVariable', () => {
variablesMap.createVariable('undefinedVariable', undefined, 1, 4);
variablesMap.createVariable('undefinedVariable', undefined, 1, null as any, 4);
const variablesContainer: VariablesContainer = variablesMap.getVariables(4);

assert.equal(variablesContainer.variables.length, 1);
Expand Down

0 comments on commit 06d9419

Please sign in to comment.