Merge a607c19f45 into 609a3fac74
This commit is contained in:
commit
7112d1b70f
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
},
|
||||
"extends": "eslint:recommended"
|
||||
}
|
||||
|
|
@ -9,14 +9,14 @@
|
|||
// Fallback for all uncought errors
|
||||
function handleError (event, err) {
|
||||
try {
|
||||
var msg = document.getElementById('noVNC_fallback_errormsg');
|
||||
const msg = document.getElementById('noVNC_fallback_errormsg');
|
||||
|
||||
// Only show the initial error
|
||||
if (msg.hasChildNodes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var div = document.createElement("div");
|
||||
let div = document.createElement("div");
|
||||
div.classList.add('noVNC_message');
|
||||
div.appendChild(document.createTextNode(event.message));
|
||||
msg.appendChild(div);
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
if (event.filename) {
|
||||
div = document.createElement("div");
|
||||
div.className = 'noVNC_location';
|
||||
var text = event.filename;
|
||||
let text = event.filename;
|
||||
if (event.lineno !== undefined) {
|
||||
text += ":" + event.lineno;
|
||||
if (event.colno !== undefined) {
|
||||
|
|
@ -51,6 +51,6 @@
|
|||
// from being printed to the browser console.
|
||||
return false;
|
||||
}
|
||||
window.addEventListener('error', function (evt) { handleError(evt, evt.error); });
|
||||
window.addEventListener('unhandledrejection', function (evt) { handleError(evt.reason, evt.reason); });
|
||||
window.addEventListener('error', evt => handleError(evt, evt.error));
|
||||
window.addEventListener('unhandledrejection', evt => handleError(evt.reason, evt.reason));
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
* Localization Utilities
|
||||
*/
|
||||
|
||||
export function Localizer() {
|
||||
export class Localizer{
|
||||
constructor() {
|
||||
// Currently configured language
|
||||
this.language = 'en';
|
||||
|
||||
|
|
@ -18,10 +19,8 @@ export function Localizer() {
|
|||
this.dictionary = undefined;
|
||||
}
|
||||
|
||||
Localizer.prototype = {
|
||||
// Configure suitable language based on user preferences
|
||||
setup: function (supportedLanguages) {
|
||||
var userLanguages;
|
||||
setup(supportedLanguages) {
|
||||
|
||||
this.language = 'en'; // Default: US English
|
||||
|
||||
|
|
@ -29,17 +28,16 @@ Localizer.prototype = {
|
|||
* Navigator.languages only available in Chrome (32+) and FireFox (32+)
|
||||
* Fall back to navigator.language for other browsers
|
||||
*/
|
||||
if (typeof window.navigator.languages == 'object') {
|
||||
userLanguages = window.navigator.languages;
|
||||
} else {
|
||||
userLanguages = [navigator.language || navigator.userLanguage];
|
||||
}
|
||||
|
||||
for (var i = 0;i < userLanguages.length;i++) {
|
||||
var userLang = userLanguages[i];
|
||||
userLang = userLang.toLowerCase();
|
||||
userLang = userLang.replace("_", "-");
|
||||
userLang = userLang.split("-");
|
||||
const userLanguages = (typeof window.navigator.languages == 'object')
|
||||
? window.navigator.languages
|
||||
: [navigator.language || navigator.userLanguage];
|
||||
|
||||
for (let i = 0;i < userLanguages.length;i++) {
|
||||
const userLang = userLanguages[i]
|
||||
.toLowerCase()
|
||||
.replace("_", "-")
|
||||
.split("-");
|
||||
|
||||
// Built-in default?
|
||||
if ((userLang[0] === 'en') &&
|
||||
|
|
@ -48,11 +46,11 @@ Localizer.prototype = {
|
|||
}
|
||||
|
||||
// First pass: perfect match
|
||||
for (var j = 0;j < supportedLanguages.length;j++) {
|
||||
var supLang = supportedLanguages[j];
|
||||
supLang = supLang.toLowerCase();
|
||||
supLang = supLang.replace("_", "-");
|
||||
supLang = supLang.split("-");
|
||||
for (let j = 0;j < supportedLanguages.length;j++) {
|
||||
const supLang = supportedLanguages[j]
|
||||
.toLowerCase()
|
||||
.replace("_", "-")
|
||||
.split("-");
|
||||
|
||||
if (userLang[0] !== supLang[0])
|
||||
continue;
|
||||
|
|
@ -64,11 +62,11 @@ Localizer.prototype = {
|
|||
}
|
||||
|
||||
// Second pass: fallback
|
||||
for (var j = 0;j < supportedLanguages.length;j++) {
|
||||
supLang = supportedLanguages[j];
|
||||
supLang = supLang.toLowerCase();
|
||||
supLang = supLang.replace("_", "-");
|
||||
supLang = supLang.split("-");
|
||||
for (let j = 0; j < supportedLanguages.length; j++) {
|
||||
const supLang = supportedLanguages[j]
|
||||
.toLowerCase()
|
||||
.replace("_", "-")
|
||||
.split("-");
|
||||
|
||||
if (userLang[0] !== supLang[0])
|
||||
continue;
|
||||
|
|
@ -79,36 +77,31 @@ Localizer.prototype = {
|
|||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Retrieve localised text
|
||||
get: function (id) {
|
||||
get(id) {
|
||||
if (typeof this.dictionary !== 'undefined' && this.dictionary[id]) {
|
||||
return this.dictionary[id];
|
||||
} else {
|
||||
return id;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Traverses the DOM and translates relevant fields
|
||||
// See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
|
||||
translateDOM: function () {
|
||||
var self = this;
|
||||
translateDOM() {
|
||||
function process(elem, enabled) {
|
||||
function isAnyOf(searchElement, items) {
|
||||
return items.indexOf(searchElement) !== -1;
|
||||
}
|
||||
|
||||
function translateAttribute(elem, attr) {
|
||||
var str = elem.getAttribute(attr);
|
||||
str = self.get(str);
|
||||
elem.setAttribute(attr, str);
|
||||
elem.setAttribute(attr, this.get(elem.getAttribute(attr)));
|
||||
}
|
||||
|
||||
function translateTextNode(node) {
|
||||
var str = node.data.trim();
|
||||
str = self.get(str);
|
||||
node.data = str;
|
||||
node.data = this.get(node.data.trim());
|
||||
}
|
||||
|
||||
if (elem.hasAttribute("translate")) {
|
||||
|
|
@ -152,19 +145,18 @@ Localizer.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
for (var i = 0;i < elem.childNodes.length;i++) {
|
||||
var node = elem.childNodes[i];
|
||||
elem.childNodes.forEach((node) => {
|
||||
if (node.nodeType === node.ELEMENT_NODE) {
|
||||
process(node, enabled);
|
||||
} else if (node.nodeType === node.TEXT_NODE && enabled) {
|
||||
translateTextNode(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
process(document.body, true);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export var l10n = new Localizer();
|
||||
export let l10n = new Localizer();
|
||||
export default l10n.get.bind(l10n);
|
||||
|
|
|
|||
101
app/webutil.js
101
app/webutil.js
|
|
@ -7,26 +7,21 @@
|
|||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
|
||||
/*jslint bitwise: false, white: false, browser: true, devel: true */
|
||||
/*global Util, window, document */
|
||||
|
||||
import { init_logging as main_init_logging } from '../core/util/logging.js';
|
||||
|
||||
// init log level reading the logging HTTP param
|
||||
export function init_logging (level) {
|
||||
"use strict";
|
||||
if (typeof level !== "undefined") {
|
||||
main_init_logging(level);
|
||||
} else {
|
||||
var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/);
|
||||
const param = document.location.href.match(/logging=([A-Za-z0-9._-]*)/);
|
||||
main_init_logging(param || undefined);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Read a query string variable
|
||||
export function getQueryVar (name, defVal) {
|
||||
"use strict";
|
||||
var re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
|
||||
const re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
|
||||
match = document.location.href.match(re);
|
||||
if (typeof defVal === 'undefined') { defVal = null; }
|
||||
if (match) {
|
||||
|
|
@ -34,12 +29,11 @@ export function getQueryVar (name, defVal) {
|
|||
} else {
|
||||
return defVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Read a hash fragment variable
|
||||
export function getHashVar (name, defVal) {
|
||||
"use strict";
|
||||
var re = new RegExp('.*[&#]' + name + '=([^&]*)'),
|
||||
const re = new RegExp('.*[&#]' + name + '=([^&]*)'),
|
||||
match = document.location.hash.match(re);
|
||||
if (typeof defVal === 'undefined') { defVal = null; }
|
||||
if (match) {
|
||||
|
|
@ -47,18 +41,17 @@ export function getHashVar (name, defVal) {
|
|||
} else {
|
||||
return defVal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Read a variable from the fragment or the query string
|
||||
// Fragment takes precedence
|
||||
export function getConfigVar (name, defVal) {
|
||||
"use strict";
|
||||
var val = getHashVar(name);
|
||||
let val = getHashVar(name);
|
||||
if (val === null) {
|
||||
val = getQueryVar(name, defVal);
|
||||
}
|
||||
return val;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
|
||||
|
|
@ -66,8 +59,7 @@ export function getConfigVar (name, defVal) {
|
|||
|
||||
// No days means only for this browser session
|
||||
export function createCookie (name, value, days) {
|
||||
"use strict";
|
||||
var date, expires;
|
||||
let date, expires;
|
||||
if (days) {
|
||||
date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
|
|
@ -76,46 +68,41 @@ export function createCookie (name, value, days) {
|
|||
expires = "";
|
||||
}
|
||||
|
||||
var secure;
|
||||
if (document.location.protocol === "https:") {
|
||||
secure = "; secure";
|
||||
} else {
|
||||
secure = "";
|
||||
}
|
||||
const secure = (document.location.protocol === "https:")
|
||||
? "; secure"
|
||||
: "";
|
||||
|
||||
document.cookie = name + "=" + value + expires + "; path=/" + secure;
|
||||
};
|
||||
}
|
||||
|
||||
export function readCookie (name, defaultValue) {
|
||||
"use strict";
|
||||
var nameEQ = name + "=",
|
||||
const nameEQ = name + "=",
|
||||
ca = document.cookie.split(';');
|
||||
|
||||
for (var i = 0; i < ca.length; i += 1) {
|
||||
var c = ca[i];
|
||||
for (let i = 0; i < ca.length; i += 1) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) === ' ') { c = c.substring(1, c.length); }
|
||||
if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length, c.length); }
|
||||
}
|
||||
|
||||
return (typeof defaultValue !== 'undefined') ? defaultValue : null;
|
||||
};
|
||||
}
|
||||
|
||||
export function eraseCookie (name) {
|
||||
"use strict";
|
||||
createCookie(name, "", -1);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting handling.
|
||||
*/
|
||||
|
||||
var settings = {};
|
||||
let settings = {};
|
||||
|
||||
export function initSettings (callback /*, ...callbackArgs */) {
|
||||
"use strict";
|
||||
var callbackArgs = Array.prototype.slice.call(arguments, 1);
|
||||
const callbackArgs = Array.prototype.slice.call(arguments, 1);
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
window.chrome.storage.sync.get(function (cfg) {
|
||||
window.chrome.storage.sync.get((cfg) => {
|
||||
settings = cfg;
|
||||
console.log(settings);
|
||||
if (callback) {
|
||||
callback.apply(this, callbackArgs);
|
||||
}
|
||||
|
|
@ -126,11 +113,10 @@ export function initSettings (callback /*, ...callbackArgs */) {
|
|||
callback.apply(this, callbackArgs);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// No days means only for this browser session
|
||||
export function writeSetting (name, value) {
|
||||
"use strict";
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
//console.log("writeSetting:", name, value);
|
||||
if (settings[name] !== value) {
|
||||
|
|
@ -140,11 +126,10 @@ export function writeSetting (name, value) {
|
|||
} else {
|
||||
localStorage.setItem(name, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function readSetting (name, defaultValue) {
|
||||
"use strict";
|
||||
var value;
|
||||
let value;
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
value = settings[name];
|
||||
} else {
|
||||
|
|
@ -158,33 +143,29 @@ export function readSetting (name, defaultValue) {
|
|||
} else {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function eraseSetting (name) {
|
||||
"use strict";
|
||||
if (window.chrome && window.chrome.storage) {
|
||||
window.chrome.storage.sync.remove(name);
|
||||
delete settings[name];
|
||||
} else {
|
||||
localStorage.removeItem(name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function injectParamIfMissing (path, param, value) {
|
||||
// force pretend that we're dealing with a relative path
|
||||
// (assume that we wanted an extra if we pass one in)
|
||||
path = "/" + path;
|
||||
|
||||
var elem = document.createElement('a');
|
||||
const elem = document.createElement('a');
|
||||
elem.href = path;
|
||||
|
||||
var param_eq = encodeURIComponent(param) + "=";
|
||||
var query;
|
||||
if (elem.search) {
|
||||
query = elem.search.slice(1).split('&');
|
||||
} else {
|
||||
query = [];
|
||||
}
|
||||
const param_eq = encodeURIComponent(param) + "=";
|
||||
const query = elem.search
|
||||
? elem.search.slice(1).split('&')
|
||||
: [];
|
||||
|
||||
if (!query.some(function (v) { return v.startsWith(param_eq); })) {
|
||||
query.push(param_eq + encodeURIComponent(value));
|
||||
|
|
@ -195,10 +176,10 @@ export function injectParamIfMissing (path, param, value) {
|
|||
// in the elem.pathname string. Handle that case gracefully.
|
||||
if (elem.pathname.charAt(0) == "/") {
|
||||
return elem.pathname.slice(1) + elem.search + elem.hash;
|
||||
} else {
|
||||
}
|
||||
|
||||
return elem.pathname + elem.search + elem.hash;
|
||||
}
|
||||
};
|
||||
|
||||
// sadly, we can't use the Fetch API until we decide to drop
|
||||
// IE11 support or polyfill promises and fetch in IE11.
|
||||
|
|
@ -206,28 +187,26 @@ export function injectParamIfMissing (path, param, value) {
|
|||
// will receive either an event or an error on failure.
|
||||
export function fetchJSON(path, resolve, reject) {
|
||||
// NB: IE11 doesn't support JSON as a responseType
|
||||
var req = new XMLHttpRequest();
|
||||
const req = new XMLHttpRequest();
|
||||
req.open('GET', path);
|
||||
|
||||
req.onload = function () {
|
||||
req.onload = () => {
|
||||
if (req.status === 200) {
|
||||
try {
|
||||
var resObj = JSON.parse(req.responseText);
|
||||
resolve(JSON.parse(req.responseText));
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(resObj);
|
||||
} else {
|
||||
reject(new Error("XHR got non-200 status while trying to load '" + path + "': " + req.status));
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function (evt) {
|
||||
req.onerror = (evt) => {
|
||||
reject(new Error("XHR encountered an error while trying to load '" + path + "': " + evt.message));
|
||||
};
|
||||
|
||||
req.ontimeout = function (evt) {
|
||||
req.ontimeout = () => {
|
||||
reject(new Error("XHR timed out while trying to load '" + path + "'"));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,50 +4,44 @@
|
|||
|
||||
// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js
|
||||
|
||||
/*jslint white: false */
|
||||
/*global console */
|
||||
import * as Log from './util/logging.js';
|
||||
|
||||
export default {
|
||||
/* Convert data (an array of integers) to a Base64 string. */
|
||||
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
|
||||
base64Pad : '=',
|
||||
|
||||
encode: function (data) {
|
||||
"use strict";
|
||||
var result = '';
|
||||
var toBase64Table = this.toBase64Table;
|
||||
var length = data.length;
|
||||
var lengthpad = (length % 3);
|
||||
encode(data) {
|
||||
let result = '';
|
||||
const length = data.length;
|
||||
const lengthpad = (length % 3);
|
||||
// Convert every three bytes to 4 ascii characters.
|
||||
|
||||
for (var i = 0; i < (length - 2); i += 3) {
|
||||
result += toBase64Table[data[i] >> 2];
|
||||
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
|
||||
result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
|
||||
result += toBase64Table[data[i + 2] & 0x3f];
|
||||
for (let i = 0; i < (length - 2); i += 3) {
|
||||
result += this.toBase64Table[data[i] >> 2];
|
||||
result += this.toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
|
||||
result += this.toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
|
||||
result += this.toBase64Table[data[i + 2] & 0x3f];
|
||||
}
|
||||
|
||||
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
||||
var j = 0;
|
||||
let j = length - lengthpad;
|
||||
if (lengthpad === 2) {
|
||||
j = length - lengthpad;
|
||||
result += toBase64Table[data[j] >> 2];
|
||||
result += toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
|
||||
result += toBase64Table[(data[j + 1] & 0x0f) << 2];
|
||||
result += toBase64Table[64];
|
||||
result += this.toBase64Table[data[j] >> 2];
|
||||
result += this.toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
|
||||
result += this.toBase64Table[(data[j + 1] & 0x0f) << 2];
|
||||
result += this.toBase64Table[64];
|
||||
} else if (lengthpad === 1) {
|
||||
j = length - lengthpad;
|
||||
result += toBase64Table[data[j] >> 2];
|
||||
result += toBase64Table[(data[j] & 0x03) << 4];
|
||||
result += toBase64Table[64];
|
||||
result += toBase64Table[64];
|
||||
result += this.toBase64Table[data[j] >> 2];
|
||||
result += this.toBase64Table[(data[j] & 0x03) << 4];
|
||||
result += this.toBase64Table[64];
|
||||
result += this.toBase64Table[64];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/* Convert Base64 data to a string */
|
||||
/* jshint -W013 */
|
||||
toBinaryTable : [
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
|
|
@ -58,31 +52,25 @@ export default {
|
|||
-1,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,-1, -1,-1,-1,-1
|
||||
],
|
||||
/* jshint +W013 */
|
||||
|
||||
decode: function (data, offset) {
|
||||
"use strict";
|
||||
decode(data, offset) {
|
||||
offset = typeof(offset) !== 'undefined' ? offset : 0;
|
||||
var toBinaryTable = this.toBinaryTable;
|
||||
var base64Pad = this.base64Pad;
|
||||
var result, result_length;
|
||||
var leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
var leftdata = 0; // bits decoded, but yet to be appended
|
||||
var data_length = data.indexOf('=') - offset;
|
||||
let leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
let leftdata = 0; // bits decoded, but yet to be appended
|
||||
let data_length = data.indexOf('=') - offset;
|
||||
|
||||
if (data_length < 0) { data_length = data.length - offset; }
|
||||
|
||||
/* Every four characters is 3 resulting numbers */
|
||||
result_length = (data_length >> 2) * 3 + Math.floor((data_length % 4) / 1.5);
|
||||
result = new Array(result_length);
|
||||
const result_length = (data_length >> 2) * 3 + Math.floor((data_length % 4) / 1.5);
|
||||
const result = new Array(result_length);
|
||||
|
||||
// Convert one by one.
|
||||
for (var idx = 0, i = offset; i < data.length; i++) {
|
||||
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
var padding = (data.charAt(i) === base64Pad);
|
||||
for (let idx = 0, i = offset; i < data.length; i++) {
|
||||
const c = this.toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
// Skip illegal characters and whitespace
|
||||
if (c === -1) {
|
||||
console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
|
||||
Log.Error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +82,7 @@ export default {
|
|||
if (leftbits >= 8) {
|
||||
leftbits -= 8;
|
||||
// Append if not padding.
|
||||
if (!padding) {
|
||||
if (data.charAt(i) !== this.base64Pad) {
|
||||
result[idx++] = (leftdata >> leftbits) & 0xff;
|
||||
}
|
||||
leftdata &= (1 << leftbits) - 1;
|
||||
|
|
@ -103,7 +91,7 @@ export default {
|
|||
|
||||
// If there are any bits left, the base64 string was corrupted
|
||||
if (leftbits) {
|
||||
err = new Error('Corrupted base64 string');
|
||||
const err = new Error('Corrupted base64 string');
|
||||
err.name = 'Base64-Error';
|
||||
throw err;
|
||||
}
|
||||
|
|
|
|||
68
core/des.js
68
core/des.js
|
|
@ -75,89 +75,79 @@
|
|||
* fine Java utilities: http://www.acme.com/java/
|
||||
*/
|
||||
|
||||
/* jslint white: false */
|
||||
|
||||
export default function DES(passwd) {
|
||||
"use strict";
|
||||
|
||||
// Tables, permutations, S-boxes, etc.
|
||||
// jshint -W013
|
||||
var PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
|
||||
const PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
|
||||
25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39,
|
||||
50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ],
|
||||
totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28],
|
||||
z = 0x0, a,b,c,d,e,f, SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8,
|
||||
keys = [];
|
||||
50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ];
|
||||
const totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28];
|
||||
const keys = [];
|
||||
const z = 0x0;
|
||||
let a,b,c,d,e,f;
|
||||
|
||||
// jshint -W015
|
||||
a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e;
|
||||
SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d,
|
||||
const SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d,
|
||||
z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z,
|
||||
a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f,
|
||||
c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d];
|
||||
a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e;
|
||||
SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d,
|
||||
const SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d,
|
||||
a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f,
|
||||
z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z,
|
||||
z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e];
|
||||
a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e;
|
||||
SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f,
|
||||
const SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f,
|
||||
b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z,
|
||||
c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d,
|
||||
b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e];
|
||||
a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e;
|
||||
SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d,
|
||||
const SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d,
|
||||
z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f,
|
||||
b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e,
|
||||
c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e];
|
||||
a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e;
|
||||
SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z,
|
||||
const SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z,
|
||||
a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f,
|
||||
z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e,
|
||||
c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d];
|
||||
a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e;
|
||||
SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f,
|
||||
const SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f,
|
||||
z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z,
|
||||
b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z,
|
||||
a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f];
|
||||
a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e;
|
||||
SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f,
|
||||
const SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f,
|
||||
b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e,
|
||||
b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e,
|
||||
z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d];
|
||||
a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e;
|
||||
SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d,
|
||||
const SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d,
|
||||
c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z,
|
||||
a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f,
|
||||
z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e];
|
||||
// jshint +W013,+W015
|
||||
|
||||
// Set the key.
|
||||
function setKeys(keyBlock) {
|
||||
var i, j, l, m, n, o, pc1m = [], pcr = [], kn = [],
|
||||
raw0, raw1, rawi, KnLi;
|
||||
const pc1m = [], pcr = [], kn = [];
|
||||
let l, m, n;
|
||||
|
||||
for (j = 0, l = 56; j < 56; ++j, l -= 8) {
|
||||
for (let j = 0, l = 56; j < 56; ++j, l -= 8) {
|
||||
l += l < -5 ? 65 : l < -3 ? 31 : l < -1 ? 63 : l === 27 ? 35 : 0; // PC1
|
||||
m = l & 0x7;
|
||||
pc1m[j] = ((keyBlock[l >>> 3] & (1<<m)) !== 0) ? 1: 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
m = i << 1;
|
||||
n = m + 1;
|
||||
kn[m] = kn[n] = 0;
|
||||
for (o = 28; o < 59; o += 28) {
|
||||
for (j = o - 28; j < o; ++j) {
|
||||
for (let o = 28; o < 59; o += 28) {
|
||||
for (let j = o - 28; j < o; ++j) {
|
||||
l = j + totrot[i];
|
||||
if (l < o) {
|
||||
pcr[j] = pc1m[l];
|
||||
} else {
|
||||
pcr[j] = pc1m[l - 28];
|
||||
pcr[j] = (l < o) ? pc1m[l] : pc1m[l - 28];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < 24; ++j) {
|
||||
for (let j = 0; j < 24; ++j) {
|
||||
if (pcr[PC2[j]] !== 0) {
|
||||
kn[m] |= 1 << (23 - j);
|
||||
}
|
||||
|
|
@ -168,9 +158,9 @@ export default function DES(passwd) {
|
|||
}
|
||||
|
||||
// cookey
|
||||
for (i = 0, rawi = 0, KnLi = 0; i < 16; ++i) {
|
||||
raw0 = kn[rawi++];
|
||||
raw1 = kn[rawi++];
|
||||
for (let i = 0, rawi = 0, KnLi = 0; i < 16; ++i) {
|
||||
const raw0 = kn[rawi++];
|
||||
const raw1 = kn[rawi++];
|
||||
keys[KnLi] = (raw0 & 0x00fc0000) << 6;
|
||||
keys[KnLi] |= (raw0 & 0x00000fc0) << 10;
|
||||
keys[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
|
||||
|
|
@ -186,7 +176,8 @@ export default function DES(passwd) {
|
|||
|
||||
// Encrypt 8 bytes of text
|
||||
function enc8(text) {
|
||||
var i = 0, b = text.slice(), fval, keysi = 0,
|
||||
const b = text.slice();
|
||||
let i = 0, fval, keysi = 0,
|
||||
l, r, x; // left, right, accumulator
|
||||
|
||||
// Squash 8 bytes to 2 ints
|
||||
|
|
@ -271,6 +262,5 @@ export default function DES(passwd) {
|
|||
}
|
||||
|
||||
setKeys(passwd); // Setup keys
|
||||
return {'encrypt': encrypt}; // Public interface
|
||||
|
||||
}; // function DES
|
||||
return { encrypt }; // Public interface
|
||||
}
|
||||
|
|
|
|||
355
core/display.js
355
core/display.js
|
|
@ -7,13 +7,19 @@
|
|||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
|
||||
/*jslint browser: true, white: false */
|
||||
/*global Util, Base64, changeCursor */
|
||||
|
||||
import * as Log from './util/logging.js';
|
||||
import Base64 from "./base64.js";
|
||||
|
||||
export default function Display(target) {
|
||||
let SUPPORTS_IMAGEDATA_CONSTRUCTOR = false;
|
||||
try {
|
||||
new ImageData(new Uint8ClampedArray(4), 1, 1);
|
||||
SUPPORTS_IMAGEDATA_CONSTRUCTOR = true;
|
||||
} catch (ex) {
|
||||
// ignore failure
|
||||
}
|
||||
|
||||
export default class Display {
|
||||
constructor(target) {
|
||||
this._drawCtx = null;
|
||||
this._c_forceCanvas = false;
|
||||
|
||||
|
|
@ -70,53 +76,48 @@ export default function Display(target) {
|
|||
}
|
||||
|
||||
this._tile16x16 = this._drawCtx.createImageData(16, 16);
|
||||
Log.Debug("<< Display.constructor");
|
||||
};
|
||||
|
||||
var SUPPORTS_IMAGEDATA_CONSTRUCTOR = false;
|
||||
try {
|
||||
new ImageData(new Uint8ClampedArray(4), 1, 1);
|
||||
SUPPORTS_IMAGEDATA_CONSTRUCTOR = true;
|
||||
} catch (ex) {
|
||||
// ignore failure
|
||||
}
|
||||
|
||||
Display.prototype = {
|
||||
// ===== PROPERTIES =====
|
||||
|
||||
_scale: 1.0,
|
||||
get scale() { return this._scale; },
|
||||
this._scale = 1.0;
|
||||
this._clipViewport = false;
|
||||
this.logo = null;
|
||||
|
||||
Log.Debug("<< Display.constructor");
|
||||
}
|
||||
|
||||
// ===== PROPERTIES =====
|
||||
|
||||
get scale() { return this._scale; }
|
||||
set scale(scale) {
|
||||
this._rescale(scale);
|
||||
},
|
||||
}
|
||||
|
||||
_clipViewport: false,
|
||||
get clipViewport() { return this._clipViewport; },
|
||||
get clipViewport() { return this._clipViewport; }
|
||||
set clipViewport(viewport) {
|
||||
this._clipViewport = viewport;
|
||||
// May need to readjust the viewport dimensions
|
||||
var vp = this._viewportLoc;
|
||||
const vp = this._viewportLoc;
|
||||
this.viewportChangeSize(vp.w, vp.h);
|
||||
this.viewportChangePos(0, 0);
|
||||
},
|
||||
}
|
||||
|
||||
get width() {
|
||||
return this._fb_width;
|
||||
},
|
||||
}
|
||||
get height() {
|
||||
return this._fb_height;
|
||||
},
|
||||
|
||||
logo: null,
|
||||
}
|
||||
|
||||
// ===== EVENT HANDLERS =====
|
||||
|
||||
onflush: function () {}, // A flush request has finished
|
||||
onflush() {} // A flush request has finished
|
||||
|
||||
// ===== PUBLIC METHODS =====
|
||||
|
||||
viewportChangePos: function (deltaX, deltaY) {
|
||||
var vp = this._viewportLoc;
|
||||
viewportChangePos(deltaX, deltaY) {
|
||||
const vp = this._viewportLoc;
|
||||
deltaX = Math.floor(deltaX);
|
||||
deltaY = Math.floor(deltaY);
|
||||
|
||||
|
|
@ -125,8 +126,8 @@ Display.prototype = {
|
|||
deltaY = -vp.h;
|
||||
}
|
||||
|
||||
var vx2 = vp.x + vp.w - 1;
|
||||
var vy2 = vp.y + vp.h - 1;
|
||||
const vx2 = vp.x + vp.w - 1;
|
||||
const vy2 = vp.y + vp.h - 1;
|
||||
|
||||
// Position change
|
||||
|
||||
|
|
@ -155,10 +156,9 @@ Display.prototype = {
|
|||
this._damage(vp.x, vp.y, vp.w, vp.h);
|
||||
|
||||
this.flip();
|
||||
},
|
||||
|
||||
viewportChangeSize: function(width, height) {
|
||||
}
|
||||
|
||||
viewportChangeSize(width, height) {
|
||||
if (!this._clipViewport ||
|
||||
typeof(width) === "undefined" ||
|
||||
typeof(height) === "undefined") {
|
||||
|
|
@ -175,12 +175,12 @@ Display.prototype = {
|
|||
height = this._fb_height;
|
||||
}
|
||||
|
||||
var vp = this._viewportLoc;
|
||||
const vp = this._viewportLoc;
|
||||
if (vp.w !== width || vp.h !== height) {
|
||||
vp.w = width;
|
||||
vp.h = height;
|
||||
|
||||
var canvas = this._target;
|
||||
const canvas = this._target;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
|
|
@ -193,27 +193,27 @@ Display.prototype = {
|
|||
// Update the visible size of the target canvas
|
||||
this._rescale(this._scale);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
absX: function (x) {
|
||||
absX(x) {
|
||||
return x / this._scale + this._viewportLoc.x;
|
||||
},
|
||||
}
|
||||
|
||||
absY: function (y) {
|
||||
absY(y) {
|
||||
return y / this._scale + this._viewportLoc.y;
|
||||
},
|
||||
}
|
||||
|
||||
resize: function (width, height) {
|
||||
resize(width, height) {
|
||||
this._prevDrawStyle = "";
|
||||
|
||||
this._fb_width = width;
|
||||
this._fb_height = height;
|
||||
|
||||
var canvas = this._backbuffer;
|
||||
const canvas = this._backbuffer;
|
||||
if (canvas.width !== width || canvas.height !== height) {
|
||||
|
||||
// We have to save the canvas data since changing the size will clear it
|
||||
var saveImg = null;
|
||||
let saveImg = null;
|
||||
if (canvas.width > 0 && canvas.height > 0) {
|
||||
saveImg = this._drawCtx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
|
@ -232,13 +232,13 @@ Display.prototype = {
|
|||
|
||||
// Readjust the viewport as it may be incorrectly sized
|
||||
// and positioned
|
||||
var vp = this._viewportLoc;
|
||||
const vp = this._viewportLoc;
|
||||
this.viewportChangeSize(vp.w, vp.h);
|
||||
this.viewportChangePos(0, 0);
|
||||
},
|
||||
}
|
||||
|
||||
// Track what parts of the visible canvas that need updating
|
||||
_damage: function(x, y, w, h) {
|
||||
_damage(x, y, w, h) {
|
||||
if (x < this._damageBounds.left) {
|
||||
this._damageBounds.left = x;
|
||||
}
|
||||
|
|
@ -251,25 +251,25 @@ Display.prototype = {
|
|||
if ((y + h) > this._damageBounds.bottom) {
|
||||
this._damageBounds.bottom = y + h;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Update the visible canvas with the contents of the
|
||||
// rendering canvas
|
||||
flip: function(from_queue) {
|
||||
flip(from_queue) {
|
||||
if (this._renderQ.length !== 0 && !from_queue) {
|
||||
this._renderQ_push({
|
||||
'type': 'flip'
|
||||
});
|
||||
} else {
|
||||
var x, y, vx, vy, w, h;
|
||||
return;
|
||||
}
|
||||
|
||||
x = this._damageBounds.left;
|
||||
y = this._damageBounds.top;
|
||||
w = this._damageBounds.right - x;
|
||||
h = this._damageBounds.bottom - y;
|
||||
let x = this._damageBounds.left;
|
||||
let y = this._damageBounds.top;
|
||||
let w = this._damageBounds.right - x;
|
||||
let h = this._damageBounds.bottom - y;
|
||||
|
||||
vx = x - this._viewportLoc.x;
|
||||
vy = y - this._viewportLoc.y;
|
||||
let vx = x - this._viewportLoc.x;
|
||||
let vy = y - this._viewportLoc.y;
|
||||
|
||||
if (vx < 0) {
|
||||
w += vx;
|
||||
|
|
@ -301,9 +301,8 @@ Display.prototype = {
|
|||
this._damageBounds.left = this._damageBounds.top = 65535;
|
||||
this._damageBounds.right = this._damageBounds.bottom = 0;
|
||||
}
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
clear() {
|
||||
if (this._logo) {
|
||||
this.resize(this._logo.width, this._logo.height);
|
||||
this.imageRect(0, 0, this._logo.type, this._logo.data);
|
||||
|
|
@ -312,21 +311,21 @@ Display.prototype = {
|
|||
this._drawCtx.clearRect(0, 0, this._fb_width, this._fb_height);
|
||||
}
|
||||
this.flip();
|
||||
},
|
||||
}
|
||||
|
||||
pending: function() {
|
||||
pending() {
|
||||
return this._renderQ.length > 0;
|
||||
},
|
||||
}
|
||||
|
||||
flush: function() {
|
||||
flush() {
|
||||
if (this._renderQ.length === 0) {
|
||||
this.onflush();
|
||||
} else {
|
||||
this._flushing = true;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
fillRect: function (x, y, width, height, color, from_queue) {
|
||||
fillRect(x, y, width, height, color, from_queue) {
|
||||
if (this._renderQ.length !== 0 && !from_queue) {
|
||||
this._renderQ_push({
|
||||
'type': 'fill',
|
||||
|
|
@ -341,9 +340,9 @@ Display.prototype = {
|
|||
this._drawCtx.fillRect(x, y, width, height);
|
||||
this._damage(x, y, width, height);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) {
|
||||
copyImage(old_x, old_y, new_x, new_y, w, h, from_queue) {
|
||||
if (this._renderQ.length !== 0 && !from_queue) {
|
||||
this._renderQ_push({
|
||||
'type': 'copy',
|
||||
|
|
@ -372,10 +371,10 @@ Display.prototype = {
|
|||
new_x, new_y, w, h);
|
||||
this._damage(new_x, new_y, w, h);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
imageRect: function(x, y, mime, arr) {
|
||||
var img = new Image();
|
||||
imageRect(x, y, mime, arr) {
|
||||
const img = new Image();
|
||||
img.src = "data: " + mime + ";base64," + Base64.encode(arr);
|
||||
this._renderQ_push({
|
||||
'type': 'img',
|
||||
|
|
@ -383,10 +382,10 @@ Display.prototype = {
|
|||
'x': x,
|
||||
'y': y
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// start updating a tile
|
||||
startTile: function (x, y, width, height, color) {
|
||||
startTile(x, y, width, height, color) {
|
||||
this._tile_x = x;
|
||||
this._tile_y = y;
|
||||
if (width === 16 && height === 16) {
|
||||
|
|
@ -395,53 +394,57 @@ Display.prototype = {
|
|||
this._tile = this._drawCtx.createImageData(width, height);
|
||||
}
|
||||
|
||||
var red = color[2];
|
||||
var green = color[1];
|
||||
var blue = color[0];
|
||||
const red = color[2];
|
||||
const green = color[1];
|
||||
const blue = color[0];
|
||||
|
||||
var data = this._tile.data;
|
||||
for (var i = 0; i < width * height * 4; i += 4) {
|
||||
const data = this._tile.data;
|
||||
for (let i = 0; i < width * height * 4; i += 4) {
|
||||
data[i] = red;
|
||||
data[i + 1] = green;
|
||||
data[i + 2] = blue;
|
||||
data[i + 3] = 255;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// update sub-rectangle of the current tile
|
||||
subTile: function (x, y, w, h, color) {
|
||||
var red = color[2];
|
||||
var green = color[1];
|
||||
var blue = color[0];
|
||||
var xend = x + w;
|
||||
var yend = y + h;
|
||||
subTile(x, y, w, h, color) {
|
||||
const red = color[2];
|
||||
const green = color[1];
|
||||
const blue = color[0];
|
||||
const xend = x + w;
|
||||
const yend = y + h;
|
||||
|
||||
var data = this._tile.data;
|
||||
var width = this._tile.width;
|
||||
for (var j = y; j < yend; j++) {
|
||||
for (var i = x; i < xend; i++) {
|
||||
var p = (i + (j * width)) * 4;
|
||||
const data = this._tile.data;
|
||||
const width = this._tile.width;
|
||||
for (let j = y; j < yend; j++) {
|
||||
for (let i = x; i < xend; i++) {
|
||||
const p = (i + (j * width)) * 4;
|
||||
data[p] = red;
|
||||
data[p + 1] = green;
|
||||
data[p + 2] = blue;
|
||||
data[p + 3] = 255;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// draw the current tile to the screen
|
||||
finishTile: function () {
|
||||
finishTile() {
|
||||
this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y);
|
||||
this._damage(this._tile_x, this._tile_y,
|
||||
this._tile.width, this._tile.height);
|
||||
},
|
||||
}
|
||||
|
||||
blitImage(x, y, width, height, arr, offset, from_queue) {
|
||||
if (this._renderQ.length === 0 || from_queue) {
|
||||
this._bgrxImageData(x, y, width, height, arr, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
blitImage: function (x, y, width, height, arr, offset, from_queue) {
|
||||
if (this._renderQ.length !== 0 && !from_queue) {
|
||||
// NB(directxman12): it's technically more performant here to use preallocated arrays,
|
||||
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
|
||||
// this probably isn't getting called *nearly* as much
|
||||
var new_arr = new Uint8Array(width * height * 4);
|
||||
const new_arr = new Uint8Array(width * height * 4);
|
||||
new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
|
||||
this._renderQ_push({
|
||||
'type': 'blit',
|
||||
|
|
@ -451,17 +454,18 @@ Display.prototype = {
|
|||
'width': width,
|
||||
'height': height,
|
||||
});
|
||||
} else {
|
||||
this._bgrxImageData(x, y, width, height, arr, offset);
|
||||
}
|
||||
},
|
||||
|
||||
blitRgbImage: function (x, y , width, height, arr, offset, from_queue) {
|
||||
if (this._renderQ.length !== 0 && !from_queue) {
|
||||
blitRgbImage(x, y , width, height, arr, offset, from_queue) {
|
||||
if (this._renderQ.length === 0 || from_queue) {
|
||||
this._rgbImageData(x, y, width, height, arr, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
// NB(directxman12): it's technically more performant here to use preallocated arrays,
|
||||
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
|
||||
// this probably isn't getting called *nearly* as much
|
||||
var new_arr = new Uint8Array(width * height * 3);
|
||||
const new_arr = new Uint8Array(width * height * 3);
|
||||
new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
|
||||
this._renderQ_push({
|
||||
'type': 'blitRgb',
|
||||
|
|
@ -471,17 +475,19 @@ Display.prototype = {
|
|||
'width': width,
|
||||
'height': height,
|
||||
});
|
||||
} else {
|
||||
this._rgbImageData(x, y, width, height, arr, offset);
|
||||
}
|
||||
},
|
||||
|
||||
blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) {
|
||||
if (this._renderQ.length !== 0 && !from_queue) {
|
||||
blitRgbxImage(x, y, width, height, arr, offset, from_queue) {
|
||||
if (this._renderQ.length === 0 || from_queue) {
|
||||
this._rgbxImageData(x, y, width, height, arr, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// NB(directxman12): it's technically more performant here to use preallocated arrays,
|
||||
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
|
||||
// this probably isn't getting called *nearly* as much
|
||||
var new_arr = new Uint8Array(width * height * 4);
|
||||
const new_arr = new Uint8Array(width * height * 4);
|
||||
new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
|
||||
this._renderQ_push({
|
||||
'type': 'blitRgbx',
|
||||
|
|
@ -491,75 +497,69 @@ Display.prototype = {
|
|||
'width': width,
|
||||
'height': height,
|
||||
});
|
||||
} else {
|
||||
this._rgbxImageData(x, y, width, height, arr, offset);
|
||||
}
|
||||
},
|
||||
|
||||
drawImage: function (img, x, y) {
|
||||
drawImage(img, x, y) {
|
||||
this._drawCtx.drawImage(img, x, y);
|
||||
this._damage(x, y, img.width, img.height);
|
||||
},
|
||||
|
||||
changeCursor: function (pixels, mask, hotx, hoty, w, h) {
|
||||
Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h);
|
||||
},
|
||||
|
||||
defaultCursor: function () {
|
||||
this._target.style.cursor = "default";
|
||||
},
|
||||
|
||||
disableLocalCursor: function () {
|
||||
this._target.style.cursor = "none";
|
||||
},
|
||||
|
||||
autoscale: function (containerWidth, containerHeight) {
|
||||
var vp = this._viewportLoc;
|
||||
var targetAspectRatio = containerWidth / containerHeight;
|
||||
var fbAspectRatio = vp.w / vp.h;
|
||||
|
||||
var scaleRatio;
|
||||
if (fbAspectRatio >= targetAspectRatio) {
|
||||
scaleRatio = containerWidth / vp.w;
|
||||
} else {
|
||||
scaleRatio = containerHeight / vp.h;
|
||||
}
|
||||
|
||||
changeCursor(pixels, mask, hotx, hoty, w, h) {
|
||||
Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h);
|
||||
}
|
||||
|
||||
defaultCursor() {
|
||||
this._target.style.cursor = "default";
|
||||
}
|
||||
|
||||
disableLocalCursor() {
|
||||
this._target.style.cursor = "none";
|
||||
}
|
||||
|
||||
autoscale(containerWidth, containerHeight) {
|
||||
const vp = this._viewportLoc;
|
||||
const targetAspectRatio = containerWidth / containerHeight;
|
||||
const fbAspectRatio = vp.w / vp.h;
|
||||
|
||||
const scaleRatio = (fbAspectRatio >= targetAspectRatio)
|
||||
? containerWidth / vp.w
|
||||
: containerHeight / vp.h;
|
||||
|
||||
this._rescale(scaleRatio);
|
||||
},
|
||||
}
|
||||
|
||||
// ===== PRIVATE METHODS =====
|
||||
|
||||
_rescale: function (factor) {
|
||||
_rescale(factor) {
|
||||
this._scale = factor;
|
||||
var vp = this._viewportLoc;
|
||||
const vp = this._viewportLoc;
|
||||
|
||||
// NB(directxman12): If you set the width directly, or set the
|
||||
// style width to a number, the canvas is cleared.
|
||||
// However, if you set the style width to a string
|
||||
// ('NNNpx'), the canvas is scaled without clearing.
|
||||
var width = Math.round(factor * vp.w) + 'px';
|
||||
var height = Math.round(factor * vp.h) + 'px';
|
||||
const width = Math.round(factor * vp.w) + 'px';
|
||||
const height = Math.round(factor * vp.h) + 'px';
|
||||
|
||||
if ((this._target.style.width !== width) ||
|
||||
(this._target.style.height !== height)) {
|
||||
this._target.style.width = width;
|
||||
this._target.style.height = height;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_setFillColor: function (color) {
|
||||
var newStyle = 'rgb(' + color[2] + ',' + color[1] + ',' + color[0] + ')';
|
||||
_setFillColor(color) {
|
||||
const newStyle = 'rgb(' + color[2] + ',' + color[1] + ',' + color[0] + ')';
|
||||
if (newStyle !== this._prevDrawStyle) {
|
||||
this._drawCtx.fillStyle = newStyle;
|
||||
this._prevDrawStyle = newStyle;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_rgbImageData: function (x, y, width, height, arr, offset) {
|
||||
var img = this._drawCtx.createImageData(width, height);
|
||||
var data = img.data;
|
||||
for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 3) {
|
||||
_rgbImageData(x, y, width, height, arr, offset) {
|
||||
const img = this._drawCtx.createImageData(width, height);
|
||||
const data = img.data;
|
||||
for (let i = 0, j = offset; i < width * height * 4; i += 4, j += 3) {
|
||||
data[i] = arr[j];
|
||||
data[i + 1] = arr[j + 1];
|
||||
data[i + 2] = arr[j + 2];
|
||||
|
|
@ -567,12 +567,12 @@ Display.prototype = {
|
|||
}
|
||||
this._drawCtx.putImageData(img, x, y);
|
||||
this._damage(x, y, img.width, img.height);
|
||||
},
|
||||
}
|
||||
|
||||
_bgrxImageData: function (x, y, width, height, arr, offset) {
|
||||
var img = this._drawCtx.createImageData(width, height);
|
||||
var data = img.data;
|
||||
for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 4) {
|
||||
_bgrxImageData(x, y, width, height, arr, offset) {
|
||||
const img = this._drawCtx.createImageData(width, height);
|
||||
const data = img.data;
|
||||
for (let i = 0, j = offset; i < width * height * 4; i += 4, j += 4) {
|
||||
data[i] = arr[j + 2];
|
||||
data[i + 1] = arr[j + 1];
|
||||
data[i + 2] = arr[j];
|
||||
|
|
@ -580,11 +580,11 @@ Display.prototype = {
|
|||
}
|
||||
this._drawCtx.putImageData(img, x, y);
|
||||
this._damage(x, y, img.width, img.height);
|
||||
},
|
||||
}
|
||||
|
||||
_rgbxImageData: function (x, y, width, height, arr, offset) {
|
||||
_rgbxImageData(x, y, width, height, arr) {
|
||||
// NB(directxman12): arr must be an Type Array view
|
||||
var img;
|
||||
let img;
|
||||
if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
|
||||
img = new ImageData(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4), width, height);
|
||||
} else {
|
||||
|
|
@ -593,28 +593,28 @@ Display.prototype = {
|
|||
}
|
||||
this._drawCtx.putImageData(img, x, y);
|
||||
this._damage(x, y, img.width, img.height);
|
||||
},
|
||||
}
|
||||
|
||||
_renderQ_push: function (action) {
|
||||
_renderQ_push(action) {
|
||||
this._renderQ.push(action);
|
||||
if (this._renderQ.length === 1) {
|
||||
// If this can be rendered immediately it will be, otherwise
|
||||
// the scanner will wait for the relevant event
|
||||
this._scan_renderQ();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_resume_renderQ: function() {
|
||||
_resume_renderQ() {
|
||||
// "this" is the object that is ready, not the
|
||||
// display object
|
||||
this.removeEventListener('load', this._noVNC_display._resume_renderQ);
|
||||
this._noVNC_display._scan_renderQ();
|
||||
},
|
||||
}
|
||||
|
||||
_scan_renderQ: function () {
|
||||
var ready = true;
|
||||
_scan_renderQ() {
|
||||
let ready = true;
|
||||
while (ready && this._renderQ.length > 0) {
|
||||
var a = this._renderQ[0];
|
||||
const a = this._renderQ[0];
|
||||
switch (a.type) {
|
||||
case 'flip':
|
||||
this.flip(true);
|
||||
|
|
@ -656,22 +656,19 @@ Display.prototype = {
|
|||
this._flushing = false;
|
||||
this.onflush();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Class Methods
|
||||
Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h) {
|
||||
static changeCursor(target, pixels, mask, hotx, hoty, w, h) {
|
||||
if ((w === 0) || (h === 0)) {
|
||||
target.style.cursor = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
var cur = []
|
||||
var y, x;
|
||||
for (y = 0; y < h; y++) {
|
||||
for (x = 0; x < w; x++) {
|
||||
var idx = y * Math.ceil(w / 8) + Math.floor(x / 8);
|
||||
var alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
|
||||
const cur = [];
|
||||
for (let y = 0; y < h; y++) {
|
||||
for (let x = 0; x < w; x++) {
|
||||
let idx = y * Math.ceil(w / 8) + Math.floor(x / 8);
|
||||
const alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
|
||||
idx = ((w * y) + x) * 4;
|
||||
cur.push(pixels[idx + 2]); // red
|
||||
cur.push(pixels[idx + 1]); // green
|
||||
|
|
@ -680,13 +677,13 @@ Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h) {
|
|||
}
|
||||
}
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
|
||||
var img;
|
||||
let img;
|
||||
if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
|
||||
img = new ImageData(new Uint8ClampedArray(cur), w, h);
|
||||
} else {
|
||||
|
|
@ -696,6 +693,8 @@ Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h) {
|
|||
ctx.clearRect(0, 0, w, h);
|
||||
ctx.putImageData(img, 0, 0);
|
||||
|
||||
var url = canvas.toDataURL();
|
||||
const url = canvas.toDataURL();
|
||||
target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default';
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
|
||||
export var encodings = {
|
||||
export let encodings = {
|
||||
encodingRaw: 0,
|
||||
encodingCopyRect: 1,
|
||||
encodingRRE: 2,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
import { inflateInit, inflate, inflateReset } from "../vendor/pako/lib/zlib/inflate.js";
|
||||
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
|
||||
|
||||
Inflate.prototype = {
|
||||
inflate: function (data, flush, expected) {
|
||||
export default class Inflate {
|
||||
constructor() {
|
||||
this.strm = new ZStream();
|
||||
this.chunkSize = 1024 * 10 * 10;
|
||||
this.strm.output = new Uint8Array(this.chunkSize);
|
||||
this.windowBits = 5;
|
||||
|
||||
inflateInit(this.strm, this.windowBits);
|
||||
}
|
||||
|
||||
inflate(data, flush, expected) {
|
||||
this.strm.input = data;
|
||||
this.strm.avail_in = this.strm.input.length;
|
||||
this.strm.next_in = 0;
|
||||
|
|
@ -21,18 +30,9 @@ Inflate.prototype = {
|
|||
inflate(this.strm, flush);
|
||||
|
||||
return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
|
||||
},
|
||||
}
|
||||
|
||||
reset: function () {
|
||||
reset() {
|
||||
inflateReset(this.strm);
|
||||
}
|
||||
};
|
||||
|
||||
export default function Inflate() {
|
||||
this.strm = new ZStream();
|
||||
this.chunkSize = 1024 * 10 * 10;
|
||||
this.strm.output = new Uint8Array(this.chunkSize);
|
||||
this.windowBits = 5;
|
||||
|
||||
inflateInit(this.strm, this.windowBits);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import KeyTable from "./keysym.js";
|
|||
* See https://www.w3.org/TR/uievents-key/ for possible values.
|
||||
*/
|
||||
|
||||
var DOMKeyTable = {};
|
||||
const DOMKeyTable = {};
|
||||
|
||||
function addStandard(key, standard)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,19 +5,18 @@
|
|||
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
|
||||
*/
|
||||
|
||||
/*jslint browser: true, white: false */
|
||||
/*global window, Util */
|
||||
|
||||
import * as Log from '../util/logging.js';
|
||||
import { stopEvent } from '../util/events.js';
|
||||
import * as KeyboardUtil from "./util.js";
|
||||
import KeyTable from "./keysym.js";
|
||||
import * as browserUtils from "../util/browsers.js";
|
||||
|
||||
//
|
||||
// Keyboard event handler
|
||||
//
|
||||
|
||||
export default function Keyboard(target) {
|
||||
export default class Keyboard {
|
||||
constructor(target) {
|
||||
this._target = target || null;
|
||||
|
||||
this._keyDownList = {}; // List of depressed keys
|
||||
|
|
@ -31,35 +30,15 @@ export default function Keyboard(target) {
|
|||
'keypress': this._handleKeyPress.bind(this),
|
||||
'blur': this._allKeysUp.bind(this)
|
||||
};
|
||||
};
|
||||
|
||||
function isMac() {
|
||||
return navigator && !!(/mac/i).exec(navigator.platform);
|
||||
}
|
||||
function isWindows() {
|
||||
return navigator && !!(/win/i).exec(navigator.platform);
|
||||
}
|
||||
function isIOS() {
|
||||
return navigator &&
|
||||
(!!(/ipad/i).exec(navigator.platform) ||
|
||||
!!(/iphone/i).exec(navigator.platform) ||
|
||||
!!(/ipod/i).exec(navigator.platform));
|
||||
}
|
||||
function isIE() {
|
||||
return navigator && !!(/trident/i).exec(navigator.userAgent);
|
||||
}
|
||||
function isEdge() {
|
||||
return navigator && !!(/edge/i).exec(navigator.userAgent);
|
||||
}
|
||||
|
||||
Keyboard.prototype = {
|
||||
// ===== EVENT HANDLERS =====
|
||||
|
||||
onkeyevent: function () {}, // Handler for key press/release
|
||||
onkeyevent() {} // Handler for key press/release
|
||||
|
||||
// ===== PRIVATE METHODS =====
|
||||
|
||||
_sendKeyEvent: function (keysym, code, down) {
|
||||
_sendKeyEvent(keysym, code, down) {
|
||||
Log.Debug("onkeyevent " + (down ? "down" : "up") +
|
||||
", keysym: " + keysym, ", code: " + code);
|
||||
|
||||
|
|
@ -67,8 +46,8 @@ Keyboard.prototype = {
|
|||
// AltGraph, which tends to confuse the hell out of
|
||||
// remote systems. Fake a release of these keys until
|
||||
// there is a way to detect AltGraph properly.
|
||||
var fakeAltGraph = false;
|
||||
if (down && isWindows()) {
|
||||
let fakeAltGraph = false;
|
||||
if (down && browserUtils.isWindows()) {
|
||||
if ((code !== 'ControlLeft') &&
|
||||
(code !== 'AltRight') &&
|
||||
('ControlLeft' in this._keyDownList) &&
|
||||
|
|
@ -89,10 +68,10 @@ Keyboard.prototype = {
|
|||
this.onkeyevent(this._keyDownList['AltRight'],
|
||||
'AltRight', true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getKeyCode: function (e) {
|
||||
var code = KeyboardUtil.getKeycode(e);
|
||||
_getKeyCode(e) {
|
||||
const code = KeyboardUtil.getKeycode(e);
|
||||
if (code !== 'Unidentified') {
|
||||
return code;
|
||||
}
|
||||
|
|
@ -115,26 +94,26 @@ Keyboard.prototype = {
|
|||
return e.keyIdentifier;
|
||||
}
|
||||
|
||||
var codepoint = parseInt(e.keyIdentifier.substr(2), 16);
|
||||
var char = String.fromCharCode(codepoint);
|
||||
const codepoint = parseInt(e.keyIdentifier.substr(2), 16);
|
||||
|
||||
// Some implementations fail to uppercase the symbols
|
||||
char = char.toUpperCase();
|
||||
const char = String.fromCharCode(codepoint).toUpperCase();
|
||||
|
||||
return 'Platform' + char.charCodeAt();
|
||||
}
|
||||
|
||||
return 'Unidentified';
|
||||
},
|
||||
}
|
||||
|
||||
_handleKeyDown: function (e) {
|
||||
var code = this._getKeyCode(e);
|
||||
var keysym = KeyboardUtil.getKeysym(e);
|
||||
_handleKeyDown(e) {
|
||||
let code = this._getKeyCode(e);
|
||||
let keysym = KeyboardUtil.getKeysym(e);
|
||||
|
||||
// We cannot handle keys we cannot track, but we also need
|
||||
// to deal with virtual keyboards which omit key info
|
||||
// (iOS omits tracking info on keyup events, which forces us to
|
||||
// special treat that platform here)
|
||||
if ((code === 'Unidentified') || isIOS()) {
|
||||
if ((code === 'Unidentified') || browserUtils.isIOS()) {
|
||||
if (keysym) {
|
||||
// If it's a virtual keyboard then it should be
|
||||
// sufficient to just send press and release right
|
||||
|
|
@ -151,7 +130,7 @@ Keyboard.prototype = {
|
|||
// keys around a bit to make things more sane for the remote
|
||||
// server. This method is used by RealVNC and TigerVNC (and
|
||||
// possibly others).
|
||||
if (isMac()) {
|
||||
if (browserUtils.isMac()) {
|
||||
switch (keysym) {
|
||||
case KeyTable.XK_Super_L:
|
||||
keysym = KeyTable.XK_Alt_L;
|
||||
|
|
@ -178,7 +157,7 @@ Keyboard.prototype = {
|
|||
// state change events. That gets extra confusing for CapsLock
|
||||
// which toggles on each press, but not on release. So pretend
|
||||
// it was a quick press and release of the button.
|
||||
if (isMac() && (code === 'CapsLock')) {
|
||||
if (browserUtils.isMac() && (code === 'CapsLock')) {
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', true);
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', false);
|
||||
stopEvent(e);
|
||||
|
|
@ -189,7 +168,8 @@ Keyboard.prototype = {
|
|||
// a keypress event as well
|
||||
// (IE and Edge has a broken KeyboardEvent.key, so we can't
|
||||
// just check for the presence of that field)
|
||||
if (!keysym && (!e.key || isIE() || isEdge())) {
|
||||
if (!keysym
|
||||
&& (!e.key || browserUtils.isIE() || browserUtils.isEdge())) {
|
||||
this._pendingKey = code;
|
||||
// However we might not get a keypress event if the key
|
||||
// is non-printable, which needs some special fallback
|
||||
|
|
@ -204,10 +184,10 @@ Keyboard.prototype = {
|
|||
this._keyDownList[code] = keysym;
|
||||
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
},
|
||||
}
|
||||
|
||||
// Legacy event for browsers without code/key
|
||||
_handleKeyPress: function (e) {
|
||||
_handleKeyPress(e) {
|
||||
stopEvent(e);
|
||||
|
||||
// Are we expecting a keypress?
|
||||
|
|
@ -215,8 +195,8 @@ Keyboard.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
var code = this._getKeyCode(e);
|
||||
var keysym = KeyboardUtil.getKeysym(e);
|
||||
let code = this._getKeyCode(e);
|
||||
const keysym = KeyboardUtil.getKeysym(e);
|
||||
|
||||
// The key we were waiting for?
|
||||
if ((code !== 'Unidentified') && (code != this._pendingKey)) {
|
||||
|
|
@ -227,23 +207,24 @@ Keyboard.prototype = {
|
|||
this._pendingKey = null;
|
||||
|
||||
if (!keysym) {
|
||||
console.log('keypress with no keysym:', e);
|
||||
Log.Debug('keypress with no keysym:', e);
|
||||
return;
|
||||
}
|
||||
|
||||
this._keyDownList[code] = keysym;
|
||||
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
},
|
||||
_handleKeyPressTimeout: function (e) {
|
||||
}
|
||||
|
||||
_handleKeyPressTimeout(e) {
|
||||
// Did someone manage to sort out the key already?
|
||||
if (this._pendingKey === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var code, keysym;
|
||||
let keysym;
|
||||
|
||||
code = this._pendingKey;
|
||||
const code = this._pendingKey;
|
||||
this._pendingKey = null;
|
||||
|
||||
// We have no way of knowing the proper keysym with the
|
||||
|
|
@ -254,12 +235,11 @@ Keyboard.prototype = {
|
|||
keysym = e.keyCode;
|
||||
} else if ((e.keyCode >= 0x41) && (e.keyCode <= 0x5a)) {
|
||||
// Character (A-Z)
|
||||
var char = String.fromCharCode(e.keyCode);
|
||||
let char = String.fromCharCode(e.keyCode);
|
||||
// A feeble attempt at the correct case
|
||||
if (e.shiftKey)
|
||||
char = char.toUpperCase();
|
||||
else
|
||||
char = char.toLowerCase();
|
||||
char = e.shiftKey
|
||||
? char.toUpperCase()
|
||||
: char.toLowerCase();
|
||||
keysym = char.charCodeAt();
|
||||
} else {
|
||||
// Unknown, give up
|
||||
|
|
@ -269,15 +249,15 @@ Keyboard.prototype = {
|
|||
this._keyDownList[code] = keysym;
|
||||
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
},
|
||||
}
|
||||
|
||||
_handleKeyUp: function (e) {
|
||||
_handleKeyUp(e) {
|
||||
stopEvent(e);
|
||||
|
||||
var code = this._getKeyCode(e);
|
||||
const code = this._getKeyCode(e);
|
||||
|
||||
// See comment in _handleKeyDown()
|
||||
if (isMac() && (code === 'CapsLock')) {
|
||||
if (browserUtils.isMac() && (code === 'CapsLock')) {
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', true);
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', false);
|
||||
return;
|
||||
|
|
@ -291,22 +271,22 @@ Keyboard.prototype = {
|
|||
this._sendKeyEvent(this._keyDownList[code], code, false);
|
||||
|
||||
delete this._keyDownList[code];
|
||||
},
|
||||
}
|
||||
|
||||
_allKeysUp: function () {
|
||||
_allKeysUp() {
|
||||
Log.Debug(">> Keyboard.allKeysUp");
|
||||
for (var code in this._keyDownList) {
|
||||
for (let code in this._keyDownList) {
|
||||
this._sendKeyEvent(this._keyDownList[code], code, false);
|
||||
};
|
||||
}
|
||||
this._keyDownList = {};
|
||||
Log.Debug("<< Keyboard.allKeysUp");
|
||||
},
|
||||
}
|
||||
|
||||
// ===== PUBLIC METHODS =====
|
||||
|
||||
grab: function () {
|
||||
grab() {
|
||||
//Log.Debug(">> Keyboard.grab");
|
||||
var c = this._target;
|
||||
const c = this._target;
|
||||
|
||||
c.addEventListener('keydown', this._eventHandlers.keydown);
|
||||
c.addEventListener('keyup', this._eventHandlers.keyup);
|
||||
|
|
@ -316,11 +296,11 @@ Keyboard.prototype = {
|
|||
window.addEventListener('blur', this._eventHandlers.blur);
|
||||
|
||||
//Log.Debug("<< Keyboard.grab");
|
||||
},
|
||||
}
|
||||
|
||||
ungrab: function () {
|
||||
ungrab () {
|
||||
//Log.Debug(">> Keyboard.ungrab");
|
||||
var c = this._target;
|
||||
const c = this._target;
|
||||
|
||||
c.removeEventListener('keydown', this._eventHandlers.keydown);
|
||||
c.removeEventListener('keyup', this._eventHandlers.keyup);
|
||||
|
|
@ -331,5 +311,5 @@ Keyboard.prototype = {
|
|||
this._allKeysUp();
|
||||
|
||||
//Log.Debug(">> Keyboard.ungrab");
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
/* Functions at the bottom */
|
||||
|
||||
var codepoints = {
|
||||
const codepoints = {
|
||||
0x0100: 0x03c0, // XK_Amacron
|
||||
0x0101: 0x03e0, // XK_amacron
|
||||
0x0102: 0x01c3, // XK_Abreve
|
||||
|
|
@ -670,14 +670,14 @@ var codepoints = {
|
|||
};
|
||||
|
||||
export default {
|
||||
lookup : function(u) {
|
||||
lookup(u) {
|
||||
// Latin-1 is one-to-one mapping
|
||||
if ((u >= 0x20) && (u <= 0xff)) {
|
||||
return u;
|
||||
}
|
||||
|
||||
// Lookup table (fairly random)
|
||||
var keysym = codepoints[u];
|
||||
const keysym = codepoints[u];
|
||||
if (keysym !== undefined) {
|
||||
return keysym;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,16 @@
|
|||
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
|
||||
*/
|
||||
|
||||
/*jslint browser: true, white: false */
|
||||
/*global window, Util */
|
||||
|
||||
import * as Log from '../util/logging.js';
|
||||
import { isTouchDevice } from '../util/browsers.js';
|
||||
import { setCapture, stopEvent, getPointerEvent } from '../util/events.js';
|
||||
|
||||
var WHEEL_STEP = 10; // Delta threshold for a mouse wheel step
|
||||
var WHEEL_STEP_TIMEOUT = 50; // ms
|
||||
var WHEEL_LINE_HEIGHT = 19;
|
||||
const WHEEL_STEP = 10; // Delta threshold for a mouse wheel step
|
||||
const WHEEL_STEP_TIMEOUT = 50; // ms
|
||||
const WHEEL_LINE_HEIGHT = 19;
|
||||
|
||||
export default function Mouse(target) {
|
||||
export default class Mouse {
|
||||
constructor(target) {
|
||||
this._target = target || document;
|
||||
|
||||
this._doubleClickTimer = null;
|
||||
|
|
@ -35,29 +33,29 @@ export default function Mouse(target) {
|
|||
'mousewheel': this._handleMouseWheel.bind(this),
|
||||
'mousedisable': this._handleMouseDisable.bind(this)
|
||||
};
|
||||
};
|
||||
|
||||
Mouse.prototype = {
|
||||
// ===== PROPERTIES =====
|
||||
|
||||
touchButton: 1, // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
|
||||
this.touchButton = 1; // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
|
||||
|
||||
}
|
||||
|
||||
// ===== EVENT HANDLERS =====
|
||||
|
||||
onmousebutton: function () {}, // Handler for mouse button click/release
|
||||
onmousemove: function () {}, // Handler for mouse movement
|
||||
onmousebutton() {} // Handler for mouse button click/release
|
||||
onmousemove() {} // Handler for mouse movement
|
||||
|
||||
// ===== PRIVATE METHODS =====
|
||||
|
||||
_resetDoubleClickTimer: function () {
|
||||
_resetDoubleClickTimer() {
|
||||
this._doubleClickTimer = null;
|
||||
},
|
||||
}
|
||||
|
||||
_handleMouseButton: function (e, down) {
|
||||
_handleMouseButton(e, down) {
|
||||
this._updateMousePosition(e);
|
||||
var pos = this._pos;
|
||||
let pos = this._pos;
|
||||
|
||||
var bmask;
|
||||
let bmask;
|
||||
if (e.touches || e.changedTouches) {
|
||||
// Touch device
|
||||
|
||||
|
|
@ -73,13 +71,13 @@ Mouse.prototype = {
|
|||
// force the position of the latter touch to the position of
|
||||
// the first.
|
||||
|
||||
var xs = this._lastTouchPos.x - pos.x;
|
||||
var ys = this._lastTouchPos.y - pos.y;
|
||||
var d = Math.sqrt((xs * xs) + (ys * ys));
|
||||
const xs = this._lastTouchPos.x - pos.x;
|
||||
const ys = this._lastTouchPos.y - pos.y;
|
||||
const d = Math.sqrt((xs * xs) + (ys * ys));
|
||||
|
||||
// The goal is to trigger on a certain physical width, the
|
||||
// devicePixelRatio brings us a bit closer but is not optimal.
|
||||
var threshold = 20 * (window.devicePixelRatio || 1);
|
||||
const threshold = 20 * (window.devicePixelRatio || 1);
|
||||
if (d < threshold) {
|
||||
pos = this._lastTouchPos;
|
||||
}
|
||||
|
|
@ -103,25 +101,25 @@ Mouse.prototype = {
|
|||
this.onmousebutton(pos.x, pos.y, down, bmask);
|
||||
|
||||
stopEvent(e);
|
||||
},
|
||||
}
|
||||
|
||||
_handleMouseDown: function (e) {
|
||||
_handleMouseDown(e) {
|
||||
// Touch events have implicit capture
|
||||
if (e.type === "mousedown") {
|
||||
setCapture(this._target);
|
||||
}
|
||||
|
||||
this._handleMouseButton(e, 1);
|
||||
},
|
||||
}
|
||||
|
||||
_handleMouseUp: function (e) {
|
||||
_handleMouseUp(e) {
|
||||
this._handleMouseButton(e, 0);
|
||||
},
|
||||
}
|
||||
|
||||
// Mouse wheel events are sent in steps over VNC. This means that the VNC
|
||||
// protocol can't handle a wheel event with specific distance or speed.
|
||||
// Therefor, if we get a lot of small mouse wheel events we combine them.
|
||||
_generateWheelStepX: function () {
|
||||
_generateWheelStepX() {
|
||||
|
||||
if (this._accumulatedWheelDeltaX < 0) {
|
||||
this.onmousebutton(this._pos.x, this._pos.y, 1, 1 << 5);
|
||||
|
|
@ -132,9 +130,9 @@ Mouse.prototype = {
|
|||
}
|
||||
|
||||
this._accumulatedWheelDeltaX = 0;
|
||||
},
|
||||
}
|
||||
|
||||
_generateWheelStepY: function () {
|
||||
_generateWheelStepY() {
|
||||
|
||||
if (this._accumulatedWheelDeltaY < 0) {
|
||||
this.onmousebutton(this._pos.x, this._pos.y, 1, 1 << 3);
|
||||
|
|
@ -145,22 +143,22 @@ Mouse.prototype = {
|
|||
}
|
||||
|
||||
this._accumulatedWheelDeltaY = 0;
|
||||
},
|
||||
}
|
||||
|
||||
_resetWheelStepTimers: function () {
|
||||
_resetWheelStepTimers() {
|
||||
window.clearTimeout(this._wheelStepXTimer);
|
||||
window.clearTimeout(this._wheelStepYTimer);
|
||||
this._wheelStepXTimer = null;
|
||||
this._wheelStepYTimer = null;
|
||||
},
|
||||
}
|
||||
|
||||
_handleMouseWheel: function (e) {
|
||||
_handleMouseWheel(e) {
|
||||
this._resetWheelStepTimers();
|
||||
|
||||
this._updateMousePosition(e);
|
||||
|
||||
var dX = e.deltaX;
|
||||
var dY = e.deltaY;
|
||||
let dX = e.deltaX;
|
||||
let dY = e.deltaY;
|
||||
|
||||
// Pixel units unless it's non-zero.
|
||||
// Note that if deltamode is line or page won't matter since we aren't
|
||||
|
|
@ -186,6 +184,7 @@ Mouse.prototype = {
|
|||
window.setTimeout(this._generateWheelStepX.bind(this),
|
||||
WHEEL_STEP_TIMEOUT);
|
||||
}
|
||||
|
||||
if (Math.abs(this._accumulatedWheelDeltaY) > WHEEL_STEP) {
|
||||
this._generateWheelStepY();
|
||||
} else {
|
||||
|
|
@ -195,15 +194,15 @@ Mouse.prototype = {
|
|||
}
|
||||
|
||||
stopEvent(e);
|
||||
},
|
||||
}
|
||||
|
||||
_handleMouseMove: function (e) {
|
||||
_handleMouseMove(e) {
|
||||
this._updateMousePosition(e);
|
||||
this.onmousemove(this._pos.x, this._pos.y);
|
||||
stopEvent(e);
|
||||
},
|
||||
}
|
||||
|
||||
_handleMouseDisable: function (e) {
|
||||
_handleMouseDisable(e) {
|
||||
/*
|
||||
* Stop propagation if inside canvas area
|
||||
* Note: This is only needed for the 'click' event as it fails
|
||||
|
|
@ -213,13 +212,13 @@ Mouse.prototype = {
|
|||
if (e.target == this._target) {
|
||||
stopEvent(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Update coordinates relative to target
|
||||
_updateMousePosition: function(e) {
|
||||
_updateMousePosition(e) {
|
||||
e = getPointerEvent(e);
|
||||
var bounds = this._target.getBoundingClientRect();
|
||||
var x, y;
|
||||
const bounds = this._target.getBoundingClientRect();
|
||||
let x, y;
|
||||
// Clip to target bounds
|
||||
if (e.clientX < bounds.left) {
|
||||
x = 0;
|
||||
|
|
@ -235,19 +234,20 @@ Mouse.prototype = {
|
|||
} else {
|
||||
y = e.clientY - bounds.top;
|
||||
}
|
||||
this._pos = {x:x, y:y};
|
||||
},
|
||||
this._pos = { x, y };
|
||||
}
|
||||
|
||||
// ===== PUBLIC METHODS =====
|
||||
|
||||
grab: function () {
|
||||
var c = this._target;
|
||||
grab() {
|
||||
const c = this._target;
|
||||
|
||||
if (isTouchDevice) {
|
||||
c.addEventListener('touchstart', this._eventHandlers.mousedown);
|
||||
c.addEventListener('touchend', this._eventHandlers.mouseup);
|
||||
c.addEventListener('touchmove', this._eventHandlers.mousemove);
|
||||
}
|
||||
|
||||
c.addEventListener('mousedown', this._eventHandlers.mousedown);
|
||||
c.addEventListener('mouseup', this._eventHandlers.mouseup);
|
||||
c.addEventListener('mousemove', this._eventHandlers.mousemove);
|
||||
|
|
@ -259,10 +259,10 @@ Mouse.prototype = {
|
|||
/* preventDefault() on mousedown doesn't stop this event for some
|
||||
reason so we have to explicitly block it */
|
||||
c.addEventListener('contextmenu', this._eventHandlers.mousedisable);
|
||||
},
|
||||
}
|
||||
|
||||
ungrab: function () {
|
||||
var c = this._target;
|
||||
ungrab() {
|
||||
const c = this._target;
|
||||
|
||||
this._resetWheelStepTimers();
|
||||
|
||||
|
|
@ -271,6 +271,7 @@ Mouse.prototype = {
|
|||
c.removeEventListener('touchend', this._eventHandlers.mouseup);
|
||||
c.removeEventListener('touchmove', this._eventHandlers.mousemove);
|
||||
}
|
||||
|
||||
c.removeEventListener('mousedown', this._eventHandlers.mousedown);
|
||||
c.removeEventListener('mouseup', this._eventHandlers.mouseup);
|
||||
c.removeEventListener('mousemove', this._eventHandlers.mousemove);
|
||||
|
|
@ -280,4 +281,4 @@ Mouse.prototype = {
|
|||
|
||||
c.removeEventListener('contextmenu', this._eventHandlers.mousedisable);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,8 @@
|
|||
import KeyTable from "./keysym.js";
|
||||
import keysyms from "./keysymdef.js";
|
||||
import vkeys from "./vkeys.js";
|
||||
import fixedkeys from "./fixedkeys.js";
|
||||
import DOMKeyTable from "./domkeytable.js";
|
||||
|
||||
function isMac() {
|
||||
return navigator && !!(/mac/i).exec(navigator.platform);
|
||||
}
|
||||
function isIE() {
|
||||
return navigator && !!(/trident/i).exec(navigator.userAgent);
|
||||
}
|
||||
function isEdge() {
|
||||
return navigator && !!(/edge/i).exec(navigator.userAgent);
|
||||
}
|
||||
import * as browserUtils from "../util/browsers.js";
|
||||
|
||||
// Get 'KeyboardEvent.code', handling legacy browsers
|
||||
export function getKeycode(evt){
|
||||
|
|
@ -34,10 +24,10 @@ export function getKeycode(evt){
|
|||
// in the 'keyCode' field for non-printable characters. However
|
||||
// Webkit sets it to the same as charCode in 'keypress' events.
|
||||
if ((evt.type !== 'keypress') && (evt.keyCode in vkeys)) {
|
||||
var code = vkeys[evt.keyCode];
|
||||
let code = vkeys[evt.keyCode];
|
||||
|
||||
// macOS has messed up this code for some reason
|
||||
if (isMac() && (code === 'ContextMenu')) {
|
||||
if (browserUtils.isMac() && (code === 'ContextMenu')) {
|
||||
code = 'MetaRight';
|
||||
}
|
||||
|
||||
|
|
@ -114,13 +104,14 @@ export function getKey(evt) {
|
|||
|
||||
// IE and Edge have broken handling of AltGraph so we cannot
|
||||
// trust them for printable characters
|
||||
if ((evt.key.length !== 1) || (!isIE() && !isEdge())) {
|
||||
if ((evt.key.length !== 1)
|
||||
|| (!browserUtils.isIE() && !browserUtils.isEdge())) {
|
||||
return evt.key;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to deduce it based on the physical key
|
||||
var code = getKeycode(evt);
|
||||
let code = getKeycode(evt);
|
||||
if (code in fixedkeys) {
|
||||
return fixedkeys[code];
|
||||
}
|
||||
|
|
@ -136,7 +127,7 @@ export function getKey(evt) {
|
|||
|
||||
// Get the most reliable keysym value we can get from a key event
|
||||
export function getKeysym(evt){
|
||||
var key = getKey(evt);
|
||||
const key = getKey(evt);
|
||||
|
||||
if (key === 'Unidentified') {
|
||||
return null;
|
||||
|
|
@ -144,7 +135,7 @@ export function getKeysym(evt){
|
|||
|
||||
// First look up special keys
|
||||
if (key in DOMKeyTable) {
|
||||
var location = evt.location;
|
||||
let location = evt.location;
|
||||
|
||||
// Safari screws up location for the right cmd key
|
||||
if ((key === 'Meta') && (location === 0)) {
|
||||
|
|
@ -159,15 +150,12 @@ export function getKeysym(evt){
|
|||
}
|
||||
|
||||
// Now we need to look at the Unicode symbol instead
|
||||
|
||||
var codepoint;
|
||||
|
||||
// Special key? (FIXME: Should have been caught earlier)
|
||||
if (key.length !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
codepoint = key.charCodeAt();
|
||||
const codepoint = key.charCodeAt();
|
||||
if (codepoint) {
|
||||
return keysyms.lookup(codepoint);
|
||||
}
|
||||
|
|
|
|||
766
core/rfb.js
766
core/rfb.js
File diff suppressed because it is too large
Load Diff
|
|
@ -8,24 +8,48 @@
|
|||
|
||||
import * as Log from './logging.js';
|
||||
|
||||
export function isMac() {
|
||||
return navigator && !!(/mac/i).exec(navigator.platform);
|
||||
}
|
||||
|
||||
export function isIE() {
|
||||
return navigator && !!(/trident/i).exec(navigator.userAgent);
|
||||
}
|
||||
|
||||
export function isEdge() {
|
||||
return navigator && !!(/edge/i).exec(navigator.userAgent);
|
||||
}
|
||||
|
||||
export function isWindows() {
|
||||
return navigator && !!(/win/i).exec(navigator.platform);
|
||||
}
|
||||
|
||||
export function isIOS() {
|
||||
return navigator &&
|
||||
(!!(/ipad/i).exec(navigator.platform) ||
|
||||
!!(/iphone/i).exec(navigator.platform) ||
|
||||
!!(/ipod/i).exec(navigator.platform));
|
||||
}
|
||||
|
||||
// Touch detection
|
||||
export var isTouchDevice = ('ontouchstart' in document.documentElement) ||
|
||||
export let isTouchDevice = ('ontouchstart' in document.documentElement) ||
|
||||
// requried for Chrome debugger
|
||||
(document.ontouchstart !== undefined) ||
|
||||
// required for MS Surface
|
||||
(navigator.maxTouchPoints > 0) ||
|
||||
(navigator.msMaxTouchPoints > 0);
|
||||
|
||||
window.addEventListener('touchstart', function onFirstTouch() {
|
||||
isTouchDevice = true;
|
||||
window.removeEventListener('touchstart', onFirstTouch, false);
|
||||
}, false);
|
||||
|
||||
var _cursor_uris_supported = null;
|
||||
let _cursor_uris_supported = null;
|
||||
|
||||
export function browserSupportsCursorURIs () {
|
||||
if (_cursor_uris_supported === null) {
|
||||
if (_cursor_uris_supported !== null) {
|
||||
try {
|
||||
var target = document.createElement('canvas');
|
||||
const target = document.createElement('canvas');
|
||||
target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';
|
||||
|
||||
if (target.style.cursor) {
|
||||
|
|
@ -42,4 +66,4 @@ export function browserSupportsCursorURIs () {
|
|||
}
|
||||
|
||||
return _cursor_uris_supported;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,26 +10,24 @@
|
|||
* Cross-browser event and position routines
|
||||
*/
|
||||
|
||||
import * as Log from './logging.js';
|
||||
|
||||
export function getPointerEvent (e) {
|
||||
return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e;
|
||||
};
|
||||
}
|
||||
|
||||
export function stopEvent (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
}
|
||||
|
||||
// Emulate Element.setCapture() when not supported
|
||||
var _captureRecursion = false;
|
||||
var _captureElem = null;
|
||||
let _captureRecursion = false;
|
||||
let _captureElem = null;
|
||||
function _captureProxy(e) {
|
||||
// Recursion protection as we'll see our own event
|
||||
if (_captureRecursion) return;
|
||||
|
||||
// Clone the event as we cannot dispatch an already dispatched event
|
||||
var newEv = new e.constructor(e.type, e);
|
||||
const newEv = new e.constructor(e.type, e);
|
||||
|
||||
_captureRecursion = true;
|
||||
_captureElem.dispatchEvent(newEv);
|
||||
|
|
@ -47,16 +45,17 @@ function _captureProxy(e) {
|
|||
if (e.type === "mouseup") {
|
||||
releaseCapture();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Follow cursor style of target element
|
||||
function _captureElemChanged() {
|
||||
var captureElem = document.getElementById("noVNC_mouse_capture_elem");
|
||||
const captureElem = document.getElementById("noVNC_mouse_capture_elem");
|
||||
captureElem.style.cursor = window.getComputedStyle(_captureElem).cursor;
|
||||
};
|
||||
var _captureObserver = new MutationObserver(_captureElemChanged);
|
||||
}
|
||||
|
||||
var _captureIndex = 0;
|
||||
let _captureObserver = new MutationObserver(_captureElemChanged);
|
||||
|
||||
let _captureIndex = 0;
|
||||
|
||||
export function setCapture (elem) {
|
||||
if (elem.setCapture) {
|
||||
|
|
@ -71,7 +70,7 @@ export function setCapture (elem) {
|
|||
// called multiple times without coordination
|
||||
releaseCapture();
|
||||
|
||||
var captureElem = document.getElementById("noVNC_mouse_capture_elem");
|
||||
let captureElem = document.getElementById("noVNC_mouse_capture_elem");
|
||||
|
||||
if (captureElem === null) {
|
||||
captureElem = document.createElement("div");
|
||||
|
|
@ -107,13 +106,11 @@ export function setCapture (elem) {
|
|||
window.addEventListener('mousemove', _captureProxy);
|
||||
window.addEventListener('mouseup', _captureProxy);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function releaseCapture () {
|
||||
if (document.releaseCapture) {
|
||||
|
||||
document.releaseCapture();
|
||||
|
||||
} else {
|
||||
if (!_captureElem) {
|
||||
return;
|
||||
|
|
@ -121,7 +118,7 @@ export function releaseCapture () {
|
|||
|
||||
// There might be events already queued, so we need to wait for
|
||||
// them to flush. E.g. contextmenu in Microsoft Edge
|
||||
window.setTimeout(function(expected) {
|
||||
window.setTimeout((expected) => {
|
||||
// Only clear it if it's the expected grab (i.e. no one
|
||||
// else has initiated a new grab)
|
||||
if (_captureIndex === expected) {
|
||||
|
|
@ -131,10 +128,10 @@ export function releaseCapture () {
|
|||
|
||||
_captureObserver.disconnect();
|
||||
|
||||
var captureElem = document.getElementById("noVNC_mouse_capture_elem");
|
||||
const captureElem = document.getElementById("noVNC_mouse_capture_elem");
|
||||
captureElem.style.display = "none";
|
||||
|
||||
window.removeEventListener('mousemove', _captureProxy);
|
||||
window.removeEventListener('mouseup', _captureProxy);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@
|
|||
* See README.md for usage and integration instructions.
|
||||
*/
|
||||
|
||||
var EventTargetMixin = {
|
||||
_listeners: null,
|
||||
export default class EventTargetMixin {
|
||||
constructor() {
|
||||
this._listeners = null;
|
||||
}
|
||||
|
||||
addEventListener: function(type, callback) {
|
||||
addEventListener(type, callback) {
|
||||
if (!this._listeners) {
|
||||
this._listeners = new Map();
|
||||
}
|
||||
|
|
@ -17,24 +19,22 @@ var EventTargetMixin = {
|
|||
this._listeners.set(type, new Set());
|
||||
}
|
||||
this._listeners.get(type).add(callback);
|
||||
},
|
||||
}
|
||||
|
||||
removeEventListener: function(type, callback) {
|
||||
removeEventListener(type, callback) {
|
||||
if (!this._listeners || !this._listeners.has(type)) {
|
||||
return;
|
||||
}
|
||||
this._listeners.get(type).delete(callback);
|
||||
},
|
||||
}
|
||||
|
||||
dispatchEvent: function(event) {
|
||||
dispatchEvent(event) {
|
||||
if (!this._listeners || !this._listeners.has(event.type)) {
|
||||
return true;
|
||||
}
|
||||
this._listeners.get(event.type).forEach(function (callback) {
|
||||
this._listeners.get(event.type).forEach((callback) => {
|
||||
callback.call(this, event);
|
||||
}, this);
|
||||
return !event.defaultPrevented;
|
||||
},
|
||||
};
|
||||
|
||||
export default EventTargetMixin;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@
|
|||
* Logging/debug routines
|
||||
*/
|
||||
|
||||
var _log_level = 'warn';
|
||||
let _log_level = 'warn';
|
||||
|
||||
var Debug = function (msg) {};
|
||||
var Info = function (msg) {};
|
||||
var Warn = function (msg) {};
|
||||
var Error = function (msg) {};
|
||||
let Debug = () => {};
|
||||
let Info = () => {};
|
||||
let Warn = () => {};
|
||||
let Error = () => {};
|
||||
|
||||
export function init_logging (level) {
|
||||
if (typeof level === 'undefined') {
|
||||
|
|
@ -24,9 +24,9 @@ export function init_logging (level) {
|
|||
_log_level = level;
|
||||
}
|
||||
|
||||
Debug = Info = Warn = Error = function (msg) {};
|
||||
Debug = Info = Warn = Error = () => {};
|
||||
if (typeof window.console !== "undefined") {
|
||||
/* jshint -W086 */
|
||||
/* eslint-disable no-fallthrough, no-console */
|
||||
switch (level) {
|
||||
case 'debug':
|
||||
Debug = console.debug.bind(window.console);
|
||||
|
|
@ -41,12 +41,14 @@ export function init_logging (level) {
|
|||
default:
|
||||
throw new Error("invalid logging type '" + level + "'");
|
||||
}
|
||||
/* jshint +W086 */
|
||||
/* eslint-enable no-fallthrough, no-console */
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function get_logging () {
|
||||
return _log_level;
|
||||
};
|
||||
}
|
||||
|
||||
export { Debug, Info, Warn, Error };
|
||||
|
||||
// Initialize logging level
|
||||
|
|
|
|||
|
|
@ -10,19 +10,18 @@
|
|||
if (typeof Object.assign != 'function') {
|
||||
// Must be writable: true, enumerable: false, configurable: true
|
||||
Object.defineProperty(Object, "assign", {
|
||||
value: function assign(target, varArgs) { // .length of function is 2
|
||||
'use strict';
|
||||
value(target) { // .length of function is 2
|
||||
if (target == null) { // TypeError if undefined or null
|
||||
throw new TypeError('Cannot convert undefined or null to object');
|
||||
}
|
||||
|
||||
var to = Object(target);
|
||||
const to = Object(target);
|
||||
|
||||
for (var index = 1; index < arguments.length; index++) {
|
||||
var nextSource = arguments[index];
|
||||
for (let index = 1; index < arguments.length; index++) {
|
||||
const nextSource = arguments[index];
|
||||
|
||||
if (nextSource != null) { // Skip over if undefined or null
|
||||
for (var nextKey in nextSource) {
|
||||
for (let nextKey in nextSource) {
|
||||
// Avoid bugs when hasOwnProperty is shadowed
|
||||
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
||||
to[nextKey] = nextSource[nextKey];
|
||||
|
|
@ -38,17 +37,17 @@ if (typeof Object.assign != 'function') {
|
|||
}
|
||||
|
||||
/* CustomEvent constructor (taken from MDN) */
|
||||
(function () {
|
||||
(() => {
|
||||
function CustomEvent( event, params ) {
|
||||
params = params || { bubbles: false, cancelable: false, detail: undefined };
|
||||
var evt = document.createEvent( 'CustomEvent' );
|
||||
const evt = document.createEvent( 'CustomEvent' );
|
||||
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
|
||||
return evt;
|
||||
}
|
||||
|
||||
CustomEvent.prototype = window.Event.prototype;
|
||||
|
||||
if (typeof window.CustomEvent !== "function") {
|
||||
if (typeof window.CustomEvent !== 'function') {
|
||||
window.CustomEvent = CustomEvent;
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -10,6 +10,5 @@
|
|||
* Decode from UTF-8
|
||||
*/
|
||||
export function decodeUTF8 (utf8string) {
|
||||
"use strict";
|
||||
return decodeURIComponent(escape(utf8string));
|
||||
};
|
||||
}
|
||||
|
|
|
|||
221
core/websock.js
221
core/websock.js
|
|
@ -14,12 +14,29 @@
|
|||
|
||||
import * as Log from './util/logging.js';
|
||||
|
||||
/*jslint browser: true, bitwise: true */
|
||||
/*global Util*/
|
||||
// this has performance issues in some versions Chromium, and
|
||||
// doesn't gain a tremendous amount of performance increase in Firefox
|
||||
// at the moment. It may be valuable to turn it on in the future.
|
||||
const ENABLE_COPYWITHIN = false;
|
||||
|
||||
export default function Websock() {
|
||||
"use strict";
|
||||
const MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
|
||||
|
||||
const typedArrayToString = (() => {
|
||||
// This is only for PhantomJS, which doesn't like apply-ing
|
||||
// with Typed Arrays
|
||||
try {
|
||||
const arr = new Uint8Array([1, 2, 3]);
|
||||
String.fromCharCode.apply(null, arr);
|
||||
return (a) => String.fromCharCode.apply(null, a);
|
||||
} catch (ex) {
|
||||
return (a) =>
|
||||
String.fromCharCode.apply(
|
||||
null, Array.prototype.slice.call(a));
|
||||
}
|
||||
})();
|
||||
|
||||
export default class Websock {
|
||||
constructor() {
|
||||
this._websocket = null; // WebSocket object
|
||||
|
||||
this._rQi = 0; // Receive queue index
|
||||
|
|
@ -35,125 +52,105 @@ export default function Websock() {
|
|||
this._sQ = null; // Send queue
|
||||
|
||||
this._eventHandlers = {
|
||||
'message': function () {},
|
||||
'open': function () {},
|
||||
'close': function () {},
|
||||
'error': function () {}
|
||||
};
|
||||
};
|
||||
|
||||
// this has performance issues in some versions Chromium, and
|
||||
// doesn't gain a tremendous amount of performance increase in Firefox
|
||||
// at the moment. It may be valuable to turn it on in the future.
|
||||
var ENABLE_COPYWITHIN = false;
|
||||
|
||||
var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
|
||||
|
||||
var typedArrayToString = (function () {
|
||||
// This is only for PhantomJS, which doesn't like apply-ing
|
||||
// with Typed Arrays
|
||||
try {
|
||||
var arr = new Uint8Array([1, 2, 3]);
|
||||
String.fromCharCode.apply(null, arr);
|
||||
return function (a) { return String.fromCharCode.apply(null, a); };
|
||||
} catch (ex) {
|
||||
return function (a) {
|
||||
return String.fromCharCode.apply(
|
||||
null, Array.prototype.slice.call(a));
|
||||
'message'() {},
|
||||
'open'() {},
|
||||
'close'() {},
|
||||
'error'() {}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
Websock.prototype = {
|
||||
// Getters and Setters
|
||||
get_sQ: function () {
|
||||
get_sQ() {
|
||||
return this._sQ;
|
||||
},
|
||||
}
|
||||
|
||||
get_rQ: function () {
|
||||
get_rQ() {
|
||||
return this._rQ;
|
||||
},
|
||||
}
|
||||
|
||||
get_rQi: function () {
|
||||
get_rQi() {
|
||||
return this._rQi;
|
||||
},
|
||||
}
|
||||
|
||||
set_rQi: function (val) {
|
||||
set_rQi(val) {
|
||||
this._rQi = val;
|
||||
},
|
||||
}
|
||||
|
||||
// Receive Queue
|
||||
rQlen: function () {
|
||||
rQlen() {
|
||||
return this._rQlen - this._rQi;
|
||||
},
|
||||
}
|
||||
|
||||
rQpeek8: function () {
|
||||
rQpeek8() {
|
||||
return this._rQ[this._rQi];
|
||||
},
|
||||
}
|
||||
|
||||
rQshift8: function () {
|
||||
rQshift8() {
|
||||
return this._rQ[this._rQi++];
|
||||
},
|
||||
}
|
||||
|
||||
rQskip8: function () {
|
||||
rQskip8() {
|
||||
this._rQi++;
|
||||
},
|
||||
}
|
||||
|
||||
rQskipBytes: function (num) {
|
||||
rQskipBytes(num) {
|
||||
this._rQi += num;
|
||||
},
|
||||
}
|
||||
|
||||
// TODO(directxman12): test performance with these vs a DataView
|
||||
rQshift16: function () {
|
||||
rQshift16() {
|
||||
return (this._rQ[this._rQi++] << 8) +
|
||||
this._rQ[this._rQi++];
|
||||
},
|
||||
}
|
||||
|
||||
rQshift32: function () {
|
||||
rQshift32() {
|
||||
return (this._rQ[this._rQi++] << 24) +
|
||||
(this._rQ[this._rQi++] << 16) +
|
||||
(this._rQ[this._rQi++] << 8) +
|
||||
this._rQ[this._rQi++];
|
||||
},
|
||||
}
|
||||
|
||||
rQshiftStr: function (len) {
|
||||
rQshiftStr(len) {
|
||||
if (typeof(len) === 'undefined') { len = this.rQlen(); }
|
||||
var arr = new Uint8Array(this._rQ.buffer, this._rQi, len);
|
||||
const arr = new Uint8Array(this._rQ.buffer, this._rQi, len);
|
||||
this._rQi += len;
|
||||
return typedArrayToString(arr);
|
||||
},
|
||||
}
|
||||
|
||||
rQshiftBytes: function (len) {
|
||||
rQshiftBytes(len) {
|
||||
if (typeof(len) === 'undefined') { len = this.rQlen(); }
|
||||
this._rQi += len;
|
||||
return new Uint8Array(this._rQ.buffer, this._rQi - len, len);
|
||||
},
|
||||
}
|
||||
|
||||
rQshiftTo: function (target, len) {
|
||||
rQshiftTo(target, len) {
|
||||
if (len === undefined) { len = this.rQlen(); }
|
||||
// TODO: make this just use set with views when using a ArrayBuffer to store the rQ
|
||||
target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));
|
||||
this._rQi += len;
|
||||
},
|
||||
}
|
||||
|
||||
rQwhole: function () {
|
||||
rQwhole() {
|
||||
return new Uint8Array(this._rQ.buffer, 0, this._rQlen);
|
||||
},
|
||||
}
|
||||
|
||||
rQslice: function (start, end) {
|
||||
rQslice(start, end) {
|
||||
if (end) {
|
||||
return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
|
||||
} else {
|
||||
return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._rQi - start);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
|
||||
// to be available in the receive queue. Return true if we need to
|
||||
// wait (and possibly print a debug message), otherwise false.
|
||||
rQwait: function (msg, num, goback) {
|
||||
var rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
|
||||
if (rQlen < num) {
|
||||
rQwait(msg, num, goback) {
|
||||
const rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
|
||||
if (rQlen >= num) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (goback) {
|
||||
if (this._rQi < goback) {
|
||||
throw new Error("rQwait cannot backup " + goback + " bytes");
|
||||
|
|
@ -162,59 +159,54 @@ Websock.prototype = {
|
|||
}
|
||||
return true; // true means need more data
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Send Queue
|
||||
|
||||
flush: function () {
|
||||
flush() {
|
||||
if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) {
|
||||
this._websocket.send(this._encode_message());
|
||||
this._sQlen = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
send: function (arr) {
|
||||
send(arr) {
|
||||
this._sQ.set(arr, this._sQlen);
|
||||
this._sQlen += arr.length;
|
||||
this.flush();
|
||||
},
|
||||
}
|
||||
|
||||
send_string: function (str) {
|
||||
this.send(str.split('').map(function (chr) {
|
||||
return chr.charCodeAt(0);
|
||||
}));
|
||||
},
|
||||
send_string(str) {
|
||||
this.send(str.split('').map(chr => chr.charCodeAt(0)));
|
||||
}
|
||||
|
||||
// Event Handlers
|
||||
off: function (evt) {
|
||||
this._eventHandlers[evt] = function () {};
|
||||
},
|
||||
off(evt) {
|
||||
this._eventHandlers[evt] = () => {};
|
||||
}
|
||||
|
||||
on: function (evt, handler) {
|
||||
on(evt, handler) {
|
||||
this._eventHandlers[evt] = handler;
|
||||
},
|
||||
}
|
||||
|
||||
_allocate_buffers: function () {
|
||||
_allocate_buffers() {
|
||||
this._rQ = new Uint8Array(this._rQbufferSize);
|
||||
this._sQ = new Uint8Array(this._sQbufferSize);
|
||||
},
|
||||
}
|
||||
|
||||
init: function () {
|
||||
init() {
|
||||
this._allocate_buffers();
|
||||
this._rQi = 0;
|
||||
this._websocket = null;
|
||||
},
|
||||
}
|
||||
|
||||
open: function (uri, protocols) {
|
||||
var ws_schema = uri.match(/^([a-z]+):\/\//)[1];
|
||||
open(uri, protocols) {
|
||||
this.init();
|
||||
|
||||
this._websocket = new WebSocket(uri, protocols);
|
||||
this._websocket.binaryType = 'arraybuffer';
|
||||
|
||||
this._websocket.onmessage = this._recv_message.bind(this);
|
||||
this._websocket.onopen = (function () {
|
||||
this._websocket.onopen = () => {
|
||||
Log.Debug('>> WebSock.onopen');
|
||||
if (this._websocket.protocol) {
|
||||
Log.Info("Server choose sub-protocol: " + this._websocket.protocol);
|
||||
|
|
@ -222,20 +214,20 @@ Websock.prototype = {
|
|||
|
||||
this._eventHandlers.open();
|
||||
Log.Debug("<< WebSock.onopen");
|
||||
}).bind(this);
|
||||
this._websocket.onclose = (function (e) {
|
||||
};
|
||||
this._websocket.onclose = (e) => {
|
||||
Log.Debug(">> WebSock.onclose");
|
||||
this._eventHandlers.close(e);
|
||||
Log.Debug("<< WebSock.onclose");
|
||||
}).bind(this);
|
||||
this._websocket.onerror = (function (e) {
|
||||
};
|
||||
this._websocket.onerror = (e) => {
|
||||
Log.Debug(">> WebSock.onerror: " + e);
|
||||
this._eventHandlers.error(e);
|
||||
Log.Debug("<< WebSock.onerror: " + e);
|
||||
}).bind(this);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
close: function () {
|
||||
close() {
|
||||
if (this._websocket) {
|
||||
if ((this._websocket.readyState === WebSocket.OPEN) ||
|
||||
(this._websocket.readyState === WebSocket.CONNECTING)) {
|
||||
|
|
@ -243,19 +235,19 @@ Websock.prototype = {
|
|||
this._websocket.close();
|
||||
}
|
||||
|
||||
this._websocket.onmessage = function (e) { return; };
|
||||
this._websocket.onmessage = () => {};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// private methods
|
||||
_encode_message: function () {
|
||||
_encode_message() {
|
||||
// Put in a binary arraybuffer
|
||||
// according to the spec, you can send ArrayBufferViews with the send method
|
||||
return new Uint8Array(this._sQ.buffer, 0, this._sQlen);
|
||||
},
|
||||
}
|
||||
|
||||
_expand_compact_rQ: function (min_fit) {
|
||||
var resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
|
||||
_expand_compact_rQ(min_fit) {
|
||||
const resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
|
||||
if (resizeNeeded) {
|
||||
if (!min_fit) {
|
||||
// just double the size if we need to do compaction
|
||||
|
|
@ -270,12 +262,12 @@ Websock.prototype = {
|
|||
if (this._rQbufferSize > MAX_RQ_GROW_SIZE) {
|
||||
this._rQbufferSize = MAX_RQ_GROW_SIZE;
|
||||
if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) {
|
||||
throw new Exception("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
|
||||
throw new Error("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
|
||||
}
|
||||
}
|
||||
|
||||
if (resizeNeeded) {
|
||||
var old_rQbuffer = this._rQ.buffer;
|
||||
const old_rQbuffer = this._rQ.buffer;
|
||||
this._rQmax = this._rQbufferSize / 8;
|
||||
this._rQ = new Uint8Array(this._rQbufferSize);
|
||||
this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi));
|
||||
|
|
@ -289,21 +281,25 @@ Websock.prototype = {
|
|||
|
||||
this._rQlen = this._rQlen - this._rQi;
|
||||
this._rQi = 0;
|
||||
},
|
||||
}
|
||||
|
||||
_decode_message: function (data) {
|
||||
_decode_message(data) {
|
||||
// push arraybuffer values onto the end
|
||||
var u8 = new Uint8Array(data);
|
||||
const u8 = new Uint8Array(data);
|
||||
if (u8.length > this._rQbufferSize - this._rQlen) {
|
||||
this._expand_compact_rQ(u8.length);
|
||||
}
|
||||
this._rQ.set(u8, this._rQlen);
|
||||
this._rQlen += u8.length;
|
||||
},
|
||||
}
|
||||
|
||||
_recv_message: function (e) {
|
||||
_recv_message(e) {
|
||||
this._decode_message(e.data);
|
||||
if (this.rQlen() > 0) {
|
||||
if (this.rQlen() <= 0) {
|
||||
Log.Debug("Ignoring empty message");
|
||||
return;
|
||||
}
|
||||
|
||||
this._eventHandlers.message();
|
||||
// Compact the receive queue
|
||||
if (this._rQlen == this._rQi) {
|
||||
|
|
@ -312,8 +308,5 @@ Websock.prototype = {
|
|||
} else if (this._rQlen > this._rQmax) {
|
||||
this._expand_compact_rQ();
|
||||
}
|
||||
} else {
|
||||
Log.Debug("Ignoring empty message");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ connection to a specified VNC server.
|
|||
|
||||
##### Syntax
|
||||
|
||||
var rfb = new RFB( target, url [, options] );
|
||||
const rfb = new RFB( target, url [, options] );
|
||||
|
||||
###### Parameters
|
||||
|
||||
|
|
|
|||
|
|
@ -4,29 +4,27 @@ module.exports = function(config) {
|
|||
var customLaunchers = {};
|
||||
var browsers = [];
|
||||
var useSauce = false;
|
||||
var transpile = false;
|
||||
|
||||
// use Sauce when running on Travis
|
||||
if (process.env.TRAVIS_JOB_NUMBER) {
|
||||
useSauce = true;
|
||||
transpile = true;
|
||||
}
|
||||
|
||||
if (useSauce && process.env.TEST_BROWSER_NAME && process.env.TEST_BROWSER_NAME != 'PhantomJS') {
|
||||
var names = process.env.TEST_BROWSER_NAME.split(',');
|
||||
var platforms = process.env.TEST_BROWSER_OS.split(',');
|
||||
var versions = [];
|
||||
if (process.env.TEST_BROWSER_VERSION) {
|
||||
versions = process.env.TEST_BROWSER_VERSION.split(',');
|
||||
} else {
|
||||
versions = [null];
|
||||
}
|
||||
var versions = process.env.TEST_BROWSER_VERSION
|
||||
? process.env.TEST_BROWSER_VERSION.split(',')
|
||||
: [null];
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
for (var j = 0; j < platforms.length; j++) {
|
||||
for (var k = 0; k < versions.length; k++) {
|
||||
var launcher_name = 'sl_' + platforms[j].replace(/[^a-zA-Z0-9]/g, '') + '_' + names[i];
|
||||
if (versions[k]) {
|
||||
launcher_name += '_' + versions[k];
|
||||
}
|
||||
var launcher_name = versions[k]
|
||||
? '_' + versions[k]
|
||||
: 'sl_' + platforms[j].replace(/[^a-zA-Z0-9]/g, '') + '_' + names[i];
|
||||
|
||||
customLaunchers[launcher_name] = {
|
||||
base: 'SauceLabs',
|
||||
|
|
@ -101,6 +99,7 @@ module.exports = function(config) {
|
|||
|
||||
babelPreprocessor: {
|
||||
options: {
|
||||
presets: transpile ? ['es2015'] : [],
|
||||
plugins: ['transform-es2015-modules-amd', 'syntax-dynamic-import'],
|
||||
sourceMap: 'inline',
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,7 +7,8 @@
|
|||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "PATH=$PATH:node_modules/karma/bin karma start karma.conf.js",
|
||||
"lint": "eslint app core tests utils",
|
||||
"test": "karma start karma.conf.js",
|
||||
"prepare": "node ./utils/use_require.js --as commonjs --clean"
|
||||
},
|
||||
"repository": {
|
||||
|
|
@ -35,11 +36,13 @@
|
|||
"babel-plugin-transform-es2015-modules-commonjs": "^6.18.0",
|
||||
"babel-plugin-transform-es2015-modules-systemjs": "^6.22.0",
|
||||
"babel-plugin-transform-es2015-modules-umd": "^6.22.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babelify": "^7.3.0",
|
||||
"browserify": "^13.1.0",
|
||||
"chai": "^3.5.0",
|
||||
"commander": "^2.9.0",
|
||||
"es-module-loader": "^2.1.0",
|
||||
"eslint": "^4.16.0",
|
||||
"fs-extra": "^1.0.0",
|
||||
"jsdom": "*",
|
||||
"karma": "^1.3.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"globals": {
|
||||
"chai": true
|
||||
}
|
||||
}
|
||||
|
|
@ -5,23 +5,21 @@ chai.use(sinonChai);
|
|||
// noVNC specific assertions
|
||||
chai.use(function (_chai, utils) {
|
||||
_chai.Assertion.addMethod('displayed', function (target_data) {
|
||||
var obj = this._obj;
|
||||
var ctx = obj._target.getContext('2d');
|
||||
var data_cl = ctx.getImageData(0, 0, obj._target.width, obj._target.height).data;
|
||||
const obj = this._obj;
|
||||
const ctx = obj._target.getContext('2d');
|
||||
const data_cl = ctx.getImageData(0, 0, obj._target.width, obj._target.height).data;
|
||||
// NB(directxman12): PhantomJS 1.x doesn't implement Uint8ClampedArray, so work around that
|
||||
var data = new Uint8Array(data_cl);
|
||||
var len = data_cl.length;
|
||||
const data = new Uint8Array(data_cl);
|
||||
const len = data_cl.length;
|
||||
new chai.Assertion(len).to.be.equal(target_data.length, "unexpected display size");
|
||||
var same = true;
|
||||
for (var i = 0; i < len; i++) {
|
||||
let same = true;
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (data[i] != target_data[i]) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!same) {
|
||||
console.log("expected data: %o, actual data: %o", target_data, data);
|
||||
}
|
||||
|
||||
this.assert(same,
|
||||
"expected #{this} to have displayed the image #{exp}, but instead it displayed #{act}",
|
||||
"expected #{this} not to have displayed the image #{act}",
|
||||
|
|
@ -30,28 +28,26 @@ chai.use(function (_chai, utils) {
|
|||
});
|
||||
|
||||
_chai.Assertion.addMethod('sent', function (target_data) {
|
||||
var obj = this._obj;
|
||||
obj.inspect = function () {
|
||||
var res = { _websocket: obj._websocket, rQi: obj._rQi, _rQ: new Uint8Array(obj._rQ.buffer, 0, obj._rQlen),
|
||||
const obj = this._obj;
|
||||
obj.inspect = () => {
|
||||
const res = { _websocket: obj._websocket, rQi: obj._rQi, _rQ: new Uint8Array(obj._rQ.buffer, 0, obj._rQlen),
|
||||
_sQ: new Uint8Array(obj._sQ.buffer, 0, obj._sQlen) };
|
||||
res.prototype = obj;
|
||||
return res;
|
||||
};
|
||||
var data = obj._websocket._get_sent_data();
|
||||
var same = true;
|
||||
const data = obj._websocket._get_sent_data();
|
||||
let same = true;
|
||||
if (data.length != target_data.length) {
|
||||
same = false;
|
||||
} else {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i] != target_data[i]) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!same) {
|
||||
console.log("expected data: %o, actual data: %o", target_data, data);
|
||||
}
|
||||
|
||||
this.assert(same,
|
||||
"expected #{this} to have sent the data #{exp}, but it actually sent #{act}",
|
||||
"expected #{this} not to have sent the data #{act}",
|
||||
|
|
@ -66,13 +62,11 @@ chai.use(function (_chai, utils) {
|
|||
_chai.Assertion.overwriteMethod('equal', function (_super) {
|
||||
return function assertArrayEqual(target) {
|
||||
if (utils.flag(this, 'array')) {
|
||||
var obj = this._obj;
|
||||
|
||||
var i;
|
||||
var same = true;
|
||||
const obj = this._obj;
|
||||
let same = true;
|
||||
|
||||
if (utils.flag(this, 'deep')) {
|
||||
for (i = 0; i < obj.length; i++) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
if (!utils.eql(obj[i], target[i])) {
|
||||
same = false;
|
||||
break;
|
||||
|
|
@ -84,7 +78,7 @@ chai.use(function (_chai, utils) {
|
|||
"expected #{this} not to have elements deeply equal to #{exp}",
|
||||
Array.prototype.slice.call(target));
|
||||
} else {
|
||||
for (i = 0; i < obj.length; i++) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
if (obj[i] != target[i]) {
|
||||
same = false;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
import Base64 from '../core/base64.js';
|
||||
|
||||
// PhantomJS can't create Event objects directly, so we need to use this
|
||||
function make_event(name, props) {
|
||||
var evt = document.createEvent('Event');
|
||||
const evt = document.createEvent('Event');
|
||||
evt.initEvent(name, true, true);
|
||||
if (props) {
|
||||
for (var prop in props) {
|
||||
for (let prop in props) {
|
||||
evt[prop] = props[prop];
|
||||
}
|
||||
}
|
||||
return evt;
|
||||
}
|
||||
|
||||
export default function FakeWebSocket (uri, protocols) {
|
||||
export default class FakeWebSocket {
|
||||
constructor(uri, protocols) {
|
||||
this.url = uri;
|
||||
this.binaryType = "arraybuffer";
|
||||
this.extensions = "";
|
||||
|
|
@ -27,17 +30,16 @@ export default function FakeWebSocket (uri, protocols) {
|
|||
this.bufferedAmount = 0;
|
||||
|
||||
this.__is_fake = true;
|
||||
};
|
||||
}
|
||||
|
||||
FakeWebSocket.prototype = {
|
||||
close: function (code, reason) {
|
||||
close(code, reason) {
|
||||
this.readyState = FakeWebSocket.CLOSED;
|
||||
if (this.onclose) {
|
||||
this.onclose(make_event("close", { 'code': code, 'reason': reason, 'wasClean': true }));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
send: function (data) {
|
||||
send(data) {
|
||||
if (this.protocol == 'base64') {
|
||||
data = Base64.decode(data);
|
||||
} else {
|
||||
|
|
@ -45,25 +47,25 @@ FakeWebSocket.prototype = {
|
|||
}
|
||||
this._send_queue.set(data, this.bufferedAmount);
|
||||
this.bufferedAmount += data.length;
|
||||
},
|
||||
}
|
||||
|
||||
_get_sent_data: function () {
|
||||
var res = new Uint8Array(this._send_queue.buffer, 0, this.bufferedAmount);
|
||||
_get_sent_data() {
|
||||
const res = new Uint8Array(this._send_queue.buffer, 0, this.bufferedAmount);
|
||||
this.bufferedAmount = 0;
|
||||
return res;
|
||||
},
|
||||
}
|
||||
|
||||
_open: function (data) {
|
||||
_open() {
|
||||
this.readyState = FakeWebSocket.OPEN;
|
||||
if (this.onopen) {
|
||||
this.onopen(make_event('open'));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_receive_data: function (data) {
|
||||
_receive_data(data) {
|
||||
this.onmessage(make_event("message", { 'data': data }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
FakeWebSocket.OPEN = WebSocket.OPEN;
|
||||
FakeWebSocket.CONNECTING = WebSocket.CONNECTING;
|
||||
|
|
@ -72,16 +74,18 @@ FakeWebSocket.CLOSED = WebSocket.CLOSED;
|
|||
|
||||
FakeWebSocket.__is_fake = true;
|
||||
|
||||
FakeWebSocket.replace = function () {
|
||||
FakeWebSocket.replace = () => {
|
||||
if (!WebSocket.__is_fake) {
|
||||
var real_version = WebSocket;
|
||||
const real_version = WebSocket;
|
||||
// eslint-disable-next-line no-global-assign
|
||||
WebSocket = FakeWebSocket;
|
||||
FakeWebSocket.__real_version = real_version;
|
||||
}
|
||||
};
|
||||
|
||||
FakeWebSocket.restore = function () {
|
||||
FakeWebSocket.restore = () => {
|
||||
if (WebSocket.__is_fake) {
|
||||
// eslint-disable-next-line no-global-assign
|
||||
WebSocket = WebSocket.__real_version;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
/* global VNC_frame_data, VNC_frame_encoding */
|
||||
|
||||
import * as WebUtil from '../app/webutil.js';
|
||||
import RecordingPlayer from './playback.js';
|
||||
|
||||
var frames = null;
|
||||
var encoding = null;
|
||||
let frames = null;
|
||||
let encoding = null;
|
||||
|
||||
function message(str) {
|
||||
console.log(str);
|
||||
var cell = document.getElementById('messages');
|
||||
const cell = document.getElementById('messages');
|
||||
cell.textContent += str + "\n";
|
||||
cell.scrollTop = cell.scrollHeight;
|
||||
}
|
||||
|
||||
function loadFile() {
|
||||
const fname = WebUtil.getQueryVar('data', null);
|
||||
const fname = WebUtil.getQueryconst('data', null);
|
||||
|
||||
if (!fname) {
|
||||
return Promise.reject("Must specify data=FOO in query string.");
|
||||
|
|
@ -21,7 +22,7 @@ function loadFile() {
|
|||
message("Loading " + fname);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var script = document.createElement("script");
|
||||
const script = document.createElement("script");
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
document.body.appendChild(script);
|
||||
|
|
@ -30,10 +31,10 @@ function loadFile() {
|
|||
}
|
||||
|
||||
function enableUI() {
|
||||
var iterations = WebUtil.getQueryVar('iterations', 3);
|
||||
const iterations = WebUtil.getQueryconst('iterations', 3);
|
||||
document.getElementById('iterations').value = iterations;
|
||||
|
||||
var mode = WebUtil.getQueryVar('mode', 3);
|
||||
const mode = WebUtil.getQueryconst('mode', 3);
|
||||
if (mode === 'realtime') {
|
||||
document.getElementById('mode2').checked = true;
|
||||
} else {
|
||||
|
|
@ -120,7 +121,7 @@ IterationPlayer.prototype = {
|
|||
this._state = 'failed';
|
||||
}
|
||||
|
||||
var evt = new Event('rfbdisconnected');
|
||||
const evt = new Event('rfbdisconnected');
|
||||
evt.clean = clean;
|
||||
evt.frame = frame;
|
||||
evt.iteration = this._iteration;
|
||||
|
|
@ -135,7 +136,7 @@ function start() {
|
|||
|
||||
const iterations = document.getElementById('iterations').value;
|
||||
|
||||
var mode;
|
||||
let mode;
|
||||
|
||||
if (document.getElementById('mode1').checked) {
|
||||
message(`Starting performance playback (fullspeed) [${iterations} iteration(s)]`);
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ import Base64 from '../core/base64.js';
|
|||
|
||||
// Immediate polyfill
|
||||
if (setImmediate === undefined) {
|
||||
var _immediateIdCounter = 1;
|
||||
var _immediateFuncs = {};
|
||||
let _immediateIdCounter = 1;
|
||||
const _immediateFuncs = {};
|
||||
|
||||
var setImmediate = function (func) {
|
||||
var index = _immediateIdCounter++;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const setImmediate = function (func) {
|
||||
const index = _immediateIdCounter++;
|
||||
_immediateFuncs[index] = func;
|
||||
window.postMessage("noVNC immediate trigger:" + index, "*");
|
||||
return index;
|
||||
|
|
@ -24,15 +25,15 @@ if (setImmediate === undefined) {
|
|||
_immediateFuncs[id];
|
||||
};
|
||||
|
||||
var _onMessage = function (event) {
|
||||
const _onMessage = function (event) {
|
||||
if ((typeof event.data !== "string") ||
|
||||
(event.data.indexOf("noVNC immediate trigger:") !== 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = event.data.slice("noVNC immediate trigger:".length);
|
||||
const index = event.data.slice("noVNC immediate trigger:".length);
|
||||
|
||||
var callback = _immediateFuncs[index];
|
||||
const callback = _immediateFuncs[index];
|
||||
if (callback === undefined) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -70,11 +71,11 @@ export default function RecordingPlayer (frames, encoding, disconnected) {
|
|||
|
||||
this._running = false;
|
||||
|
||||
this.onfinish = function () {};
|
||||
this.onfinish = () => {};
|
||||
}
|
||||
|
||||
RecordingPlayer.prototype = {
|
||||
run: function (realtime, trafficManagement) {
|
||||
run(realtime, trafficManagement) {
|
||||
// initialize a new RFB
|
||||
this._rfb = new RFB(document.getElementById('VNC_screen'), 'wss://test');
|
||||
this._rfb.viewOnly = true;
|
||||
|
|
@ -95,20 +96,20 @@ RecordingPlayer.prototype = {
|
|||
},
|
||||
|
||||
// _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._sock.open = function () {
|
||||
_enablePlaybackMode() {
|
||||
this._rfb._sock.send = () => {};
|
||||
this._rfb._sock.close = () => {};
|
||||
this._rfb._sock.flush = () => {};
|
||||
this._rfb._sock.open = () => {
|
||||
this.init();
|
||||
this._eventHandlers.open();
|
||||
};
|
||||
},
|
||||
|
||||
_queueNextPacket: function () {
|
||||
_queueNextPacket() {
|
||||
if (!this._running) { return; }
|
||||
|
||||
var frame = this._frames[this._frame_index];
|
||||
let frame = this._frames[this._frame_index];
|
||||
|
||||
// skip send frames
|
||||
while (this._frame_index < this._frame_length && frame.charAt(0) === "}") {
|
||||
|
|
@ -140,7 +141,7 @@ RecordingPlayer.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_doPacket: function () {
|
||||
_doPacket() {
|
||||
// Avoid having excessive queue buildup in non-realtime mode
|
||||
if (this._trafficManagement && this._rfb._flushing) {
|
||||
let player = this;
|
||||
|
|
@ -154,12 +155,13 @@ RecordingPlayer.prototype = {
|
|||
}
|
||||
|
||||
const frame = this._frames[this._frame_index];
|
||||
var start = frame.indexOf('{', 1) + 1;
|
||||
let start = frame.indexOf('{', 1) + 1;
|
||||
let u8;
|
||||
if (this._encoding === 'base64') {
|
||||
var u8 = Base64.decode(frame.slice(start));
|
||||
u8 = Base64.decode(frame.slice(start));
|
||||
start = 0;
|
||||
} else {
|
||||
var u8 = new Uint8Array(frame.length - start);
|
||||
u8 = new Uint8Array(frame.length - start);
|
||||
for (let i = 0; i < frame.length - start; i++) {
|
||||
u8[i] = frame.charCodeAt(start + i);
|
||||
}
|
||||
|
|
@ -173,7 +175,7 @@ RecordingPlayer.prototype = {
|
|||
|
||||
_finish() {
|
||||
if (this._rfb._display.pending()) {
|
||||
var player = this;
|
||||
const player = this;
|
||||
this._rfb._display.onflush = function () {
|
||||
if (player._rfb._flushing) {
|
||||
player._rfb._onFlush();
|
||||
|
|
|
|||
|
|
@ -1,29 +1,26 @@
|
|||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
const expect = chai.expect;
|
||||
|
||||
import Base64 from '../core/base64.js';
|
||||
|
||||
describe('Base64 Tools', function() {
|
||||
"use strict";
|
||||
|
||||
var BIN_ARR = new Array(256);
|
||||
for (var i = 0; i < 256; i++) {
|
||||
const BIN_ARR = new Array(256);
|
||||
for (let i = 0; i < 256; i++) {
|
||||
BIN_ARR[i] = i;
|
||||
}
|
||||
|
||||
var B64_STR = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
|
||||
const B64_STR = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
|
||||
|
||||
|
||||
describe('encode', function() {
|
||||
it('should encode a binary string into Base64', function() {
|
||||
var encoded = Base64.encode(BIN_ARR);
|
||||
const encoded = Base64.encode(BIN_ARR);
|
||||
expect(encoded).to.equal(B64_STR);
|
||||
});
|
||||
});
|
||||
|
||||
describe('decode', function() {
|
||||
it('should decode a Base64 string into a normal string', function() {
|
||||
var decoded = Base64.decode(B64_STR);
|
||||
const decoded = Base64.decode(B64_STR);
|
||||
expect(decoded).to.deep.equal(BIN_ARR);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/* jshint expr: true */
|
||||
var expect = chai.expect;
|
||||
const expect = chai.expect;
|
||||
|
||||
import Base64 from '../core/base64.js';
|
||||
import Display from '../core/display.js';
|
||||
|
|
@ -7,37 +6,35 @@ import Display from '../core/display.js';
|
|||
import sinon from '../vendor/sinon.js';
|
||||
|
||||
describe('Display/Canvas Helper', function () {
|
||||
var checked_data = [
|
||||
const checked_data = new Uint8Array([
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
||||
];
|
||||
checked_data = new Uint8Array(checked_data);
|
||||
]);
|
||||
|
||||
var basic_data = [0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0xff, 0xff, 0xff, 255];
|
||||
basic_data = new Uint8Array(basic_data);
|
||||
const basic_data = new Uint8Array([0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0xff, 0xff, 0xff, 255]);
|
||||
|
||||
function make_image_canvas (input_data) {
|
||||
var canvas = document.createElement('canvas');
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = 4;
|
||||
canvas.height = 4;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var data = ctx.createImageData(4, 4);
|
||||
for (var i = 0; i < checked_data.length; i++) { data.data[i] = input_data[i]; }
|
||||
const ctx = canvas.getContext('2d');
|
||||
const data = ctx.createImageData(4, 4);
|
||||
for (let i = 0; i < checked_data.length; i++) { data.data[i] = input_data[i]; }
|
||||
ctx.putImageData(data, 0, 0);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function make_image_png (input_data) {
|
||||
var canvas = make_image_canvas(input_data);
|
||||
var url = canvas.toDataURL();
|
||||
var data = url.split(",")[1];
|
||||
const canvas = make_image_canvas(input_data);
|
||||
const url = canvas.toDataURL();
|
||||
const data = url.split(",")[1];
|
||||
return Base64.decode(data);
|
||||
}
|
||||
|
||||
describe('viewport handling', function () {
|
||||
var display;
|
||||
let display;
|
||||
beforeEach(function () {
|
||||
display = new Display(document.createElement('canvas'));
|
||||
display.clipViewport = true;
|
||||
|
|
@ -52,10 +49,9 @@ describe('Display/Canvas Helper', function () {
|
|||
display.drawImage(make_image_canvas(basic_data), 1, 1);
|
||||
display.flip();
|
||||
|
||||
var expected = new Uint8Array(16);
|
||||
var i;
|
||||
for (i = 0; i < 8; i++) { expected[i] = basic_data[i]; }
|
||||
for (i = 8; i < 16; i++) { expected[i] = 0; }
|
||||
const expected = new Uint8Array(16);
|
||||
for (let i = 0; i < 8; i++) { expected[i] = basic_data[i]; }
|
||||
for (let i = 8; i < 16; i++) { expected[i] = 0; }
|
||||
expect(display).to.have.displayed(expected);
|
||||
});
|
||||
|
||||
|
|
@ -120,7 +116,7 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
describe('resizing', function () {
|
||||
var display;
|
||||
let display;
|
||||
beforeEach(function () {
|
||||
display = new Display(document.createElement('canvas'));
|
||||
display.clipViewport = false;
|
||||
|
|
@ -137,8 +133,8 @@ describe('Display/Canvas Helper', function () {
|
|||
display.fillRect(0, 0, 4, 4, [0, 0, 0xff]);
|
||||
display.resize(2, 2);
|
||||
display.flip();
|
||||
var expected = [];
|
||||
for (var i = 0; i < 4 * 2*2; i += 4) {
|
||||
const expected = [];
|
||||
for (let i = 0; i < 4 * 2*2; i += 4) {
|
||||
expected[i] = 0xff;
|
||||
expected[i+1] = expected[i+2] = 0;
|
||||
expected[i+3] = 0xff;
|
||||
|
|
@ -180,8 +176,8 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
describe('rescaling', function () {
|
||||
var display;
|
||||
var canvas;
|
||||
let display;
|
||||
let canvas;
|
||||
|
||||
beforeEach(function () {
|
||||
canvas = document.createElement('canvas');
|
||||
|
|
@ -221,8 +217,8 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
describe('autoscaling', function () {
|
||||
var display;
|
||||
var canvas;
|
||||
let display;
|
||||
let canvas;
|
||||
|
||||
beforeEach(function () {
|
||||
canvas = document.createElement('canvas');
|
||||
|
|
@ -269,7 +265,7 @@ describe('Display/Canvas Helper', function () {
|
|||
|
||||
// TODO(directxman12): improve the tests for each of the drawing functions to cover more than just the
|
||||
// basic cases
|
||||
var display;
|
||||
let display;
|
||||
beforeEach(function () {
|
||||
display = new Display(document.createElement('canvas'));
|
||||
display.resize(4, 4);
|
||||
|
|
@ -280,15 +276,15 @@ describe('Display/Canvas Helper', function () {
|
|||
display._logo = null;
|
||||
display.clear();
|
||||
display.resize(4, 4);
|
||||
var empty = [];
|
||||
for (var i = 0; i < 4 * display._fb_width * display._fb_height; i++) { empty[i] = 0; }
|
||||
const empty = [];
|
||||
for (let i = 0; i < 4 * display._fb_width * display._fb_height; i++) { empty[i] = 0; }
|
||||
expect(display).to.have.displayed(new Uint8Array(empty));
|
||||
});
|
||||
|
||||
it('should draw the logo on #clear with a logo set', function (done) {
|
||||
display._logo = { width: 4, height: 4, type: "image/png", data: make_image_png(checked_data) };
|
||||
display.clear();
|
||||
display.onflush = function () {
|
||||
display.onflush = () => {
|
||||
expect(display).to.have.displayed(checked_data);
|
||||
expect(display._fb_width).to.equal(4);
|
||||
expect(display._fb_height).to.equal(4);
|
||||
|
|
@ -301,8 +297,8 @@ describe('Display/Canvas Helper', function () {
|
|||
display.fillRect(0, 0, 4, 4, [0, 0, 0xff]);
|
||||
display.flip();
|
||||
display.fillRect(0, 0, 4, 4, [0, 0xff, 0]);
|
||||
var expected = [];
|
||||
for (var i = 0; i < 4 * display._fb_width * display._fb_height; i += 4) {
|
||||
const expected = [];
|
||||
for (let i = 0; i < 4 * display._fb_width * display._fb_height; i += 4) {
|
||||
expected[i] = 0xff;
|
||||
expected[i+1] = expected[i+2] = 0;
|
||||
expected[i+3] = 0xff;
|
||||
|
|
@ -329,7 +325,7 @@ describe('Display/Canvas Helper', function () {
|
|||
it('should support drawing images via #imageRect', function (done) {
|
||||
display.imageRect(0, 0, "image/png", make_image_png(checked_data));
|
||||
display.flip();
|
||||
display.onflush = function () {
|
||||
display.onflush = () => {
|
||||
expect(display).to.have.displayed(checked_data);
|
||||
done();
|
||||
};
|
||||
|
|
@ -372,8 +368,8 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
it('should support drawing BGRX blit images with true color via #blitImage', function () {
|
||||
var data = [];
|
||||
for (var i = 0; i < 16; i++) {
|
||||
const data = [];
|
||||
for (let i = 0; i < 16; i++) {
|
||||
data[i * 4] = checked_data[i * 4 + 2];
|
||||
data[i * 4 + 1] = checked_data[i * 4 + 1];
|
||||
data[i * 4 + 2] = checked_data[i * 4];
|
||||
|
|
@ -385,8 +381,8 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
it('should support drawing RGB blit images with true color via #blitRgbImage', function () {
|
||||
var data = [];
|
||||
for (var i = 0; i < 16; i++) {
|
||||
const data = [];
|
||||
for (let i = 0; i < 16; i++) {
|
||||
data[i * 3] = checked_data[i * 4];
|
||||
data[i * 3 + 1] = checked_data[i * 4 + 1];
|
||||
data[i * 3 + 2] = checked_data[i * 4 + 2];
|
||||
|
|
@ -397,7 +393,7 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
it('should support drawing an image object via #drawImage', function () {
|
||||
var img = make_image_canvas(checked_data);
|
||||
const img = make_image_canvas(checked_data);
|
||||
display.drawImage(img, 0, 0);
|
||||
display.flip();
|
||||
expect(display).to.have.displayed(checked_data);
|
||||
|
|
@ -405,7 +401,7 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
describe('the render queue processor', function () {
|
||||
var display;
|
||||
let display;
|
||||
beforeEach(function () {
|
||||
display = new Display(document.createElement('canvas'));
|
||||
display.resize(4, 4);
|
||||
|
|
@ -428,7 +424,7 @@ describe('Display/Canvas Helper', function () {
|
|||
});
|
||||
|
||||
it('should wait until an image is loaded to attempt to draw it and the rest of the queue', function () {
|
||||
var img = { complete: false, addEventListener: sinon.spy() }
|
||||
const img = { complete: false, addEventListener: sinon.spy() }
|
||||
display._renderQ = [{ type: 'img', x: 3, y: 4, img: img },
|
||||
{ type: 'fill', x: 1, y: 2, width: 3, height: 4, color: 5 }];
|
||||
display.drawImage = sinon.spy();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
const expect = chai.expect;
|
||||
|
||||
import keysyms from '../core/input/keysymdef.js';
|
||||
import * as KeyboardUtil from "../core/input/util.js";
|
||||
|
|
@ -12,8 +11,6 @@ function isEdge() {
|
|||
}
|
||||
|
||||
describe('Helpers', function() {
|
||||
"use strict";
|
||||
|
||||
describe('keysyms.lookup', function() {
|
||||
it('should map ASCII characters to keysyms', function() {
|
||||
expect(keysyms.lookup('a'.charCodeAt())).to.be.equal(0x61);
|
||||
|
|
@ -71,7 +68,7 @@ describe('Helpers', function() {
|
|||
});
|
||||
|
||||
describe('Fix Meta on macOS', function() {
|
||||
var origNavigator;
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -134,7 +131,7 @@ describe('Helpers', function() {
|
|||
});
|
||||
|
||||
describe('Broken key AltGraph on IE/Edge', function() {
|
||||
var origNavigator;
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
const expect = chai.expect;
|
||||
|
||||
import sinon from '../vendor/sinon.js';
|
||||
|
||||
|
|
@ -12,27 +11,24 @@ function isEdge() {
|
|||
return navigator && !!(/edge/i).exec(navigator.userAgent);
|
||||
}
|
||||
|
||||
/* jshint newcap: false, expr: true */
|
||||
describe('Key Event Handling', function() {
|
||||
"use strict";
|
||||
|
||||
// The real KeyboardEvent constructor might not work everywhere we
|
||||
// want to run these tests
|
||||
function keyevent(typeArg, KeyboardEventInit) {
|
||||
var e = { type: typeArg };
|
||||
for (var key in KeyboardEventInit) {
|
||||
const e = { type: typeArg };
|
||||
for (let key in KeyboardEventInit) {
|
||||
e[key] = KeyboardEventInit[key];
|
||||
}
|
||||
e.stopPropagation = sinon.spy();
|
||||
e.preventDefault = sinon.spy();
|
||||
return e;
|
||||
};
|
||||
}
|
||||
|
||||
describe('Decode Keyboard Events', function() {
|
||||
it('should decode keydown events', function(done) {
|
||||
if (isIE() || isEdge()) this.skip();
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -42,9 +38,9 @@ describe('Key Event Handling', function() {
|
|||
});
|
||||
it('should decode keyup events', function(done) {
|
||||
if (isIE() || isEdge()) this.skip();
|
||||
var calls = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let calls = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
if (calls++ === 1) {
|
||||
|
|
@ -58,14 +54,14 @@ describe('Key Event Handling', function() {
|
|||
|
||||
describe('Legacy keypress Events', function() {
|
||||
it('should wait for keypress when needed', function() {
|
||||
var kbd = new Keyboard(document);
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
});
|
||||
it('should decode keypress events', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -75,15 +71,15 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyPress(keyevent('keypress', {code: 'KeyA', charCode: 0x61}));
|
||||
});
|
||||
it('should ignore keypress with different code', function() {
|
||||
var kbd = new Keyboard(document);
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41}));
|
||||
kbd._handleKeyPress(keyevent('keypress', {code: 'KeyB', charCode: 0x61}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
});
|
||||
it('should handle keypress with missing code', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -93,8 +89,8 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyPress(keyevent('keypress', {charCode: 0x61}));
|
||||
});
|
||||
it('should guess key if no keypress and numeric key', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x32);
|
||||
expect(code).to.be.equal('Digit2');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -103,8 +99,8 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyDown(keyevent('keydown', {code: 'Digit2', keyCode: 0x32}));
|
||||
});
|
||||
it('should guess key if no keypress and alpha key', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -113,8 +109,8 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41, shiftKey: false}));
|
||||
});
|
||||
it('should guess key if no keypress and alpha key (with shift)', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x41);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -123,8 +119,8 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41, shiftKey: true}));
|
||||
});
|
||||
it('should not guess key if no keypress and unknown key', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -139,27 +135,27 @@ describe('Key Event Handling', function() {
|
|||
if (isIE() || isEdge()) this.skip();
|
||||
});
|
||||
it('should suppress anything with a valid key', function() {
|
||||
var kbd = new Keyboard(document, {});
|
||||
var evt = keyevent('keydown', {code: 'KeyA', key: 'a'});
|
||||
kbd._handleKeyDown(evt);
|
||||
expect(evt.preventDefault).to.have.been.called;
|
||||
evt = keyevent('keyup', {code: 'KeyA', key: 'a'});
|
||||
kbd._handleKeyUp(evt);
|
||||
expect(evt.preventDefault).to.have.been.called;
|
||||
const kbd = new Keyboard(document, {});
|
||||
const evt1 = keyevent('keydown', {code: 'KeyA', key: 'a'});
|
||||
kbd._handleKeyDown(evt1);
|
||||
expect(evt1.preventDefault).to.have.been.called;
|
||||
const evt2 = keyevent('keyup', {code: 'KeyA', key: 'a'});
|
||||
kbd._handleKeyUp(evt2);
|
||||
expect(evt2.preventDefault).to.have.been.called;
|
||||
});
|
||||
it('should not suppress keys without key', function() {
|
||||
var kbd = new Keyboard(document, {});
|
||||
var evt = keyevent('keydown', {code: 'KeyA', keyCode: 0x41});
|
||||
const kbd = new Keyboard(document, {});
|
||||
const evt = keyevent('keydown', {code: 'KeyA', keyCode: 0x41});
|
||||
kbd._handleKeyDown(evt);
|
||||
expect(evt.preventDefault).to.not.have.been.called;
|
||||
});
|
||||
it('should suppress the following keypress event', function() {
|
||||
var kbd = new Keyboard(document, {});
|
||||
var evt = keyevent('keydown', {code: 'KeyA', keyCode: 0x41});
|
||||
kbd._handleKeyDown(evt);
|
||||
var evt = keyevent('keypress', {code: 'KeyA', charCode: 0x41});
|
||||
kbd._handleKeyPress(evt);
|
||||
expect(evt.preventDefault).to.have.been.called;
|
||||
const kbd = new Keyboard(document, {});
|
||||
const evt1 = keyevent('keydown', {code: 'KeyA', keyCode: 0x41});
|
||||
kbd._handleKeyDown(evt1);
|
||||
const evt2 = keyevent('keypress', {code: 'KeyA', charCode: 0x41});
|
||||
kbd._handleKeyPress(evt2);
|
||||
expect(evt2.preventDefault).to.have.been.called;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -167,9 +163,9 @@ describe('Key Event Handling', function() {
|
|||
describe('Fake keyup', function() {
|
||||
it('should fake keyup events for virtual keyboards', function(done) {
|
||||
if (isIE() || isEdge()) this.skip();
|
||||
var count = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let count = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch (count++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
|
|
@ -187,7 +183,7 @@ describe('Key Event Handling', function() {
|
|||
});
|
||||
|
||||
describe('iOS', function() {
|
||||
var origNavigator;
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -214,9 +210,9 @@ describe('Key Event Handling', function() {
|
|||
|
||||
it('should fake keyup events on iOS', function(done) {
|
||||
if (isIE() || isEdge()) this.skip();
|
||||
var count = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let count = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch (count++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
|
|
@ -240,8 +236,8 @@ describe('Key Event Handling', function() {
|
|||
if (isIE() || isEdge()) this.skip();
|
||||
});
|
||||
it('should send release using the same keysym as the press', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
if (!down) {
|
||||
|
|
@ -252,9 +248,9 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'b'}));
|
||||
});
|
||||
it('should send the same keysym for multiple presses', function() {
|
||||
var count = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let count = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
|
|
@ -265,7 +261,7 @@ describe('Key Event Handling', function() {
|
|||
expect(count).to.be.equal(2);
|
||||
});
|
||||
it('should do nothing on keyup events if no keys are down', function() {
|
||||
var kbd = new Keyboard(document);
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
|
|
@ -273,8 +269,8 @@ describe('Key Event Handling', function() {
|
|||
|
||||
describe('Legacy Events', function() {
|
||||
it('should track keys using keyCode if no code', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Platform65');
|
||||
if (!down) {
|
||||
|
|
@ -285,16 +281,16 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyUp(keyevent('keyup', {keyCode: 65, key: 'b'}));
|
||||
});
|
||||
it('should ignore compositing code', function() {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Unidentified');
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {keyCode: 229, key: 'a'}));
|
||||
});
|
||||
it('should track keys using keyIdentifier if no code', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Platform65');
|
||||
if (!down) {
|
||||
|
|
@ -308,7 +304,7 @@ describe('Key Event Handling', function() {
|
|||
});
|
||||
|
||||
describe('Shuffle modifiers on macOS', function() {
|
||||
var origNavigator;
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -334,9 +330,9 @@ describe('Key Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should change Alt to AltGraph', function() {
|
||||
var count = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let count = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code) => {
|
||||
switch (count++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0xFF7E);
|
||||
|
|
@ -353,8 +349,8 @@ describe('Key Event Handling', function() {
|
|||
expect(count).to.be.equal(2);
|
||||
});
|
||||
it('should change left Super to Alt', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code) => {
|
||||
expect(keysym).to.be.equal(0xFFE9);
|
||||
expect(code).to.be.equal('MetaLeft');
|
||||
done();
|
||||
|
|
@ -362,8 +358,8 @@ describe('Key Event Handling', function() {
|
|||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaLeft', key: 'Meta', location: 1}));
|
||||
});
|
||||
it('should change right Super to left Super', function(done) {
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code) => {
|
||||
expect(keysym).to.be.equal(0xFFEB);
|
||||
expect(code).to.be.equal('MetaRight');
|
||||
done();
|
||||
|
|
@ -373,7 +369,7 @@ describe('Key Event Handling', function() {
|
|||
});
|
||||
|
||||
describe('Escape AltGraph on Windows', function() {
|
||||
var origNavigator;
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -399,9 +395,9 @@ describe('Key Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should generate fake undo/redo events on press when AltGraph is down', function() {
|
||||
var times_called = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let times_called = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch(times_called++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0xFFE3);
|
||||
|
|
@ -448,9 +444,9 @@ describe('Key Event Handling', function() {
|
|||
expect(times_called).to.be.equal(7);
|
||||
});
|
||||
it('should no do anything on key release', function() {
|
||||
var times_called = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let times_called = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch(times_called++) {
|
||||
case 7:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
|
|
@ -468,9 +464,9 @@ describe('Key Event Handling', function() {
|
|||
expect(times_called).to.be.equal(8);
|
||||
});
|
||||
it('should not consider a char modifier to be down on the modifier key itself', function() {
|
||||
var times_called = 0;
|
||||
var kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = function(keysym, code, down) {
|
||||
let times_called = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch(times_called++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0xFFE3);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
/* jshint expr: true */
|
||||
const expect = chai.expect;
|
||||
|
||||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
|
||||
import l10nGet, { l10n } from '../app/localization.js';
|
||||
import { l10n } from '../app/localization.js';
|
||||
|
||||
describe('Localization', function() {
|
||||
"use strict";
|
||||
|
||||
describe('language selection', function () {
|
||||
var origNavigator;
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -35,7 +30,8 @@ describe('Localization', function() {
|
|||
});
|
||||
|
||||
it('should use English by default', function() {
|
||||
expect(l10n.language).to.equal('en');
|
||||
const a = l10n.language;
|
||||
expect(a).to.equal('en');
|
||||
});
|
||||
it('should use English if no user language matches', function() {
|
||||
window.navigator.languages = ["nl", "de"];
|
||||
|
|
|
|||
|
|
@ -1,40 +1,36 @@
|
|||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
const expect = chai.expect;
|
||||
|
||||
import sinon from '../vendor/sinon.js';
|
||||
|
||||
import Mouse from '../core/input/mouse.js';
|
||||
import * as eventUtils from '../core/util/events.js';
|
||||
|
||||
/* jshint newcap: false, expr: true */
|
||||
describe('Mouse Event Handling', function() {
|
||||
"use strict";
|
||||
|
||||
sinon.stub(eventUtils, 'setCapture');
|
||||
// This function is only used on target (the canvas)
|
||||
// and for these tests we can assume that the canvas is 100x100
|
||||
// located at coordinates 10x10
|
||||
sinon.stub(Element.prototype, 'getBoundingClientRect').returns(
|
||||
{left: 10, right: 110, top: 10, bottom: 110, width: 100, height: 100});
|
||||
var target = document.createElement('canvas');
|
||||
const target = document.createElement('canvas');
|
||||
|
||||
// The real constructors might not work everywhere we
|
||||
// want to run these tests
|
||||
var mouseevent, touchevent;
|
||||
mouseevent = touchevent = function(typeArg, MouseEventInit) {
|
||||
var e = { type: typeArg };
|
||||
for (var key in MouseEventInit) {
|
||||
const touchevent = (typeArg, MouseEventInit) => {
|
||||
const e = { type: typeArg };
|
||||
for (let key in MouseEventInit) {
|
||||
e[key] = MouseEventInit[key];
|
||||
}
|
||||
e.stopPropagation = sinon.spy();
|
||||
e.preventDefault = sinon.spy();
|
||||
return e;
|
||||
};
|
||||
const mouseevent = touchevent;
|
||||
|
||||
describe('Decode Mouse Events', function() {
|
||||
it('should decode mousedown events', function(done) {
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down, bmask) => {
|
||||
expect(bmask).to.be.equal(0x01);
|
||||
expect(down).to.be.equal(1);
|
||||
done();
|
||||
|
|
@ -42,9 +38,9 @@ describe('Mouse Event Handling', function() {
|
|||
mouse._handleMouseDown(mouseevent('mousedown', { button: '0x01' }));
|
||||
});
|
||||
it('should decode mouseup events', function(done) {
|
||||
var calls = 0;
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
let calls = 0;
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down, bmask) => {
|
||||
expect(bmask).to.be.equal(0x01);
|
||||
if (calls++ === 1) {
|
||||
expect(down).to.not.be.equal(1);
|
||||
|
|
@ -55,8 +51,8 @@ describe('Mouse Event Handling', function() {
|
|||
mouse._handleMouseUp(mouseevent('mouseup', { button: '0x01' }));
|
||||
});
|
||||
it('should decode mousemove events', function(done) {
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousemove = function(x, y) {
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousemove = (x, y) => {
|
||||
// Note that target relative coordinates are sent
|
||||
expect(x).to.be.equal(40);
|
||||
expect(y).to.be.equal(10);
|
||||
|
|
@ -66,9 +62,9 @@ describe('Mouse Event Handling', function() {
|
|||
{ clientX: 50, clientY: 20 }));
|
||||
});
|
||||
it('should decode mousewheel events', function(done) {
|
||||
var calls = 0;
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
let calls = 0;
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down, bmask) => {
|
||||
calls++;
|
||||
expect(bmask).to.be.equal(1<<6);
|
||||
if (calls === 1) {
|
||||
|
|
@ -90,9 +86,9 @@ describe('Mouse Event Handling', function() {
|
|||
afterEach(function () { this.clock.restore(); });
|
||||
|
||||
it('should use same pos for 2nd tap if close enough', function(done) {
|
||||
var calls = 0;
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
let calls = 0;
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down) => {
|
||||
calls++;
|
||||
if (calls === 1) {
|
||||
expect(down).to.be.equal(1);
|
||||
|
|
@ -121,9 +117,9 @@ describe('Mouse Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should not modify 2nd tap pos if far apart', function(done) {
|
||||
var calls = 0;
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
let calls = 0;
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down) => {
|
||||
calls++;
|
||||
if (calls === 1) {
|
||||
expect(down).to.be.equal(1);
|
||||
|
|
@ -150,9 +146,9 @@ describe('Mouse Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should not modify 2nd tap pos if not soon enough', function(done) {
|
||||
var calls = 0;
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
let calls = 0;
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down) => {
|
||||
calls++;
|
||||
if (calls === 1) {
|
||||
expect(down).to.be.equal(1);
|
||||
|
|
@ -179,9 +175,9 @@ describe('Mouse Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should not modify 2nd tap pos if not touch', function(done) {
|
||||
var calls = 0;
|
||||
var mouse = new Mouse(target);
|
||||
mouse.onmousebutton = function(x, y, down, bmask) {
|
||||
let calls = 0;
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = (x, y, down) => {
|
||||
calls++;
|
||||
if (calls === 1) {
|
||||
expect(down).to.be.equal(1);
|
||||
|
|
@ -215,7 +211,7 @@ describe('Mouse Event Handling', function() {
|
|||
afterEach(function () { this.clock.restore(); });
|
||||
|
||||
it('should accumulate wheel events if small enough', function () {
|
||||
var mouse = new Mouse(target);
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = sinon.spy();
|
||||
|
||||
mouse._handleMouseWheel(mouseevent(
|
||||
|
|
@ -248,7 +244,7 @@ describe('Mouse Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should not accumulate large wheel events', function () {
|
||||
var mouse = new Mouse(target);
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = sinon.spy();
|
||||
|
||||
mouse._handleMouseWheel(mouseevent(
|
||||
|
|
@ -267,7 +263,7 @@ describe('Mouse Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should send even small wheel events after a timeout', function () {
|
||||
var mouse = new Mouse(target);
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = sinon.spy();
|
||||
|
||||
mouse._handleMouseWheel(mouseevent(
|
||||
|
|
@ -279,7 +275,7 @@ describe('Mouse Event Handling', function() {
|
|||
});
|
||||
|
||||
it('should account for non-zero deltaMode', function () {
|
||||
var mouse = new Mouse(target);
|
||||
const mouse = new Mouse(target);
|
||||
mouse.onmousebutton = sinon.spy();
|
||||
|
||||
mouse._handleMouseWheel(mouseevent(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,5 @@
|
|||
/* jshint expr: true */
|
||||
|
||||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
/* eslint-disable no-console */
|
||||
const expect = chai.expect;
|
||||
|
||||
import * as Log from '../core/util/logging.js';
|
||||
|
||||
|
|
@ -70,3 +68,4 @@ describe('Utils', function() {
|
|||
// (we can't really test them against the browsers, except for Gecko
|
||||
// via PhantomJS, the default test driver)
|
||||
});
|
||||
/* eslint-enable no-console */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/* jshint expr: true */
|
||||
var assert = chai.assert;
|
||||
var expect = chai.expect;
|
||||
const expect = chai.expect;
|
||||
|
||||
import Websock from '../core/websock.js';
|
||||
import FakeWebSocket from './fake.websocket.js';
|
||||
|
|
@ -11,8 +9,8 @@ describe('Websock', function() {
|
|||
"use strict";
|
||||
|
||||
describe('Queue methods', function () {
|
||||
var sock;
|
||||
var RQ_TEMPLATE = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
let sock;
|
||||
const RQ_TEMPLATE = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
|
||||
beforeEach(function () {
|
||||
sock = new Websock();
|
||||
|
|
@ -37,8 +35,8 @@ describe('Websock', function() {
|
|||
|
||||
describe('rQpeek8', function () {
|
||||
it('should peek at the next byte without poping it off the queue', function () {
|
||||
var bef_len = sock.rQlen();
|
||||
var peek = sock.rQpeek8();
|
||||
const bef_len = sock.rQlen();
|
||||
const peek = sock.rQpeek8();
|
||||
expect(sock.rQpeek8()).to.equal(peek);
|
||||
expect(sock.rQlen()).to.equal(bef_len);
|
||||
});
|
||||
|
|
@ -46,8 +44,8 @@ describe('Websock', function() {
|
|||
|
||||
describe('rQshift8', function () {
|
||||
it('should pop a single byte from the receive queue', function () {
|
||||
var peek = sock.rQpeek8();
|
||||
var bef_len = sock.rQlen();
|
||||
const peek = sock.rQpeek8();
|
||||
const bef_len = sock.rQlen();
|
||||
expect(sock.rQshift8()).to.equal(peek);
|
||||
expect(sock.rQlen()).to.equal(bef_len - 1);
|
||||
});
|
||||
|
|
@ -55,8 +53,8 @@ describe('Websock', function() {
|
|||
|
||||
describe('rQshift16', function () {
|
||||
it('should pop two bytes from the receive queue and return a single number', function () {
|
||||
var bef_len = sock.rQlen();
|
||||
var expected = (RQ_TEMPLATE[0] << 8) + RQ_TEMPLATE[1];
|
||||
const bef_len = sock.rQlen();
|
||||
const expected = (RQ_TEMPLATE[0] << 8) + RQ_TEMPLATE[1];
|
||||
expect(sock.rQshift16()).to.equal(expected);
|
||||
expect(sock.rQlen()).to.equal(bef_len - 2);
|
||||
});
|
||||
|
|
@ -64,8 +62,8 @@ describe('Websock', function() {
|
|||
|
||||
describe('rQshift32', function () {
|
||||
it('should pop four bytes from the receive queue and return a single number', function () {
|
||||
var bef_len = sock.rQlen();
|
||||
var expected = (RQ_TEMPLATE[0] << 24) +
|
||||
const bef_len = sock.rQlen();
|
||||
const expected = (RQ_TEMPLATE[0] << 24) +
|
||||
(RQ_TEMPLATE[1] << 16) +
|
||||
(RQ_TEMPLATE[2] << 8) +
|
||||
RQ_TEMPLATE[3];
|
||||
|
|
@ -76,9 +74,9 @@ describe('Websock', function() {
|
|||
|
||||
describe('rQshiftStr', function () {
|
||||
it('should shift the given number of bytes off of the receive queue and return a string', function () {
|
||||
var bef_len = sock.rQlen();
|
||||
var bef_rQi = sock.get_rQi();
|
||||
var shifted = sock.rQshiftStr(3);
|
||||
const bef_len = sock.rQlen();
|
||||
const bef_rQi = sock.get_rQi();
|
||||
const shifted = sock.rQshiftStr(3);
|
||||
expect(shifted).to.be.a('string');
|
||||
expect(shifted).to.equal(String.fromCharCode.apply(null, Array.prototype.slice.call(new Uint8Array(RQ_TEMPLATE.buffer, bef_rQi, 3))));
|
||||
expect(sock.rQlen()).to.equal(bef_len - 3);
|
||||
|
|
@ -92,9 +90,9 @@ describe('Websock', function() {
|
|||
|
||||
describe('rQshiftBytes', function () {
|
||||
it('should shift the given number of bytes of the receive queue and return an array', function () {
|
||||
var bef_len = sock.rQlen();
|
||||
var bef_rQi = sock.get_rQi();
|
||||
var shifted = sock.rQshiftBytes(3);
|
||||
const bef_len = sock.rQlen();
|
||||
const bef_rQi = sock.get_rQi();
|
||||
const shifted = sock.rQshiftBytes(3);
|
||||
expect(shifted).to.be.an.instanceof(Uint8Array);
|
||||
expect(shifted).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, bef_rQi, 3));
|
||||
expect(sock.rQlen()).to.equal(bef_len - 3);
|
||||
|
|
@ -112,19 +110,19 @@ describe('Websock', function() {
|
|||
});
|
||||
|
||||
it('should not modify the receive queue', function () {
|
||||
var bef_len = sock.rQlen();
|
||||
const bef_len = sock.rQlen();
|
||||
sock.rQslice(0, 2);
|
||||
expect(sock.rQlen()).to.equal(bef_len);
|
||||
});
|
||||
|
||||
it('should return an array containing the given slice of the receive queue', function () {
|
||||
var sl = sock.rQslice(0, 2);
|
||||
const sl = sock.rQslice(0, 2);
|
||||
expect(sl).to.be.an.instanceof(Uint8Array);
|
||||
expect(sl).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, 0, 2));
|
||||
});
|
||||
|
||||
it('should use the rest of the receive queue if no end is given', function () {
|
||||
var sl = sock.rQslice(1);
|
||||
const sl = sock.rQslice(1);
|
||||
expect(sl).to.have.length(RQ_TEMPLATE.length - 1);
|
||||
expect(sl).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, 1));
|
||||
});
|
||||
|
|
@ -178,7 +176,7 @@ describe('Websock', function() {
|
|||
sock._websocket.readyState = WebSocket.OPEN
|
||||
sock._sQ = new Uint8Array([1, 2, 3]);
|
||||
sock._sQlen = 3;
|
||||
var encoded = sock._encode_message();
|
||||
const encoded = sock._encode_message();
|
||||
|
||||
sock.flush();
|
||||
expect(sock._websocket.send).to.have.been.calledOnce;
|
||||
|
|
@ -202,7 +200,7 @@ describe('Websock', function() {
|
|||
|
||||
it('should add to the send queue', function () {
|
||||
sock.send([1, 2, 3]);
|
||||
var sq = sock.get_sQ();
|
||||
const sq = sock.get_sQ();
|
||||
expect(new Uint8Array(sq.buffer, sock._sQlen - 3, 3)).to.array.equal(new Uint8Array([1, 2, 3]));
|
||||
});
|
||||
|
||||
|
|
@ -225,14 +223,15 @@ describe('Websock', function() {
|
|||
});
|
||||
|
||||
describe('lifecycle methods', function () {
|
||||
var old_WS;
|
||||
let old_WS;
|
||||
before(function () {
|
||||
old_WS = WebSocket;
|
||||
});
|
||||
|
||||
var sock;
|
||||
let sock;
|
||||
beforeEach(function () {
|
||||
sock = new Websock();
|
||||
// eslint-disable-next-line no-global-assign
|
||||
WebSocket = sinon.spy();
|
||||
WebSocket.OPEN = old_WS.OPEN;
|
||||
WebSocket.CONNECTING = old_WS.CONNECTING;
|
||||
|
|
@ -328,19 +327,20 @@ describe('Websock', function() {
|
|||
});
|
||||
|
||||
after(function () {
|
||||
// eslint-disable-next-line no-global-assign
|
||||
WebSocket = old_WS;
|
||||
});
|
||||
});
|
||||
|
||||
describe('WebSocket Receiving', function () {
|
||||
var sock;
|
||||
let sock;
|
||||
beforeEach(function () {
|
||||
sock = new Websock();
|
||||
sock._allocate_buffers();
|
||||
});
|
||||
|
||||
it('should support adding binary Uint8Array data to the receive queue', function () {
|
||||
var msg = { data: new Uint8Array([1, 2, 3]) };
|
||||
const msg = { data: new Uint8Array([1, 2, 3]) };
|
||||
sock._mode = 'binary';
|
||||
sock._recv_message(msg);
|
||||
expect(sock.rQshiftStr(3)).to.equal('\x01\x02\x03');
|
||||
|
|
@ -348,7 +348,7 @@ describe('Websock', function() {
|
|||
|
||||
it('should call the message event handler if present', function () {
|
||||
sock._eventHandlers.message = sinon.spy();
|
||||
var msg = { data: new Uint8Array([1, 2, 3]).buffer };
|
||||
const msg = { data: new Uint8Array([1, 2, 3]).buffer };
|
||||
sock._mode = 'binary';
|
||||
sock._recv_message(msg);
|
||||
expect(sock._eventHandlers.message).to.have.been.calledOnce;
|
||||
|
|
@ -356,7 +356,7 @@ describe('Websock', function() {
|
|||
|
||||
it('should not call the message event handler if there is nothing in the receive queue', function () {
|
||||
sock._eventHandlers.message = sinon.spy();
|
||||
var msg = { data: new Uint8Array([]).buffer };
|
||||
const msg = { data: new Uint8Array([]).buffer };
|
||||
sock._mode = 'binary';
|
||||
sock._recv_message(msg);
|
||||
expect(sock._eventHandlers.message).not.to.have.been.called;
|
||||
|
|
@ -369,7 +369,7 @@ describe('Websock', function() {
|
|||
sock._rQlen = 6;
|
||||
sock.set_rQi(6);
|
||||
sock._rQmax = 3;
|
||||
var msg = { data: new Uint8Array([1, 2, 3]).buffer };
|
||||
const msg = { data: new Uint8Array([1, 2, 3]).buffer };
|
||||
sock._mode = 'binary';
|
||||
sock._recv_message(msg);
|
||||
expect(sock._rQlen).to.equal(3);
|
||||
|
|
@ -382,12 +382,12 @@ describe('Websock', function() {
|
|||
sock.set_rQi(0);
|
||||
sock._rQbufferSize = 20;
|
||||
sock._rQmax = 2;
|
||||
var msg = { data: new Uint8Array(30).buffer };
|
||||
const msg = { data: new Uint8Array(30).buffer };
|
||||
sock._mode = 'binary';
|
||||
sock._recv_message(msg);
|
||||
expect(sock._rQlen).to.equal(30);
|
||||
expect(sock.get_rQi()).to.equal(0);
|
||||
expect(sock._rQ.length).to.equal(240); // keep the invariant that rQbufferSize / 8 >= rQlen
|
||||
expect(sock._rQ.length).to.equal(240); // keep the inconstiant that rQbufferSize / 8 >= rQlen
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -396,7 +396,7 @@ describe('Websock', function() {
|
|||
after(function () { FakeWebSocket.restore(); });
|
||||
|
||||
describe('as binary data', function () {
|
||||
var sock;
|
||||
let sock;
|
||||
beforeEach(function () {
|
||||
sock = new Websock();
|
||||
sock.open('ws://', 'binary');
|
||||
|
|
@ -406,7 +406,7 @@ describe('Websock', function() {
|
|||
it('should only send the send queue up to the send queue length', function () {
|
||||
sock._sQ = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
sock._sQlen = 3;
|
||||
var res = sock._encode_message();
|
||||
const res = sock._encode_message();
|
||||
expect(res).to.array.equal(new Uint8Array([1, 2, 3]));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
||||
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var fs = require('fs');
|
||||
const fs = require('fs');
|
||||
|
||||
var show_help = process.argv.length === 2;
|
||||
var filename;
|
||||
let show_help = process.argv.length === 2;
|
||||
let filename;
|
||||
|
||||
for (var i = 2; i < process.argv.length; ++i) {
|
||||
for (let i = 2; i < process.argv.length; ++i) {
|
||||
switch (process.argv[i]) {
|
||||
case "--help":
|
||||
case "-h":
|
||||
|
|
@ -36,37 +36,37 @@ if (show_help) {
|
|||
console.log("Usage: node parse.js [options] filename:");
|
||||
console.log(" -h [ --help ] Produce this help message");
|
||||
console.log(" filename The keysymdef.h file to parse");
|
||||
return;
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
var buf = fs.readFileSync(filename);
|
||||
var str = buf.toString('utf8');
|
||||
const buf = fs.readFileSync(filename);
|
||||
const str = buf.toString('utf8');
|
||||
|
||||
var re = /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/m;
|
||||
const re = /^#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/m;
|
||||
|
||||
var arr = str.split('\n');
|
||||
const arr = str.split('\n');
|
||||
|
||||
var codepoints = {};
|
||||
const codepoints = {};
|
||||
|
||||
for (var i = 0; i < arr.length; ++i) {
|
||||
var result = re.exec(arr[i]);
|
||||
for (let i = 0; i < arr.length; ++i) {
|
||||
const result = re.exec(arr[i]);
|
||||
if (result){
|
||||
var keyname = result[1];
|
||||
var keysym = parseInt(result[2], 16);
|
||||
var remainder = result[3];
|
||||
const name = result[1];
|
||||
const keysym = parseInt(result[2], 16);
|
||||
const remainder = result[3];
|
||||
|
||||
var unicodeRes = /U\+([0-9a-fA-F]+)/.exec(remainder);
|
||||
const unicodeRes = /U\+([0-9a-fA-F]+)/.exec(remainder);
|
||||
if (unicodeRes) {
|
||||
var unicode = parseInt(unicodeRes[1], 16);
|
||||
const unicode = parseInt(unicodeRes[1], 16);
|
||||
// The first entry is the preferred one
|
||||
if (!codepoints[unicode]){
|
||||
codepoints[unicode] = { keysym: keysym, name: keyname };
|
||||
codepoints[unicode] = { keysym, name };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var out =
|
||||
let out =
|
||||
"/*\n" +
|
||||
" * Mapping from Unicode codepoints to X11/RFB keysyms\n" +
|
||||
" *\n" +
|
||||
|
|
@ -79,14 +79,14 @@ var out =
|
|||
"var codepoints = {\n";
|
||||
|
||||
function toHex(num) {
|
||||
var s = num.toString(16);
|
||||
let s = num.toString(16);
|
||||
if (s.length < 4) {
|
||||
s = ("0000" + s).slice(-4);
|
||||
}
|
||||
return "0x" + s;
|
||||
};
|
||||
}
|
||||
|
||||
for (var codepoint in codepoints) {
|
||||
for (let codepoint in codepoints) {
|
||||
codepoint = parseInt(codepoint);
|
||||
|
||||
// Latin-1?
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var path = require('path');
|
||||
var program = require('commander');
|
||||
var fs = require('fs');
|
||||
var fse = require('fs-extra');
|
||||
const path = require('path');
|
||||
const program = require('commander');
|
||||
const fs = require('fs');
|
||||
const fse = require('fs-extra');
|
||||
|
||||
const SUPPORTED_FORMATS = new Set(['amd', 'commonjs', 'systemjs', 'umd']);
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ no_copy_files.forEach((file) => no_transform_files.add(file));
|
|||
|
||||
// walkDir *recursively* walks directories trees,
|
||||
// calling the callback for all normal files found.
|
||||
var walkDir = function (base_path, cb, filter) {
|
||||
function walkDir(base_path, cb, filter) {
|
||||
fs.readdir(base_path, (err, files) => {
|
||||
if (err) throw err;
|
||||
|
||||
|
|
@ -56,26 +56,26 @@ var walkDir = function (base_path, cb, filter) {
|
|||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
var transform_html = function (new_script) {
|
||||
function transform_html(new_script) {
|
||||
// write out the modified vnc.html file that works with the bundle
|
||||
var src_html_path = path.resolve(__dirname, '..', 'vnc.html');
|
||||
var out_html_path = path.resolve(paths.out_dir_base, 'vnc.html');
|
||||
const src_html_path = path.resolve(__dirname, '..', 'vnc.html');
|
||||
const out_html_path = path.resolve(paths.out_dir_base, 'vnc.html');
|
||||
fs.readFile(src_html_path, (err, contents_raw) => {
|
||||
if (err) { throw err; }
|
||||
|
||||
var contents = contents_raw.toString();
|
||||
let contents = contents_raw.toString();
|
||||
|
||||
var start_marker = '<!-- begin scripts -->\n';
|
||||
var end_marker = '<!-- end scripts -->';
|
||||
var start_ind = contents.indexOf(start_marker) + start_marker.length;
|
||||
var end_ind = contents.indexOf(end_marker, start_ind);
|
||||
const start_marker = '<!-- begin scripts -->\n';
|
||||
const end_marker = '<!-- end scripts -->';
|
||||
const start_ind = contents.indexOf(start_marker) + start_marker.length;
|
||||
const end_ind = contents.indexOf(end_marker, start_ind);
|
||||
|
||||
contents = contents.slice(0, start_ind) + `${new_script}\n` + contents.slice(end_ind);
|
||||
|
||||
console.log(`Writing ${out_html_path}`);
|
||||
fs.writeFile(out_html_path, contents, function (err) {
|
||||
fs.writeFile(out_html_path, contents, (err) => {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
});
|
||||
|
|
@ -90,18 +90,20 @@ var make_lib_files = function (import_format, source_maps, with_app_dir) {
|
|||
|
||||
// NB: we need to make a copy of babel_opts, since babel sets some defaults on it
|
||||
const babel_opts = () => ({
|
||||
presets: ['es2015'],
|
||||
plugins: [`transform-es2015-modules-${import_format}`],
|
||||
ast: false,
|
||||
sourceMaps: source_maps,
|
||||
});
|
||||
const babel = require('babel-core');
|
||||
|
||||
var in_path;
|
||||
let in_path;
|
||||
let out_path_base;
|
||||
if (with_app_dir) {
|
||||
var out_path_base = paths.out_dir_base;
|
||||
out_path_base = paths.out_dir_base;
|
||||
in_path = paths.main;
|
||||
} else {
|
||||
var out_path_base = paths.lib_dir_base;
|
||||
out_path_base = paths.lib_dir_base;
|
||||
}
|
||||
|
||||
fse.ensureDirSync(out_path_base);
|
||||
|
|
@ -109,7 +111,7 @@ var make_lib_files = function (import_format, source_maps, with_app_dir) {
|
|||
const helpers = require('./use_require_helpers');
|
||||
const helper = helpers[import_format];
|
||||
|
||||
var handleDir = (js_only, vendor_rewrite, in_path_base, filename) => {
|
||||
const handleDir = (js_only, vendor_rewrite, in_path_base, filename) => {
|
||||
if (no_copy_files.has(filename)) return;
|
||||
|
||||
const out_path = path.join(out_path_base, path.relative(in_path_base, filename));
|
||||
|
|
@ -143,7 +145,7 @@ var make_lib_files = function (import_format, source_maps, with_app_dir) {
|
|||
babel.transformFile(filename, opts, (err, res) => {
|
||||
console.log(`Writing ${out_path}`);
|
||||
if (err) throw err;
|
||||
var {code, map, ast} = res;
|
||||
let {code, map} = res;
|
||||
if (source_maps === true) {
|
||||
// append URL for external source map
|
||||
code += `\n//# sourceMappingURL=${path.basename(out_path)}.map\n`;
|
||||
|
|
@ -161,11 +163,11 @@ var make_lib_files = function (import_format, source_maps, with_app_dir) {
|
|||
helper.noCopyOverride(paths, no_copy_files);
|
||||
}
|
||||
|
||||
walkDir(paths.vendor, handleDir.bind(null, true, false, in_path || paths.main), (filename, stats) => !no_copy_files.has(filename));
|
||||
walkDir(paths.core, handleDir.bind(null, true, !in_path, in_path || paths.core), (filename, stats) => !no_copy_files.has(filename));
|
||||
walkDir(paths.vendor, handleDir.bind(null, true, false, in_path || paths.main), filename => !no_copy_files.has(filename));
|
||||
walkDir(paths.core, handleDir.bind(null, true, !in_path, in_path || paths.core), filename => !no_copy_files.has(filename));
|
||||
|
||||
if (with_app_dir) {
|
||||
walkDir(paths.app, handleDir.bind(null, false, false, in_path), (filename, stats) => !no_copy_files.has(filename));
|
||||
walkDir(paths.app, handleDir.bind(null, false, false, in_path), filename => !no_copy_files.has(filename));
|
||||
|
||||
const out_app_path = path.join(out_path_base, 'app.js');
|
||||
if (helper && helper.appWriter) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// writes helpers require for vnc.html (they should output app.js)
|
||||
var fs = require('fs');
|
||||
var fse = require('fs-extra');
|
||||
var path = require('path');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
'amd': {
|
||||
|
|
@ -19,8 +18,8 @@ module.exports = {
|
|||
opts.plugins.unshift("add-module-exports");
|
||||
},
|
||||
appWriter: (base_out_path, out_path) => {
|
||||
var browserify = require('browserify');
|
||||
var b = browserify(path.join(base_out_path, 'app/ui.js'), {});
|
||||
const browserify = require('browserify');
|
||||
const b = browserify(path.join(base_out_path, 'app/ui.js'), {});
|
||||
b.bundle().pipe(fs.createWriteStream(out_path));
|
||||
return `<script src="${path.relative(base_out_path, out_path)}"></script>`;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ function longest_match(s, cur_match) {
|
|||
* the 256th check will be made at strstart+258.
|
||||
*/
|
||||
do {
|
||||
/*jshint noempty:false*/
|
||||
// Do nothing
|
||||
} while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
||||
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
||||
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
||||
|
|
@ -892,7 +892,7 @@ function deflate_rle(s, flush) {
|
|||
if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
|
||||
strend = s.strstart + MAX_MATCH;
|
||||
do {
|
||||
/*jshint noempty:false*/
|
||||
// Do nothing
|
||||
} while (prev === _win[++scan] && prev === _win[++scan] &&
|
||||
prev === _win[++scan] && prev === _win[++scan] &&
|
||||
prev === _win[++scan] && prev === _win[++scan] &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue