mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-22 17:39:19 +00:00
implement a more reliable evaluation queue
This commit is contained in:
102
src/debugMain.js
102
src/debugMain.js
@@ -721,7 +721,8 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
_ensureLocals(frameId) {
|
_ensureLocals(frameId) {
|
||||||
// retrieve the varinfo associated with the id
|
// retrieve the varinfo associated with the id
|
||||||
var varinfo = this._variableHandles[frameId];
|
var varinfo = this._variableHandles[frameId];
|
||||||
if (!varinfo) return $.Deferred().rejectWith(this, [new Error('Invalid frameId: '+frameId)]);
|
if (!varinfo)
|
||||||
|
return $.Deferred().rejectWith(this, [new Error('Invalid frameId: '+frameId)]);
|
||||||
// if we're currently processing it (or we've finished), just return the promise
|
// if we're currently processing it (or we've finished), just return the promise
|
||||||
if (this._locals_done[frameId]) return this._locals_done[frameId];
|
if (this._locals_done[frameId]) return this._locals_done[frameId];
|
||||||
// create a new promise
|
// create a new promise
|
||||||
@@ -734,7 +735,10 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
// cache the results and resolve the promise
|
// cache the results and resolve the promise
|
||||||
x.varinfo.cached = locals;
|
x.varinfo.cached = locals;
|
||||||
x.def.resolveWith(this, [x.varinfo]);
|
x.def.resolveWith(this, [x.varinfo]);
|
||||||
});
|
})
|
||||||
|
.fail(e => {
|
||||||
|
x.def.rejectWith(this, [e]);
|
||||||
|
})
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1208,26 +1212,66 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
// so we have to queue them or we end up with strange results
|
// so we have to queue them or we end up with strange results
|
||||||
|
|
||||||
if (this._running) {
|
if (this._running) {
|
||||||
response.body = { result:'(running)', variablesReference:0 };
|
response.success = false;
|
||||||
this.sendResponse(response);
|
response.message = '(running)';
|
||||||
|
this.sendResponse(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._evals_queue.push([response,args]);
|
|
||||||
if (this._evals_queue.length > 1)
|
// look for a matching entry in the list (other than at index:0)
|
||||||
|
var previdx = this._evals_queue.findIndex(e => e.args.expression === args.expression);
|
||||||
|
if (previdx > 0) {
|
||||||
|
// if we find a match, immediately fail the old one and queue the new one
|
||||||
|
var prev = this._evals_queue.splice(previdx,1)[0];
|
||||||
|
prev.response.success = false;
|
||||||
|
prev.response.message = '(evaluating)';
|
||||||
|
this.sendResponse(prev.response);
|
||||||
|
}
|
||||||
|
// if there's no frameId, we are being asked to evaluate the value in the 'global' context
|
||||||
|
var getlocals = args.frameId ? this._ensureLocals(args.frameId) : $.Deferred().resolve([]);
|
||||||
|
|
||||||
|
this._evals_queue.push({response,args,getlocals});
|
||||||
|
|
||||||
|
// if we're currently processing, just wait
|
||||||
|
if (this._evals_queue.length > 1) {
|
||||||
return;
|
return;
|
||||||
// start the evaluations
|
}
|
||||||
|
|
||||||
|
// begin processing
|
||||||
this.doNextEvaluateRequest();
|
this.doNextEvaluateRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
doNextEvaluateRequest() {
|
doNextEvaluateRequest() {
|
||||||
if (!this._evals_queue.length) return;
|
if (!this._evals_queue.length) {
|
||||||
var args = this._evals_queue[0][1];
|
return;
|
||||||
// if there's no frameId, we are being asked to evaluate the value in the 'global' context
|
}
|
||||||
var getLocals = args.frameId ? this._ensureLocals(args.frameId) : $.Deferred().resolve();
|
if (this._running) {
|
||||||
|
while (this._evals_queue.length) {
|
||||||
|
var {response} = this._evals_queue.shift();
|
||||||
|
response.success = false;
|
||||||
|
response.message = '(running)';
|
||||||
|
this.sendResponse(response);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var {response, args, getlocals} = this._evals_queue[0];
|
||||||
|
|
||||||
// wait for any locals in the given context to be retrieved
|
// wait for any locals in the given context to be retrieved
|
||||||
getLocals.then(() => {
|
getlocals.then(locals => {
|
||||||
this.doEvaluateRequest.apply(this, this._evals_queue[0]);
|
return this.evaluate(args.expression, locals && locals.cached);
|
||||||
});
|
})
|
||||||
|
.then((value,variablesReference) => {
|
||||||
|
response.body = { result:value, variablesReference:variablesReference|0 };
|
||||||
|
})
|
||||||
|
.fail(e => {
|
||||||
|
response.success = false;
|
||||||
|
response.message = e.message;
|
||||||
|
})
|
||||||
|
.always(() => {
|
||||||
|
this.sendResponse(response);
|
||||||
|
this._evals_queue.shift();
|
||||||
|
this.doNextEvaluateRequest();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
createJavaString(s, opts) {
|
createJavaString(s, opts) {
|
||||||
@@ -1236,33 +1280,6 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
return this.dbgr.createstring(raw);
|
return this.dbgr.createstring(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
doEvaluateRequest(response, args) {
|
|
||||||
|
|
||||||
const sendEvaluateResponseAndDoNext = (value, varref) => {
|
|
||||||
response.body = { result:value, variablesReference:varref|0 };
|
|
||||||
this.sendResponse(response);
|
|
||||||
this._evals_queue.shift();
|
|
||||||
this.doNextEvaluateRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
// just in case the user starts the app running again, before we've evaluated everything in the queue
|
|
||||||
if (this._running) {
|
|
||||||
sendEvaluateResponseAndDoNext('(running)');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var v = this._variableHandles[args.frameId];
|
|
||||||
var locals = v && v.frame && v.cached;
|
|
||||||
|
|
||||||
this.evaluate(args.expression, locals)
|
|
||||||
.then((value,variablesReference) => {
|
|
||||||
sendEvaluateResponseAndDoNext(value, variablesReference);
|
|
||||||
})
|
|
||||||
.fail(err => {
|
|
||||||
sendEvaluateResponseAndDoNext(err.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Asynchronously evaluate an expression
|
Asynchronously evaluate an expression
|
||||||
*/
|
*/
|
||||||
@@ -1356,8 +1373,7 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
local = { vtype:'literal',name:'',hasnullvalue:true,type:JTYPES.null,value:nullvalue,valid:true };
|
local = { vtype:'literal',name:'',hasnullvalue:true,type:JTYPES.null,value:nullvalue,valid:true };
|
||||||
break;
|
break;
|
||||||
case 'ident':
|
case 'ident':
|
||||||
if (!locals) return reject_evaluation(`Cannot find variable: ${expr.root_term}`);
|
local = locals && locals.find(l => l.name === expr.root_term);
|
||||||
local = locals.find(l => l.name === expr.root_term);
|
|
||||||
break;
|
break;
|
||||||
case 'number':
|
case 'number':
|
||||||
local = evaluate_number(expr.root_term);
|
local = evaluate_number(expr.root_term);
|
||||||
|
|||||||
@@ -712,6 +712,8 @@ Debugger.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getsupertype: function (local, extra) {
|
getsupertype: function (local, extra) {
|
||||||
|
if (local.type.signature==='Ljava/lang/Object;')
|
||||||
|
return $.Deferred().rejectWith(this,[new Error('java.lang.Object has no super type')]);
|
||||||
return this.gettypedebuginfo(local.type.signature, { local: local, extra: extra })
|
return this.gettypedebuginfo(local.type.signature, { local: local, extra: extra })
|
||||||
.then(function (dbgtype, x) {
|
.then(function (dbgtype, x) {
|
||||||
return this._ensuresuper(dbgtype[x.local.type.signature])
|
return this._ensuresuper(dbgtype[x.local.type.signature])
|
||||||
|
|||||||
Reference in New Issue
Block a user