@serverless/tencent-tornado
Version:
Tencent Cloud Python Tornado Serverless Component
231 lines (216 loc) • 6.46 kB
JavaScript
$(function() {
if (!EVALEX_TRUSTED) {
initPinBox()
}
/**
* if we are in console mode, show the console.
*/
if (CONSOLE_MODE && EVALEX) {
openShell(null, $('div.console div.inner').empty(), 0)
}
$('div.detail').click(function() {
$('div.traceback')
.get(0)
.scrollIntoView(false)
})
$('div.traceback div.frame').each(function() {
var target = $('pre', this),
consoleNode = null,
frameID = this.id.substring(6)
target.click(function() {
$(this)
.parent()
.toggleClass('expanded')
})
/**
* Add an interactive console to the frames
*/
if (EVALEX && target.is('.current')) {
$('<img src="?__debugger__=yes&cmd=resource&f=console.png">')
.attr('title', 'Open an interactive python shell in this frame')
.click(function() {
consoleNode = openShell(consoleNode, target, frameID)
return false
})
.prependTo(target)
}
})
/**
* toggle traceback types on click.
*/
$('h2.traceback')
.click(function() {
$(this)
.next()
.slideToggle('fast')
$('div.plain').slideToggle('fast')
})
.css('cursor', 'pointer')
$('div.plain').hide()
/**
* Add extra info (this is here so that only users with JavaScript
* enabled see it.)
*/
$('span.nojavascript')
.removeClass('nojavascript')
.html(
'<p>To switch between the interactive traceback and the plaintext ' +
'one, you can click on the "Traceback" headline. From the text ' +
'traceback you can also create a paste of it. ' +
(!EVALEX
? ''
: 'For code execution mouse-over the frame you want to debug and ' +
'click on the console icon on the right side.' +
'<p>You can execute arbitrary Python code in the stack frames and ' +
'there are some extra helpers available for introspection:' +
'<ul><li><code>dump()</code> shows all variables in the frame' +
"<li><code>dump(obj)</code> dumps all that's known about the object</ul>")
)
/**
* Add the pastebin feature
*/
$('div.plain form').submit(function() {
var label = $('input[type="submit"]', this)
var old_val = label.val()
label.val('submitting...')
$.ajax({
dataType: 'json',
url: document.location.pathname,
data: { __debugger__: 'yes', tb: TRACEBACK, cmd: 'paste', s: SECRET },
success: function(data) {
$('div.plain span.pastemessage')
.removeClass('pastemessage')
.text('Paste created: ')
.append($('<a>#' + data.id + '</a>').attr('href', data.url))
},
error: function() {
alert('Error: Could not submit paste. No network connection?')
label.val(old_val)
}
})
return false
})
// if we have javascript we submit by ajax anyways, so no need for the
// not scaling textarea.
var plainTraceback = $('div.plain textarea')
plainTraceback.replaceWith($('<pre>').text(plainTraceback.text()))
})
function initPinBox() {
$('.pin-prompt form').submit(function(evt) {
evt.preventDefault()
var pin = this.pin.value
var btn = this.btn
btn.disabled = true
$.ajax({
dataType: 'json',
url: document.location.pathname,
data: { __debugger__: 'yes', cmd: 'pinauth', pin: pin, s: SECRET },
success: function(data) {
btn.disabled = false
if (data.auth) {
EVALEX_TRUSTED = true
$('.pin-prompt').fadeOut()
} else {
if (data.exhausted) {
alert('Error: too many attempts. Restart server to retry.')
} else {
alert('Error: incorrect pin')
}
}
console.log(data)
},
error: function() {
btn.disabled = false
alert('Error: Could not verify PIN. Network error?')
}
})
})
}
function promptForPin() {
if (!EVALEX_TRUSTED) {
$.ajax({
url: document.location.pathname,
data: { __debugger__: 'yes', cmd: 'printpin', s: SECRET }
})
$('.pin-prompt').fadeIn(function() {
$('.pin-prompt input[name="pin"]').focus()
})
}
}
/**
* Helper function for shell initialization
*/
function openShell(consoleNode, target, frameID) {
promptForPin()
if (consoleNode) {
return consoleNode.slideToggle('fast')
}
consoleNode = $('<pre class="console">')
.appendTo(target.parent())
.hide()
var historyPos = 0,
history = ['']
var output = $('<div class="output">[console ready]</div>').appendTo(consoleNode)
var form = $('<form>>>> </form>')
.submit(function() {
var cmd = command.val()
$.get(
'',
{
__debugger__: 'yes',
cmd: cmd,
frm: frameID,
s: SECRET
},
function(data) {
var tmp = $('<div>').html(data)
$('span.extended', tmp).each(function() {
var hidden = $(this)
.wrap('<span>')
.hide()
hidden.parent().append(
$('<a href="#" class="toggle"> </a>').click(function() {
hidden.toggle()
$(this).toggleClass('open')
return false
})
)
})
output.append(tmp)
command.focus()
consoleNode.scrollTop(consoleNode.get(0).scrollHeight)
var old = history.pop()
history.push(cmd)
if (typeof old != 'undefined') {
history.push(old)
}
historyPos = history.length - 1
}
)
command.val('')
return false
})
.appendTo(consoleNode)
var command = $(
'<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">'
)
.appendTo(form)
.keydown(function(e) {
if (e.key == 'l' && e.ctrlKey) {
output.text('--- screen cleared ---')
return false
} else if (e.charCode == 0 && (e.keyCode == 38 || e.keyCode == 40)) {
// handle up arrow and down arrow
if (e.keyCode == 38 && historyPos > 0) {
historyPos--
} else if (e.keyCode == 40 && historyPos < history.length) {
historyPos++
}
command.val(history[historyPos])
return false
}
})
return consoleNode.slideDown('fast', function() {
command.focus()
})
}