diff options
author | Solly Ross <sross@redhat.com> | 2017-03-01 21:10:09 -0500 |
---|---|---|
committer | Solly Ross <sross@redhat.com> | 2017-03-07 11:11:29 -0500 |
commit | 3af44ff67f89621886935fb5d151181900b8c751 (patch) | |
tree | 31977376bd9f8677efb4b9719c48dcad7f22dd64 | |
parent | 38a57e4d79288dd9f1f2fba4585e9a2d362f73c3 (diff) | |
download | novnc-refactor/es6-module-loader.tar.gz |
Make vnc_playback.html functional once morerefactor/es6-module-loader
This commit makes vnc_playback.html functional once more, and completely
refactors tests/playback.js to make it usable in other scenarios.
In order for vnc_playback.js to properly load playback files now, they
must `export` their variables.
-rw-r--r-- | tests/playback-ui.js | 174 | ||||
-rw-r--r-- | tests/playback.js | 279 | ||||
-rw-r--r-- | tests/vnc_playback.html | 100 | ||||
-rw-r--r-- | vendor/browser-es-module-loader/dist/browser-es-module-loader.js | 8 | ||||
-rw-r--r-- | vendor/browser-es-module-loader/src/browser-es-module-loader.js | 8 |
5 files changed, 330 insertions, 239 deletions
diff --git a/tests/playback-ui.js b/tests/playback-ui.js new file mode 100644 index 0000000..f47b9d8 --- /dev/null +++ b/tests/playback-ui.js @@ -0,0 +1,174 @@ +import * as WebUtil from '../app/webutil.js'; +import RecordingPlayer from './playback.js'; + +var frames = null; +var encoding = null; + +function message(str) { + console.log(str); + var cell = document.getElementById('messages'); + cell.textContent += str + "\n"; + cell.scrollTop = cell.scrollHeight; +} + +function loadFile() { + const fname = WebUtil.getQueryVar('data', null); + + if (!fname) { + return Promise.reject("Must specify data=FOO in query string."); + } + + message("Loading " + fname); + return import(`../recordings/${fname}#nocache`); +} + +function enableUI(recording) { + var iterations = WebUtil.getQueryVar('iterations', 3); + document.getElementById('iterations').value = iterations; + + var mode = WebUtil.getQueryVar('mode', 3); + if (mode === 'realtime') { + document.getElementById('mode2').checked = true; + } else { + document.getElementById('mode1').checked = true; + } + + message("VNC_frame_data.length: " + recording.VNC_frame_data.length); + + const startButton = document.getElementById('startButton'); + startButton.disabled = false + startButton.addEventListener('click', start); + + frames = recording.VNC_frame_data; + encoding = recording.VNC_frame_encoding; +} + +const notification = function (rfb, mesg, level, options) { + document.getElementById('VNC_status').textContent = mesg; +} + +function IterationPlayer (iterations, frames, encoding) { + this._iterations = iterations; + + this._iteration = undefined; + this._player = undefined; + + this._start_time = undefined; + + this._frames = frames; + this._encoding = encoding; + + this._state = 'running'; + + this.onfinish = function() {}; + this.oniterationfinish = function() {}; + this.rfbdisconnected = function() {}; + this.rfbnotification = function() {}; +} + +IterationPlayer.prototype = { + start: function (mode) { + this._iteration = 0; + this._start_time = (new Date()).getTime(); + + this._realtime = mode.startsWith('realtime'); + this._trafficMgmt = !mode.endsWith('-no-mgmt'); + + this._nextIteration(); + }, + + _nextIteration: function () { + const player = new RecordingPlayer(this._frames, this._encoding, this._disconnected.bind(this), this._notification.bind(this)); + player.onfinish = this._iterationFinish.bind(this); + + if (this._state !== 'running') { return; } + + this._iteration++; + if (this._iteration > this._iterations) { + this._finish(); + return; + } + + player.run(this._realtime, this._trafficMgmt); + }, + + _finish: function () { + const endTime = (new Date()).getTime(); + const totalDuration = endTime - this._start_time; + + const evt = new Event('finish'); + evt.duration = totalDuration; + evt.iterations = this._iterations; + this.onfinish(evt); + }, + + _iterationFinish: function (duration) { + const evt = new Event('iterationfinish'); + evt.duration = duration; + evt.number = this._iteration; + this.oniterationfinish(evt); + + this._nextIteration(); + }, + + _disconnected: function (rfb, reason, frame) { + if (reason) { + this._state = 'failed'; + } + + var evt = new Event('rfbdisconnected'); + evt.reason = reason; + evt.frame = frame; + + this.onrfbdisconnected(evt); + }, + + _notification: function (rfb, msg, level, options) { + var evt = new Event('rfbnotification'); + evt.message = msg; + evt.level = level; + evt.options = options; + + this.onrfbnotification(evt); + }, +}; + +function start() { + document.getElementById('startButton').value = "Running"; + document.getElementById('startButton').disabled = true; + + const iterations = document.getElementById('iterations').value; + + var mode; + + if (document.getElementById('mode1').checked) { + message(`Starting performance playback (fullspeed) [${iterations} iteration(s)]`); + mode = 'perftest'; + } else { + message(`Starting realtime playback [${iterations} iteration(s)]`); + mode = 'realtime'; + } + + const player = new IterationPlayer(iterations, frames, encoding); + player.oniterationfinish = function (evt) { + message(`Iteration ${evt.number} took ${evt.duration}ms`); + }; + player.onrfbdisconnected = function (evt) { + if (evt.reason) { + message(`noVNC sent disconnected during iteration ${evt.iteration} frame ${evt.frame}`); + } + }; + player.onrfbnotification = function (evt) { + document.getElementById('VNC_status').textContent = evt.message; + }; + player.onfinish = function (evt) { + const iterTime = parseInt(evt.duration / evt.iterations, 10); + message(`${evt.iterations} iterations took ${evt.duration}ms (average ${iterTime}ms / iteration)`); + + document.getElementById('startButton').disabled = false; + document.getElementById('startButton').value = "Start"; + }; + player.start(mode); +} + +loadFile().then(enableUI).catch(message); diff --git a/tests/playback.js b/tests/playback.js index a25fac4..b39c981 100644 --- a/tests/playback.js +++ b/tests/playback.js @@ -4,29 +4,17 @@ * Licensed under MPL 2.0 (see LICENSE.txt) */ -"use strict"; -/*jslint browser: true, white: false */ -/*global Util, VNC_frame_data, finish */ - -var rfb, mode, test_state, frame_idx, frame_length, - iteration, iterations, istart_time, encoding, - - // Pre-declarations for jslint - send_array, next_iteration, end_iteration, queue_next_packet, - do_packet, enable_test_mode; - -// Override send_array -send_array = function (arr) { - // Stub out send_array -}; +import RFB from '../core/rfb.js'; +import * as Log from '../core/util/logging.js'; +import Base64 from '../core/base64.js'; // Immediate polyfill -if (window.setImmediate === undefined) { +if (setImmediate === undefined) { var _immediateIdCounter = 1; var _immediateFuncs = {}; - window.setImmediate = function (func) { - var index = Util._immediateIdCounter++; + var setImmediate = function (func) { + var index = _immediateIdCounter++; _immediateFuncs[index] = func; window.postMessage("noVNC immediate trigger:" + index, "*"); return index; @@ -56,143 +44,160 @@ if (window.setImmediate === undefined) { window.addEventListener("message", _onMessage); } -enable_test_mode = function () { - rfb._sock.send = send_array; - rfb._sock.close = function () {}; - rfb._sock.flush = function () {}; - rfb._checkEvents = function () {}; - rfb.connect = function (host, port, password, path) { - this._rfb_host = host; - this._rfb_port = port; - this._rfb_password = (password !== undefined) ? password : ""; - this._rfb_path = (path !== undefined) ? path : ""; - this._sock.init('binary', 'ws'); - this._rfb_connection_state = 'connecting'; - this._rfb_init_state = 'ProtocolVersion'; - }; -}; +export default function RecordingPlayer (frames, encoding, disconnected, notification) { + this._frames = frames; + this._encoding = encoding; -next_iteration = function () { - rfb = new RFB({'target': document.getElementById('VNC_canvas'), - 'view_only': true, - 'onDisconnected': disconnected, - 'onNotification': notification}); - enable_test_mode(); + this._disconnected = disconnected; + this._notification = notification; - // Missing in older recordings - if (typeof VNC_frame_encoding === 'undefined') { - var frame = VNC_frame_data[0]; - var start = frame.indexOf('{', 1) + 1; + if (this._encoding === undefined) { + let frame = this._frames[0]; + let start = frame.indexOf('{', 1) + 1; if (frame.slice(start).startsWith('UkZC')) { - encoding = 'base64'; + this._encoding = 'base64'; } else { - encoding = 'binary'; + this._encoding = 'binary'; } - } else { - encoding = VNC_frame_encoding; } - if (iteration === 0) { - frame_length = VNC_frame_data.length; - test_state = 'running'; - } - - if (test_state !== 'running') { return; } - - iteration += 1; - if (iteration > iterations) { - finish(); - return; - } + this._rfb = undefined; + this._frame_length = this._frames.length; - frame_idx = 0; - istart_time = (new Date()).getTime(); - rfb.connect('test', 0, "bogus"); + this._frame_index = 0; + this._start_time = undefined; + this._realtime = true; + this._trafficManagement = true; - queue_next_packet(); + this._running = false; -}; + this.onfinish = function () {}; +} -end_iteration = function () { - if (rfb._display.pending()) { - rfb._display.set_onFlush(function () { - if (rfb._flushing) { - rfb._onFlush(); - } - end_iteration(); - }); - rfb._display.flush(); - } else { - next_iteration(); - } -}; +RecordingPlayer.prototype = { + run: function (realtime, trafficManagement) { + // initialize a new RFB + this._rfb = new RFB({'target': document.getElementById('VNC_canvas'), + 'view_only': true, + 'onDisconnected': this._handleDisconnect.bind(this), + 'onNotification': this._notification}); + this._enablePlaybackMode(); + + // reset the frame index and timer + this._frame_index = 0; + this._start_time = (new Date()).getTime(); + + this._realtime = realtime; + this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement; + + this._running = true; + + // launch the tests + this._rfb.connect('test', 0, 'bogus'); + + this._queueNextPacket(); + }, + + // _enablePlaybackMode mocks out things not required for running playback + _enablePlaybackMode: function () { + this._rfb._sock.send = function (arr) {}; + this._rfb._sock.close = function () {}; + this._rfb._sock.flush = function () {}; + this._rfb._checkEvents = function () {}; + this._rfb.connect = function (host, port, password, path) { + this._rfb_host = host; + this._rfb_port = port; + this._rfb_password = (password !== undefined) ? password : ""; + this._rfb_path = (path !== undefined) ? path : ""; + this._sock.init('binary', 'ws'); + this._rfb_connection_state = 'connecting'; + this._rfb_init_state = 'ProtocolVersion'; + }; + }, + + _queueNextPacket: function () { + if (!this._running) { return; } + + var frame = this._frames[this._frame_index]; + + // skip send frames + while (this._frame_index < this._frame_length && frame.charAt(0) === "}") { + this._frame_index++; + frame = this._frames[this._frame_index]; + } -queue_next_packet = function () { - var frame, foffset, toffset, delay; - if (test_state !== 'running') { return; } + if (frame === 'EOF') { + Log.Debug('Finished, found EOF'); + this._finish(); + return; + } - frame = VNC_frame_data[frame_idx]; - while ((frame_idx < frame_length) && (frame.charAt(0) === "}")) { - //Util.Debug("Send frame " + frame_idx); - frame_idx += 1; - frame = VNC_frame_data[frame_idx]; - } + if (this._frame_index >= this._frame_length) { + Log.Debug('Finished, no more frames'); + this._finish(); + return; + } - if (frame === 'EOF') { - Util.Debug("Finished, found EOF"); - end_iteration(); - return; - } - if (frame_idx >= frame_length) { - Util.Debug("Finished, no more frames"); - end_iteration(); - return; - } + if (this._realtime) { + let foffset = frame.slice(1, frame.indexOf('{', 1)); + let toffset = (new Date()).getTime() - this._start_time; + let delay = foffset - toffset; + if (delay < 1) delay = 1; - if (mode === 'realtime') { - foffset = frame.slice(1, frame.indexOf('{', 1)); - toffset = (new Date()).getTime() - istart_time; - delay = foffset - toffset; - if (delay < 1) { - delay = 1; + setTimeout(this._doPacket.bind(this), delay); + } else { + setImmediate(this._doPacket.bind(this)); + } + }, + + _doPacket: function () { + // Avoid having excessive queue buildup in non-realtime mode + if (!this._trafficManagement && this._rfb._flushing) { + let player = this; + this._rfb.display.set_onFlush(function () { + this._rfb._display.set_onFlush(this._rfb._onFlush.bind(this._rfb)); + this._rfb._onFlush(); + player._doPacket(); + }); + return; } - setTimeout(do_packet, delay); - } else { - window.setImmediate(do_packet); - } -}; - -var bytes_processed = 0; - -do_packet = function () { - // Avoid having an excessive queue buildup - if (rfb._flushing && (mode !== 'realtime')) { - rfb._display.set_onFlush(function () { - rfb._display.set_onFlush(rfb._onFlush.bind(rfb)); - rfb._onFlush(); - do_packet(); - }); - return; - } + const frame = this._frames[this._frame_index]; + var start = frame.indexOf('{', 1) + 1; + if (this._encoding === 'base64') { + var u8 = Base64.decode(frame.slice(start)); + start = 0; + } else { + var u8 = new Uint8Array(frame.length - start); + for (let i = 0; i < frame.length - start; i++) { + u8[i] = frame.charCodeAt(start + i); + } + } - //Util.Debug("Processing frame: " + frame_idx); - var frame = VNC_frame_data[frame_idx], - start = frame.indexOf('{', 1) + 1; - var u8; - if (encoding === 'base64') { - u8 = Base64.decode(frame.slice(start)); - start = 0; - } else { - u8 = new Uint8Array(frame.length - start); - for (var i = 0; i < frame.length - start; i++) { - u8[i] = frame.charCodeAt(start + i); + this._rfb._sock._recv_message({'data': u8}); + this._frame_index++; + + this._queueNextPacket(); + }, + + _finish() { + if (this._rfb._display.pending()) { + var player = this; + this._rfb._display.set_onFlush(function () { + if (player._rfb._flushing) { + player._rfb._onFlush(); + } + player._finish(); + }); + this._rfb._display.flush(); + } else { + this._running = false; + this.onfinish((new Date()).getTime() - this._start_time); } - } - bytes_processed += u8.length; - rfb._sock._recv_message({'data' : u8}); - frame_idx += 1; + }, - queue_next_packet(); + _handleDisconnect(rfb, reason) { + this._running = false; + this._disconnected(rfb, reason, this._frame_index); + } }; - diff --git a/tests/vnc_playback.html b/tests/vnc_playback.html index 65b735e..66f4057 100644 --- a/tests/vnc_playback.html +++ b/tests/vnc_playback.html @@ -2,6 +2,8 @@ <html> <head> <title>VNC Playback</title> + <script src="/vendor/browser-es-module-loader/dist/browser-es-module-loader.js"></script> + <script type="module" src="./playback.js"></script> </head> <body> @@ -9,8 +11,7 @@ Perftest:<input type='radio' id='mode1' name='mode' checked> Realtime:<input type='radio' id='mode2' name='mode'> - <input id='startButton' type='button' value='Start' style='width:100px' - onclick="start();" disabled> + <input id='startButton' type='button' value='Start' style='width:100px' disabled> <br><br> @@ -37,98 +38,5 @@ src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script> --> - <script type="text/javascript"> - var INCLUDE_URI= "../"; - </script> - <script src="../core/util.js"></script> - <script src="../app/webutil.js"></script> - - <script> - var fname, start_time; - - function message(str) { - console.log(str); - var cell = document.getElementById('messages'); - cell.textContent += str + "\n"; - cell.scrollTop = cell.scrollHeight; - } - - fname = WebUtil.getQueryVar('data', null); - if (fname) { - message("Loading " + fname); - // Load supporting scripts - WebUtil.load_scripts({ - 'core': ["base64.js", "websock.js", "des.js", "input/keysym.js", - "input/keysymdef.js", "input/xtscancodes.js", "input/util.js", - "input/devices.js", "display.js", "rfb.js", "inflator.js"], - 'tests': ["playback.js"], - 'recordings': [fname]}); - - } else { - message("Must specify data=FOO in query string."); - } - - disconnected = function (rfb, reason) { - if (reason) { - message("noVNC sent '" + state + "' state during iteration " + iteration + " frame " + frame_idx); - test_state = 'failed'; - } - } - - notification = function (rfb, mesg, level, options) { - document.getElementById('VNC_status').textContent = mesg; - } - - function start() { - document.getElementById('startButton').value = "Running"; - document.getElementById('startButton').disabled = true; - - iterations = document.getElementById('iterations').value; - iteration = 0; - start_time = (new Date()).getTime(); - - if (document.getElementById('mode1').checked) { - message("Starting performance playback (fullspeed) [" + iterations + " iteration(s)]"); - mode = 'perftest'; - } else { - message("Starting realtime playback [" + iterations + " iteration(s)]"); - mode = 'realtime'; - } - - //recv_message = rfb.testMode(send_array, VNC_frame_encoding); - - next_iteration(); - } - - function finish() { - // Finished with all iterations - var total_time, end_time = (new Date()).getTime(); - total_time = end_time - start_time; - - iter_time = parseInt(total_time / iterations, 10); - message(iterations + " iterations took " + total_time + "ms, " + - iter_time + "ms per iteration"); - // Shut-off event interception - rfb.get_mouse().ungrab(); - rfb.get_keyboard().ungrab(); - document.getElementById('startButton').disabled = false; - document.getElementById('startButton').value = "Start"; - - } - - window.onscriptsload = function () { - iterations = WebUtil.getQueryVar('iterations', 3); - document.getElementById('iterations').value = iterations; - mode = WebUtil.getQueryVar('mode', 3); - if (mode === 'realtime') { - document.getElementById('mode2').checked = true; - } else { - document.getElementById('mode1').checked = true; - } - if (fname) { - message("VNC_frame_data.length: " + VNC_frame_data.length); - } - document.getElementById('startButton').disabled = false; - } - </script> + <script type="module" src="./playback-ui.js"> </html> diff --git a/vendor/browser-es-module-loader/dist/browser-es-module-loader.js b/vendor/browser-es-module-loader/dist/browser-es-module-loader.js index 8d3a2ee..f191d1a 100644 --- a/vendor/browser-es-module-loader/dist/browser-es-module-loader.js +++ b/vendor/browser-es-module-loader/dist/browser-es-module-loader.js @@ -1350,7 +1350,7 @@ WorkerPool.prototype = { }; var promiseMap = new Map(); -var babelWorker = new WorkerPool('vendor/browser-es-module-loader/dist/babel-worker.js', 3); +var babelWorker = new WorkerPool('/vendor/browser-es-module-loader/dist/babel-worker.js', 3); babelWorker.onmessage = function (evt) { var promFuncs = promiseMap.get(evt.data.key); promFuncs.resolve(evt.data); @@ -1391,8 +1391,10 @@ BrowserESModuleLoader.prototype[RegisterLoader$1.instantiate] = function(key, pr }).then(function (data) { // evaluate without require, exports and module variables // we leave module in for now to allow module.require access - localStorage.setItem(key+'!raw', data.source); - localStorage.setItem(data.key+'!transpiled', data.code); + if (data.key.slice(-8) !== '#nocache') { + localStorage.setItem(key+'!raw', data.source); + localStorage.setItem(data.key+'!transpiled', data.code); + } (0, eval)(data.code + '\n//# sourceURL=' + data.key + '!transpiled'); processAnonRegister(); }); diff --git a/vendor/browser-es-module-loader/src/browser-es-module-loader.js b/vendor/browser-es-module-loader/src/browser-es-module-loader.js index 6154e44..4b968eb 100644 --- a/vendor/browser-es-module-loader/src/browser-es-module-loader.js +++ b/vendor/browser-es-module-loader/src/browser-es-module-loader.js @@ -190,7 +190,7 @@ WorkerPool.prototype = { }; var promiseMap = new Map(); -var babelWorker = new WorkerPool('vendor/browser-es-module-loader/dist/babel-worker.js', 3); +var babelWorker = new WorkerPool('/vendor/browser-es-module-loader/dist/babel-worker.js', 3); babelWorker.onmessage = function (evt) { var promFuncs = promiseMap.get(evt.data.key); promFuncs.resolve(evt.data); @@ -231,8 +231,10 @@ BrowserESModuleLoader.prototype[RegisterLoader.instantiate] = function(key, proc }).then(function (data) { // evaluate without require, exports and module variables // we leave module in for now to allow module.require access - localStorage.setItem(key+'!raw', data.source); - localStorage.setItem(data.key+'!transpiled', data.code); + if (data.key.slice(-8) !== '#nocache') { + localStorage.setItem(key+'!raw', data.source); + localStorage.setItem(data.key+'!transpiled', data.code); + } (0, eval)(data.code + '\n//# sourceURL=' + data.key + '!transpiled'); processAnonRegister(); }); |