jsynchronous 0.9.5 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/jsynchronous-client.d.ts +40 -0
- package/jsynchronous-client.js +35 -17
- package/jsynchronous.d.ts +41 -0
- package/jsynchronous.js +44 -21
- package/package.json +1 -1
- package/tests/selenium/test.js +1 -1
package/README.md
CHANGED
|
@@ -257,7 +257,7 @@ $orientation.i = 0; // Will synchronize
|
|
|
257
257
|
$orientation.j = 1; // Will synchronize
|
|
258
258
|
```
|
|
259
259
|
|
|
260
|
-
We recommended you use the prefix ‘$’ or some other convention when you reference a synchronized variable to indicate that assignments to that variable will be sent over the network.
|
|
260
|
+
We recommended you use the prefix ‘$’ or some other convention when you reference a synchronized variable to indicate that the variable is reactive and assignments to that variable will be sent over the network.
|
|
261
261
|
|
|
262
262
|
# Documentation Reference
|
|
263
263
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
type Stand_In = 'object' | 'array';
|
|
2
|
+
type Event = 'changes' | 'snapshot';
|
|
3
|
+
type Event_Changes_Callback = (data: any) => void;
|
|
4
|
+
|
|
5
|
+
export type Synchronized_Variable<Variable_Type> = Variable_Type & {
|
|
6
|
+
$on: (event: Event, callback: Event_Changes_Callback) => void;
|
|
7
|
+
$info: () => {
|
|
8
|
+
client_history: boolean
|
|
9
|
+
counter: number
|
|
10
|
+
handshake: true
|
|
11
|
+
history_length: number
|
|
12
|
+
name: string
|
|
13
|
+
one_way: boolean
|
|
14
|
+
resyncs : number
|
|
15
|
+
rewind : boolean
|
|
16
|
+
rewound : boolean
|
|
17
|
+
snapshots : string[]
|
|
18
|
+
standIn : boolean
|
|
19
|
+
};
|
|
20
|
+
$tart: () => void;
|
|
21
|
+
$listeners: () => any[];
|
|
22
|
+
$napshot: (name: string) => void;
|
|
23
|
+
$rewind: (name: string, counter?: number) => void;
|
|
24
|
+
list: () => string[];
|
|
25
|
+
variables: () => { [key]: string, value: Synchronized_Variable<Variable_Type> };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare function jsynchronous<Variable_Type>(standInType: Stand_In, name?: string): Synchronized_Variable<Variable_Type>;
|
|
29
|
+
|
|
30
|
+
declare namespace jsynchronous {
|
|
31
|
+
export let send: (websocket: any, data: any) => void;
|
|
32
|
+
export const onmessage: (data: any) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default jsynchronous;
|
|
36
|
+
|
|
37
|
+
// export interface jsynchronous {
|
|
38
|
+
// <Synchronized_Variable>(standInType: Stand_In, name: string) => Synchronized_Type;
|
|
39
|
+
// send: (data: any) => void;
|
|
40
|
+
// }
|
package/jsynchronous-client.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
var jsynchronous;
|
|
2
2
|
|
|
3
3
|
function jsynchronousSetup() {
|
|
4
|
+
var ENCODE = false;
|
|
5
|
+
|
|
4
6
|
var TYPE_ENCODINGS = [
|
|
5
7
|
'array',
|
|
6
8
|
'object',
|
|
@@ -11,7 +13,8 @@ function jsynchronousSetup() {
|
|
|
11
13
|
'null',
|
|
12
14
|
'empty',
|
|
13
15
|
'bigint',
|
|
14
|
-
'function'
|
|
16
|
+
'function',
|
|
17
|
+
'date'
|
|
15
18
|
]
|
|
16
19
|
|
|
17
20
|
var OP_ENCODINGS = [
|
|
@@ -40,7 +43,7 @@ function jsynchronousSetup() {
|
|
|
40
43
|
|
|
41
44
|
function onmessage(data) {
|
|
42
45
|
var json = JSON.parse(data);
|
|
43
|
-
var op =
|
|
46
|
+
var op = decodeOp(json[0]);
|
|
44
47
|
var name = json[1];
|
|
45
48
|
|
|
46
49
|
if (op === 'initial') {
|
|
@@ -62,7 +65,7 @@ function jsynchronousSetup() {
|
|
|
62
65
|
if (jsynchronous.send) {
|
|
63
66
|
var uniqueId = 'initial' + name;
|
|
64
67
|
communicateWithBackoff(uniqueId, ['initial', name], function () {
|
|
65
|
-
console.
|
|
68
|
+
console.warn('Unknown jsynchronous variable, requesting initial' + name);
|
|
66
69
|
return jsyncs[name] === undefined;
|
|
67
70
|
}, 2000);
|
|
68
71
|
} else {
|
|
@@ -140,7 +143,7 @@ function jsynchronousSetup() {
|
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
function newJsynchronous(name, counter, settings, data) {
|
|
143
|
-
var rootType =
|
|
146
|
+
var rootType = decodeType(data[0][1]);
|
|
144
147
|
var jsync = jsyncObject(name, counter, settings);
|
|
145
148
|
var reserved;
|
|
146
149
|
if (settings) reserved = settings.reserved;
|
|
@@ -152,7 +155,7 @@ function jsynchronousSetup() {
|
|
|
152
155
|
for (var i=0; i<data.length; i++) {
|
|
153
156
|
var d = data[i];
|
|
154
157
|
var hash = d[0];
|
|
155
|
-
var type =
|
|
158
|
+
var type = decodeType(d[1]);
|
|
156
159
|
var each = d[2];
|
|
157
160
|
var description = createSyncedVariable(hash, type, each, jsync, (i === 0));
|
|
158
161
|
|
|
@@ -249,9 +252,6 @@ function jsynchronousSetup() {
|
|
|
249
252
|
hash: hash,
|
|
250
253
|
type: type,
|
|
251
254
|
variable: undefined,
|
|
252
|
-
descendants: {}, // key->value corresponds to descendant.hash->[properties]. Follow properties to find descendant
|
|
253
|
-
parents: {}, // key->value corresponds to parentHash->{details: parent, props: []}
|
|
254
|
-
children: {} // key->value corresponds to childHash->{details: child, props: []}
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
if (existing && detailedType(existing.variable) === type) {
|
|
@@ -266,7 +266,7 @@ function jsynchronousSetup() {
|
|
|
266
266
|
jsync.objects[hash] = details;
|
|
267
267
|
|
|
268
268
|
enumerate(each, type, function (prop, encoded) {
|
|
269
|
-
var t =
|
|
269
|
+
var t = decodeType(encoded[0])
|
|
270
270
|
var v = encoded[1];
|
|
271
271
|
|
|
272
272
|
if (isPrimitive(t)) {
|
|
@@ -320,7 +320,7 @@ function jsynchronousSetup() {
|
|
|
320
320
|
|
|
321
321
|
if (change === null) { continue }
|
|
322
322
|
|
|
323
|
-
var op =
|
|
323
|
+
var op = decodeOp(change[0]);
|
|
324
324
|
var hash = change[1];
|
|
325
325
|
var details;
|
|
326
326
|
var pt;
|
|
@@ -347,7 +347,7 @@ function jsynchronousSetup() {
|
|
|
347
347
|
} else if (op === 'new') {
|
|
348
348
|
var type = change[2];
|
|
349
349
|
var each = change[3];
|
|
350
|
-
createSyncedVariable(hash,
|
|
350
|
+
createSyncedVariable(hash, decodeType(type), each, jsync);
|
|
351
351
|
} else if (op === 'end') {
|
|
352
352
|
endObject(details, jsync);
|
|
353
353
|
} else if (op === 'snapshot') {
|
|
@@ -389,7 +389,7 @@ function jsynchronousSetup() {
|
|
|
389
389
|
}
|
|
390
390
|
function set(details, prop, newDetails, oldDetails, jsync) {
|
|
391
391
|
var object = details.variable;
|
|
392
|
-
var type =
|
|
392
|
+
var type = decodeType(newDetails[0]);
|
|
393
393
|
var value;
|
|
394
394
|
|
|
395
395
|
if (isPrimitive(type)) {
|
|
@@ -400,7 +400,7 @@ function jsynchronousSetup() {
|
|
|
400
400
|
value = childDetails.variable;
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
var oldType =
|
|
403
|
+
var oldType = decodeType(oldDetails[0]);
|
|
404
404
|
var oldValue;
|
|
405
405
|
|
|
406
406
|
if (isPrimitive(oldType)) {
|
|
@@ -414,7 +414,7 @@ function jsynchronousSetup() {
|
|
|
414
414
|
}
|
|
415
415
|
function del(details, prop, oldDetails, jsync) {
|
|
416
416
|
var object = details.variable;
|
|
417
|
-
var oldType =
|
|
417
|
+
var oldType = decodeType(oldDetails[0]);
|
|
418
418
|
var oldValue = oldDetails[1];
|
|
419
419
|
|
|
420
420
|
if (isPrimitive(oldType)) {
|
|
@@ -557,6 +557,8 @@ function jsynchronousSetup() {
|
|
|
557
557
|
return null;
|
|
558
558
|
} else if (type === 'function') {
|
|
559
559
|
return undefined; // Functions are, for now, read-only
|
|
560
|
+
} else if (type === 'date') {
|
|
561
|
+
return new Date(value);
|
|
560
562
|
}
|
|
561
563
|
}
|
|
562
564
|
function detailedType(value) {
|
|
@@ -596,7 +598,8 @@ function jsynchronousSetup() {
|
|
|
596
598
|
type === 'null' ||
|
|
597
599
|
type === 'empty' ||
|
|
598
600
|
type === 'bigint' ||
|
|
599
|
-
type === 'function'
|
|
601
|
+
type === 'function' || // Functions are, for now, read-only
|
|
602
|
+
type === 'date') {
|
|
600
603
|
return true
|
|
601
604
|
} else {
|
|
602
605
|
return false
|
|
@@ -662,6 +665,21 @@ function jsynchronousSetup() {
|
|
|
662
665
|
return mirror;
|
|
663
666
|
}
|
|
664
667
|
}
|
|
668
|
+
function decodeOp(number) {
|
|
669
|
+
if (ENCODE) {
|
|
670
|
+
return OP_ENCODINGS[number]
|
|
671
|
+
} else {
|
|
672
|
+
return number
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
function decodeType(number) {
|
|
676
|
+
if (ENCODE) {
|
|
677
|
+
return TYPE_ENCODINGS[number];
|
|
678
|
+
} else {
|
|
679
|
+
return number;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
665
683
|
|
|
666
684
|
|
|
667
685
|
function addSynchronizedVariableMethods(jsync, targetVariable, reservedWords) {
|
|
@@ -749,7 +767,7 @@ function jsynchronousSetup() {
|
|
|
749
767
|
});
|
|
750
768
|
}
|
|
751
769
|
}
|
|
752
|
-
function triggerChanges(jsync
|
|
770
|
+
function triggerChanges(jsync) {
|
|
753
771
|
for (var j=0; j<jsync.changesEvents.length; j++) {
|
|
754
772
|
var e = jsync.changesEvents[j];
|
|
755
773
|
var variable = jsync.root.variable;
|
|
@@ -762,7 +780,7 @@ function jsynchronousSetup() {
|
|
|
762
780
|
// ----------------------------------------------------------------
|
|
763
781
|
function communicate(op, a, b, c, d) {
|
|
764
782
|
var payload = []
|
|
765
|
-
payload.push(OP_ENCODINGS.indexOf(op));
|
|
783
|
+
payload.push(ENCODE ? OP_ENCODINGS.indexOf(op) : op);
|
|
766
784
|
if (a !== undefined) payload.push(a);
|
|
767
785
|
if (b !== undefined) payload.push(b);
|
|
768
786
|
if (c !== undefined) payload.push(c);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
type Event_Changes_Callback = (data: any) => void;
|
|
2
|
+
|
|
3
|
+
export type Synchronized_Variable<Variable_Type> = Variable_Type & {
|
|
4
|
+
$on: (event: Event, callback: Event_Changes_Callback) => void;
|
|
5
|
+
$ync: (websocket: any) => void;
|
|
6
|
+
$unsync: (websocket: any) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type JysnchronousOptions = {
|
|
10
|
+
rewind?: boolean;
|
|
11
|
+
one_way?: boolean;
|
|
12
|
+
send?: (websocket: any, data: any) => void;
|
|
13
|
+
buffer_time?: number;
|
|
14
|
+
client_history?: number;
|
|
15
|
+
history_limit?: number;
|
|
16
|
+
wait?: boolean;
|
|
17
|
+
$ync?: string;
|
|
18
|
+
$unsync?: string;
|
|
19
|
+
$on?: string;
|
|
20
|
+
$tart?: string;
|
|
21
|
+
$listeners?: string;
|
|
22
|
+
$info?: string;
|
|
23
|
+
$napshot?: string;
|
|
24
|
+
$rewind?: string;
|
|
25
|
+
$copy?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type Jsynchronous = {
|
|
29
|
+
<Variable_Type>(initialVariable: Variable_Type, name?: string, options?: JsynchronousOptions): Synchronized_Variable<Variable_Type>;
|
|
30
|
+
send: (websocket: any, data: any) => void;
|
|
31
|
+
onmessage: (websocket: any, data: any) => void;
|
|
32
|
+
list: () => string[];
|
|
33
|
+
variables: () => { [key: string]: Synchronized_Variable<Variable_Type> };
|
|
34
|
+
pausegc: () => void;
|
|
35
|
+
resumegc: () => void;
|
|
36
|
+
rungc: () => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare const jsynchronous: Jsynchronous;
|
|
40
|
+
|
|
41
|
+
export default jsynchronous;
|
package/jsynchronous.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const ENCODE = false;
|
|
4
|
+
|
|
3
5
|
const TYPE_ENCODINGS = {
|
|
4
6
|
'array': 0,
|
|
5
7
|
'object': 1,
|
|
@@ -10,7 +12,8 @@ const TYPE_ENCODINGS = {
|
|
|
10
12
|
'null': 6,
|
|
11
13
|
'empty': 7,
|
|
12
14
|
'bigint': 8,
|
|
13
|
-
'function': 9
|
|
15
|
+
'function': 9,
|
|
16
|
+
'date': 10
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
const OP_ENCODINGS = {
|
|
@@ -60,7 +63,7 @@ class Change {
|
|
|
60
63
|
}
|
|
61
64
|
encode() {
|
|
62
65
|
const change = [
|
|
63
|
-
|
|
66
|
+
encodeOp(this.operation),
|
|
64
67
|
this.hash,
|
|
65
68
|
this.prop,
|
|
66
69
|
encode(this.value, this.type),
|
|
@@ -82,7 +85,7 @@ class Creation {
|
|
|
82
85
|
}
|
|
83
86
|
encode() {
|
|
84
87
|
const creation = [
|
|
85
|
-
|
|
88
|
+
encodeOp(this.operation),
|
|
86
89
|
this.description[0],
|
|
87
90
|
this.description[1],
|
|
88
91
|
this.description[2]
|
|
@@ -106,7 +109,7 @@ class Deletion {
|
|
|
106
109
|
}
|
|
107
110
|
encode() {
|
|
108
111
|
const deletion = [
|
|
109
|
-
|
|
112
|
+
encodeOp(this.operation),
|
|
110
113
|
this.hash
|
|
111
114
|
]
|
|
112
115
|
return deletion;
|
|
@@ -132,7 +135,7 @@ class Snapshot {
|
|
|
132
135
|
}
|
|
133
136
|
encode() {
|
|
134
137
|
const snapshot = [
|
|
135
|
-
|
|
138
|
+
encodeOp(this.operation),
|
|
136
139
|
this.id,
|
|
137
140
|
this.name
|
|
138
141
|
]
|
|
@@ -272,7 +275,7 @@ class SyncedObject {
|
|
|
272
275
|
describe() {
|
|
273
276
|
const state = [
|
|
274
277
|
this.hash,
|
|
275
|
-
|
|
278
|
+
encodeOp(this.type),
|
|
276
279
|
newCollection(this.type, this.proxy)
|
|
277
280
|
]
|
|
278
281
|
|
|
@@ -435,7 +438,7 @@ class JSynchronous {
|
|
|
435
438
|
}
|
|
436
439
|
|
|
437
440
|
for (let [websocket, listener] of this.listeners) {
|
|
438
|
-
this.send(websocket, JSON.stringify([
|
|
441
|
+
this.send(websocket, JSON.stringify([encodeOp('changes'), this.name, min, max, changes]));
|
|
439
442
|
}
|
|
440
443
|
|
|
441
444
|
// Now that it's sent, the rest is history
|
|
@@ -470,7 +473,7 @@ class JSynchronous {
|
|
|
470
473
|
return c.encode();
|
|
471
474
|
});
|
|
472
475
|
|
|
473
|
-
this.send(websocket, JSON.stringify([
|
|
476
|
+
this.send(websocket, JSON.stringify([encodeOp('changes'), this.name, min, max, changes]));
|
|
474
477
|
}
|
|
475
478
|
}
|
|
476
479
|
}
|
|
@@ -557,7 +560,7 @@ class JSynchronous {
|
|
|
557
560
|
} catch (e) {
|
|
558
561
|
listener.penalty += 5; // Penalize clients heavily if they trigger errors
|
|
559
562
|
console.error("Jsynchronous client->server onmessage error", e);
|
|
560
|
-
jsynchronous.send(websocket, JSON.stringify([
|
|
563
|
+
jsynchronous.send(websocket, JSON.stringify([encodeOp('error'), e.toString()]));
|
|
561
564
|
}
|
|
562
565
|
}
|
|
563
566
|
handshake(websocket, listener, rootHash) {
|
|
@@ -567,7 +570,7 @@ class JSynchronous {
|
|
|
567
570
|
|
|
568
571
|
let secret = listener.secret || randomHash(); // no need to worry about collisions. Secrets aren't shared.
|
|
569
572
|
listener.secret = secret;
|
|
570
|
-
this.send(websocket, JSON.stringify([
|
|
573
|
+
this.send(websocket, JSON.stringify([encodeOp('handshake'), this.name, secret]));
|
|
571
574
|
}
|
|
572
575
|
resync(websocket, listener, json) {
|
|
573
576
|
let secret = json[2];
|
|
@@ -578,17 +581,17 @@ class JSynchronous {
|
|
|
578
581
|
let historyMax = historyMin + (max-min);
|
|
579
582
|
if (historyMin === -1 || historyMax >= this.history.length) {
|
|
580
583
|
// TODO: Hard reset on client
|
|
581
|
-
let payload = [
|
|
584
|
+
let payload = [encodeOp('error'), 'Unable to resync'];
|
|
582
585
|
jsynchronous.send(websocket, JSON.stringify(payload));
|
|
583
586
|
} else {
|
|
584
587
|
let slice = this.history.slice(historyMin, historyMax);
|
|
585
588
|
let encoded = slice.map((h) => h.encode());
|
|
586
|
-
let payload = [
|
|
589
|
+
let payload = [encodeOp('changes'), this.name, min, max-1, encoded];
|
|
587
590
|
this.send(websocket, JSON.stringify(payload));
|
|
588
591
|
}
|
|
589
592
|
} else {
|
|
590
593
|
// TODO: Tear this out, we don't need to be polite to clients that fail the secret check
|
|
591
|
-
let payload = [
|
|
594
|
+
let payload = [encodeOp('error'), 'Secret check failed'];
|
|
592
595
|
jsynchronous.send(websocket, JSON.stringify(payload));
|
|
593
596
|
}
|
|
594
597
|
}
|
|
@@ -712,7 +715,7 @@ class JSynchronous {
|
|
|
712
715
|
}
|
|
713
716
|
|
|
714
717
|
const fullState = [
|
|
715
|
-
|
|
718
|
+
encodeOp('initial'),
|
|
716
719
|
this.name,
|
|
717
720
|
this.counter,
|
|
718
721
|
settings
|
|
@@ -880,7 +883,8 @@ function isPrimitive(detailed) {
|
|
|
880
883
|
detailed === 'bigint' ||
|
|
881
884
|
detailed === 'null' || // Although null is in ECMA an object, we'll consider it a primitive for simplicity
|
|
882
885
|
detailed === 'undefined' ||
|
|
883
|
-
detailed === 'function'
|
|
886
|
+
detailed === 'function' || // For now, functions are just values as far as jsynchronous is concerned
|
|
887
|
+
detailed === 'date') {
|
|
884
888
|
return true;
|
|
885
889
|
} else {
|
|
886
890
|
return false;
|
|
@@ -1020,15 +1024,15 @@ function labelEmpty(source, target) {
|
|
|
1020
1024
|
if (value === undefined) {
|
|
1021
1025
|
allKeys = allKeys || Object.keys(source).map(k => Number(k));
|
|
1022
1026
|
if (binarySearch(allKeys, ((a) => a - i)) === -1) {
|
|
1023
|
-
target[i] = [
|
|
1027
|
+
target[i] = [encodeOp('empty')];
|
|
1024
1028
|
}
|
|
1025
1029
|
}
|
|
1026
1030
|
}
|
|
1027
1031
|
}
|
|
1028
1032
|
|
|
1029
1033
|
function encode(value, type) {
|
|
1030
|
-
// Expects value to be either be a primitive or a syncedObject Proxy
|
|
1031
|
-
const encoded = [
|
|
1034
|
+
// Expects value to be either be a primitive, a date or a syncedObject Proxy
|
|
1035
|
+
const encoded = [encodeOp(type)];
|
|
1032
1036
|
|
|
1033
1037
|
if (isPrimitive(type)) {
|
|
1034
1038
|
const p = encodePrimitive(value, type)
|
|
@@ -1051,6 +1055,7 @@ function encodePrimitive(value, type) {
|
|
|
1051
1055
|
if (type === 'boolean') return !!value ? 1 : 0;
|
|
1052
1056
|
if (type === 'bigint') return String(value);
|
|
1053
1057
|
if (type === 'function') return undefined;
|
|
1058
|
+
if (type === 'date') return value.getTime();
|
|
1054
1059
|
throw `Jsynchronous sanity error - Primitive is unserializable ${type}, ${value}`;
|
|
1055
1060
|
}
|
|
1056
1061
|
function encodeEnumerable(value) {
|
|
@@ -1061,8 +1066,26 @@ function encodeEnumerable(value) {
|
|
|
1061
1066
|
return syncedObject.hash;
|
|
1062
1067
|
}
|
|
1063
1068
|
function getOp(number) {
|
|
1064
|
-
|
|
1065
|
-
|
|
1069
|
+
if (ENCODE) {
|
|
1070
|
+
for (const [key, value] of Object.entries(OP_ENCODINGS)) {
|
|
1071
|
+
if (value === number) return key;
|
|
1072
|
+
}
|
|
1073
|
+
return false;
|
|
1074
|
+
} else {
|
|
1075
|
+
return number;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
function encodeType(type) {
|
|
1079
|
+
if (encode) {
|
|
1080
|
+
return TYPE_ENCODINGS[type];
|
|
1081
|
+
} else {
|
|
1082
|
+
return type;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
function encodeOp(op) {
|
|
1086
|
+
if (ENCODE) {
|
|
1087
|
+
return OP_ENCODINGS[op];
|
|
1088
|
+
} else {
|
|
1089
|
+
return op;
|
|
1066
1090
|
}
|
|
1067
|
-
return false;
|
|
1068
1091
|
}
|
package/package.json
CHANGED
package/tests/selenium/test.js
CHANGED
|
@@ -67,7 +67,7 @@ app.get('/jsynchronous-client.js', (req, res) => {
|
|
|
67
67
|
// ----------------------------------------------------------------
|
|
68
68
|
// Selenium Test
|
|
69
69
|
// ----------------------------------------------------------------
|
|
70
|
-
const browsers = ['firefox'
|
|
70
|
+
const browsers = ['firefox'];
|
|
71
71
|
let drivers = [];
|
|
72
72
|
const runTests = (async () => {
|
|
73
73
|
drivers = await Promise.all(browsers.map((browser) => new Builder().forBrowser(browser).build()));
|