-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathdebugger.js
More file actions
146 lines (121 loc) · 5.3 KB
/
debugger.js
File metadata and controls
146 lines (121 loc) · 5.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
'use strict'
const Ethdebugger = require('../Ethdebugger')
const EventManager = require('../eventManager')
const traceHelper = require('../trace/traceHelper')
const BreakpointManager = require('../code/breakpointManager')
const StepManager = require('./stepManager')
const VmDebuggerLogic = require('./VmDebugger')
function Debugger (options) {
this.event = new EventManager()
this.offsetToLineColumnConverter = options.offsetToLineColumnConverter
/*
Returns a compilation result for a given address or the last one available if none are found
*/
this.compilationResult = options.compilationResult || function (contractAddress) { return null }
this.debugger = new Ethdebugger({
web3: options.web3,
compilationResult: this.compilationResult
})
this.breakPointManager = new BreakpointManager(this.debugger, async (sourceLocation) => {
const compilationResult = await this.compilationResult()
if (!compilationResult) return { start: null, end: null }
return this.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, compilationResult.source.sources, compilationResult.data.sources)
}, (step) => {
this.event.trigger('breakpointStep', [step])
})
this.debugger.setBreakpointManager(this.breakPointManager)
this.debugger.event.register('newTraceLoaded', this, () => {
this.event.trigger('debuggerStatus', [true])
})
this.debugger.event.register('traceUnloaded', this, () => {
this.event.trigger('debuggerStatus', [false])
})
this.event.register('breakpointStep', (step) => {
this.step_manager.jumpTo(step)
})
}
Debugger.prototype.registerAndHighlightCodeItem = async function (index) {
// register selected code item, highlight the corresponding source location
// this.debugger.traceManager.getCurrentCalledAddressAt(index, async (error, address) => {
try {
const address = this.debugger.traceManager.getCurrentCalledAddressAt(index)
const compilationResultForAddress = await this.compilationResult(address)
if (!compilationResultForAddress) return
this.debugger.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, index, compilationResultForAddress.data.contracts).then((rawLocation) => {
if (compilationResultForAddress && compilationResultForAddress.data) {
var lineColumnPos = this.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, compilationResultForAddress.source.sources, compilationResultForAddress.data.sources)
this.event.trigger('newSourceLocation', [lineColumnPos, rawLocation])
} else {
this.event.trigger('newSourceLocation', [null])
}
}).catch((_error) => {
this.event.trigger('newSourceLocation', [null])
})
// })
} catch (error) {
return console.log(error)
}
}
Debugger.prototype.updateWeb3 = function (web3) {
this.debugger.web3 = web3
}
Debugger.prototype.debug = function (blockNumber, txNumber, tx, loadingCb) {
const web3 = this.debugger.web3
return new Promise((resolve, reject) => {
if (this.debugger.traceManager.isLoading) {
return resolve()
}
if (tx) {
if (!tx.to) {
tx.to = traceHelper.contractCreationToken('0')
}
this.debugTx(tx, loadingCb)
return resolve()
}
try {
if (txNumber.indexOf('0x') !== -1) {
return web3.eth.getTransaction(txNumber, (_error, tx) => {
if (_error) return reject(_error)
if (!tx) return reject('cannot find transaction ' + txNumber)
this.debugTx(tx, loadingCb)
return resolve()
})
}
web3.eth.getTransactionFromBlock(blockNumber, txNumber, (_error, tx) => {
if (_error) return reject(_error)
if (!tx) return reject('cannot find transaction ' + blockNumber + ' ' + txNumber)
this.debugTx(tx, loadingCb)
return resolve()
})
} catch (e) {
return reject(e.message)
}
})
}
Debugger.prototype.debugTx = function (tx, loadingCb) {
this.step_manager = new StepManager(this.debugger, this.debugger.traceManager)
this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => {
this.debugger.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, this.step_manager.currentStepIndex, this.debugger.solidityProxy.contracts).then((sourceLocation) => {
this.vmDebuggerLogic.event.trigger('sourceLocationChanged', [sourceLocation])
})
})
this.vmDebuggerLogic = new VmDebuggerLogic(this.debugger, tx, this.step_manager, this.debugger.traceManager, this.debugger.codeManager, this.debugger.solidityProxy, this.debugger.callTree)
this.vmDebuggerLogic.start()
this.step_manager.event.register('stepChanged', this, (stepIndex) => {
if (typeof stepIndex !== 'number' || stepIndex >= this.step_manager.traceLength) {
return this.event.trigger('endDebug')
}
this.debugger.codeManager.resolveStep(stepIndex, tx)
this.step_manager.event.trigger('indexChanged', [stepIndex])
this.vmDebuggerLogic.event.trigger('indexChanged', [stepIndex])
this.vmDebuggerLogic.debugger.event.trigger('indexChanged', [stepIndex])
this.registerAndHighlightCodeItem(stepIndex)
})
loadingCb()
this.debugger.debug(tx)
}
Debugger.prototype.unload = function () {
this.debugger.unLoad()
this.event.trigger('debuggerUnloaded')
}
module.exports = Debugger