@qooxdoo/framework 7.7.2 → 7.9.0
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/Manifest.json +2 -2
- package/lib/compiler/compile-info.json +91 -89
- package/lib/compiler/index.js +2517 -1488
- package/lib/resource/qx/tool/schema/compile-1-0-0.json +13 -0
- package/lib/resource/qx/tool/website/build/404.html +3 -25
- package/lib/resource/qx/tool/website/build/about.html +3 -25
- package/lib/resource/qx/tool/website/build/assets/common.js +20 -0
- package/lib/resource/qx/tool/website/build/diagnostics/dependson.html +3 -25
- package/lib/resource/qx/tool/website/build/diagnostics/requiredby.html +3 -22
- package/lib/resource/qx/tool/website/build/index.html +3 -25
- package/lib/resource/qx/tool/website/partials/footer.html +3 -21
- package/lib/resource/qx/tool/website/partials/head.html +0 -1
- package/package.json +2 -2
- package/source/class/qx/Bootstrap.js +6 -3
- package/source/class/qx/Promise.js +93 -6964
- package/source/class/qx/bom/Label.js +82 -2
- package/source/class/qx/bom/webfonts/WebFont.js +1 -0
- package/source/class/qx/core/Environment.js +83 -1
- package/source/class/qx/data/controller/List.js +50 -21
- package/source/class/qx/data/controller/MSelection.js +45 -12
- package/source/class/qx/data/marshal/Json.js +64 -11
- package/source/class/qx/dev/unit/AsyncWrapper.js +8 -0
- package/source/class/qx/event/Manager.js +163 -124
- package/source/class/qx/io/ImageLoader.js +6 -3
- package/source/class/qx/io/exception/Transport.js +1 -0
- package/source/class/qx/io/jsonrpc/Client.js +64 -8
- package/source/class/qx/io/jsonrpc/protocol/Request.js +10 -6
- package/source/class/qx/lang/Type.js +36 -3
- package/source/class/qx/promise/BluebirdImpl.js +6918 -0
- package/source/class/qx/promise/NativeWrapper.js +738 -0
- package/source/class/qx/test/Promise.js +1145 -22
- package/source/class/qx/test/bom/client/Pdfjs.js +4 -0
- package/source/class/qx/test/bom/element/AnimationJs.js +3 -0
- package/source/class/qx/test/bom/element/Style.js +1 -0
- package/source/class/qx/test/bom/media/MediaTestCase.js +6 -0
- package/source/class/qx/test/core/Environment.js +44 -0
- package/source/class/qx/test/data/controller/List.js +6 -0
- package/source/class/qx/test/data/marshal/Json.js +29 -0
- package/source/class/qx/test/io/MAssert.js +94 -0
- package/source/class/qx/test/io/TestMAssert.js +47 -0
- package/source/class/qx/test/io/jsonrpc/Client.js +79 -19
- package/source/class/qx/test/io/jsonrpc/PostMessageClient.js +152 -0
- package/source/class/qx/test/io/jsonrpc/Protocol.js +1 -5
- package/source/class/qx/test/io/request/Xhr.js +16 -0
- package/source/class/qx/test/lang/Type.js +151 -0
- package/source/class/qx/test/ui/embed/Iframe.js +1 -1
- package/source/class/qx/test/ui/form/TextArea.js +4 -0
- package/source/class/qx/test/util/DeferredCall.js +6 -0
- package/source/class/qx/test/util/Function.js +2 -2
- package/source/class/qx/theme/indigo/ColorDark.js +1 -1
- package/source/class/qx/tool/cli/api/Test.js +22 -0
- package/source/class/qx/tool/cli/commands/Compile.js +17 -4
- package/source/class/qx/tool/cli/commands/Test.js +7 -1
- package/source/class/qx/tool/compiler/Analyser.js +7 -0
- package/source/class/qx/tool/compiler/ClassFile.js +3 -2
- package/source/class/qx/tool/compiler/MetaExtraction.js +0 -5
- package/source/class/qx/tool/compiler/targets/meta/Browserify.js +8 -2
- package/source/class/qx/ui/basic/Image.js +72 -8
- package/source/class/qx/ui/basic/Label.js +4 -6
- package/source/class/qx/ui/control/DateChooser.js +4 -6
- package/source/class/qx/ui/core/Blocker.js +4 -6
- package/source/class/qx/ui/core/LayoutItem.js +4 -6
- package/source/class/qx/ui/core/MPlacement.js +23 -1
- package/source/class/qx/ui/core/Widget.js +7 -5
- package/source/class/qx/ui/form/AbstractField.js +4 -6
- package/source/class/qx/ui/form/MForm.js +4 -6
- package/source/class/qx/ui/form/Spinner.js +4 -6
- package/source/class/qx/ui/form/renderer/AbstractRenderer.js +4 -6
- package/source/class/qx/ui/menu/AbstractButton.js +7 -11
- package/source/class/qx/ui/mobile/basic/Label.js +4 -6
- package/source/class/qx/ui/mobile/form/Label.js +4 -6
- package/source/class/qx/ui/mobile/list/List.js +4 -6
- package/source/class/qx/ui/progressive/renderer/table/Row.js +35 -7
- package/source/class/qx/ui/progressive/renderer/table/cell/Boolean.js +4 -6
- package/source/class/qx/ui/table/Table.js +4 -6
- package/source/class/qx/ui/table/cellrenderer/Abstract.js +4 -6
- package/source/class/qx/ui/table/cellrenderer/Boolean.js +4 -6
- package/source/class/qx/ui/table/pane/Scroller.js +1 -1
- package/source/class/qx/ui/table/rowrenderer/Default.js +4 -6
- package/source/class/qx/util/ConcurrencyLimiter.js +78 -0
- package/source/resource/qx/tool/schema/compile-1-0-0.json +13 -0
- package/source/resource/qx/tool/website/build/404.html +3 -25
- package/source/resource/qx/tool/website/build/about.html +3 -25
- package/source/resource/qx/tool/website/build/assets/common.js +20 -0
- package/source/resource/qx/tool/website/build/diagnostics/dependson.html +3 -25
- package/source/resource/qx/tool/website/build/diagnostics/requiredby.html +3 -22
- package/source/resource/qx/tool/website/build/index.html +3 -25
- package/source/resource/qx/tool/website/partials/footer.html +3 -21
- package/source/resource/qx/tool/website/partials/head.html +0 -1
- package/lib/resource/qx/tool/website/build/assets/bluebird.min.js +0 -4615
- package/lib/resource/qx/tool/website/src/assets/bluebird.min.js +0 -4615
- package/source/resource/qx/tool/website/build/assets/bluebird.min.js +0 -4615
- package/source/resource/qx/tool/website/src/assets/bluebird.min.js +0 -4615
|
@@ -66,7 +66,7 @@ qx.Class.define("qx.event.Manager", {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// Registry for event listeners
|
|
69
|
-
this.__listeners =
|
|
69
|
+
this.__listeners = new Map();
|
|
70
70
|
|
|
71
71
|
// The handler and dispatcher instances
|
|
72
72
|
this.__handlers = {};
|
|
@@ -264,18 +264,41 @@ qx.Class.define("qx.event.Manager", {
|
|
|
264
264
|
* null when no listener were found.
|
|
265
265
|
*/
|
|
266
266
|
getListeners(target, type, capture) {
|
|
267
|
-
var targetKey =
|
|
268
|
-
|
|
269
|
-
var targetMap = this.__listeners[targetKey];
|
|
267
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
268
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
270
269
|
|
|
271
270
|
if (!targetMap) {
|
|
272
271
|
return null;
|
|
273
272
|
}
|
|
274
273
|
|
|
275
274
|
var entryKey = type + (capture ? "|capture" : "|bubble");
|
|
276
|
-
var
|
|
277
|
-
|
|
278
|
-
|
|
275
|
+
var entryMap = targetMap.get(entryKey);
|
|
276
|
+
|
|
277
|
+
if (entryMap && entryMap.size > 0) {
|
|
278
|
+
var listeners = [...entryMap.values()];
|
|
279
|
+
|
|
280
|
+
return new Proxy(listeners, {
|
|
281
|
+
deleteProperty(target, property) {
|
|
282
|
+
if (property !== "length") {
|
|
283
|
+
var listener = target[property];
|
|
284
|
+
entryMap.delete(listener.unique);
|
|
285
|
+
}
|
|
286
|
+
delete target[property];
|
|
287
|
+
return true;
|
|
288
|
+
},
|
|
289
|
+
set(target, property, value, receiver) {
|
|
290
|
+
if (property !== "length") {
|
|
291
|
+
if (!value.unique) {
|
|
292
|
+
throw new Error("Cannot store a listener without a unique id. Use addListener()");
|
|
293
|
+
}
|
|
294
|
+
entryMap[value.unique] = value;
|
|
295
|
+
}
|
|
296
|
+
target[property] = value;
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
return null;
|
|
279
302
|
},
|
|
280
303
|
|
|
281
304
|
/**
|
|
@@ -283,10 +306,41 @@ qx.Class.define("qx.event.Manager", {
|
|
|
283
306
|
*
|
|
284
307
|
* @internal
|
|
285
308
|
*
|
|
286
|
-
* @return {
|
|
309
|
+
* @return {Object} All registered listeners. The key is the hash code for an object.
|
|
287
310
|
*/
|
|
288
311
|
getAllListeners() {
|
|
289
|
-
return
|
|
312
|
+
return Object.fromEntries(
|
|
313
|
+
this.__listeners.entries().map(
|
|
314
|
+
([targetKey, targetMap]) => [targetKey, Object.fromEntries(
|
|
315
|
+
targetMap.entries().map(
|
|
316
|
+
([entryKey, entryMap]) => {
|
|
317
|
+
var listeners = [...entryMap.values()];
|
|
318
|
+
var proxy = new Proxy(listeners, {
|
|
319
|
+
deleteProperty(target, property) {
|
|
320
|
+
if (property !== "length") {
|
|
321
|
+
var listener = target[property];
|
|
322
|
+
entryMap.delete(listener.unique);
|
|
323
|
+
}
|
|
324
|
+
delete target[property];
|
|
325
|
+
return true;
|
|
326
|
+
},
|
|
327
|
+
set(target, property, value, receiver) {
|
|
328
|
+
if (property !== "length") {
|
|
329
|
+
if (!value.unique) {
|
|
330
|
+
throw new Error("Cannot store a listener without a unique id. Use addListener()");
|
|
331
|
+
}
|
|
332
|
+
entryMap[value.unique] = value;
|
|
333
|
+
}
|
|
334
|
+
target[property] = value;
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
return [entryKey, proxy];
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
)]
|
|
342
|
+
)
|
|
343
|
+
);
|
|
290
344
|
},
|
|
291
345
|
|
|
292
346
|
/**
|
|
@@ -297,28 +351,25 @@ qx.Class.define("qx.event.Manager", {
|
|
|
297
351
|
* <code>handler</code>, <code>self</code>, <code>type</code> and <code>capture</code>.
|
|
298
352
|
*/
|
|
299
353
|
serializeListeners(target) {
|
|
300
|
-
var targetKey =
|
|
301
|
-
|
|
302
|
-
var targetMap = this.__listeners[targetKey];
|
|
354
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
355
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
303
356
|
var result = [];
|
|
304
357
|
|
|
305
358
|
if (targetMap) {
|
|
306
|
-
var indexOf, type, capture
|
|
307
|
-
for (
|
|
359
|
+
var indexOf, type, capture;
|
|
360
|
+
for (const [entryKey, entryMap] of targetMap) {
|
|
308
361
|
indexOf = entryKey.indexOf("|");
|
|
309
362
|
type = entryKey.substring(0, indexOf);
|
|
310
|
-
capture = entryKey.charAt(indexOf + 1)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
});
|
|
321
|
-
}
|
|
363
|
+
capture = entryKey.charAt(indexOf + 1) === "c";
|
|
364
|
+
result = result.concat(
|
|
365
|
+
[...entryMap.values().map(entry => ({
|
|
366
|
+
self: entry.context,
|
|
367
|
+
handler: entry.handler,
|
|
368
|
+
type: type,
|
|
369
|
+
capture: capture
|
|
370
|
+
})
|
|
371
|
+
)]
|
|
372
|
+
);
|
|
322
373
|
}
|
|
323
374
|
}
|
|
324
375
|
|
|
@@ -339,17 +390,15 @@ qx.Class.define("qx.event.Manager", {
|
|
|
339
390
|
* @param enable {Boolean} Whether to enable or disable the events
|
|
340
391
|
*/
|
|
341
392
|
toggleAttachedEvents(target, enable) {
|
|
342
|
-
var targetKey =
|
|
343
|
-
|
|
344
|
-
var targetMap = this.__listeners[targetKey];
|
|
393
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
394
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
345
395
|
|
|
346
396
|
if (targetMap) {
|
|
347
|
-
var indexOf, type, capture
|
|
348
|
-
for (
|
|
397
|
+
var indexOf, type, capture;
|
|
398
|
+
for (const entryKey of targetMap.keys()) {
|
|
349
399
|
indexOf = entryKey.indexOf("|");
|
|
350
400
|
type = entryKey.substring(0, indexOf);
|
|
351
401
|
capture = entryKey.charCodeAt(indexOf + 1) === 99; // checking for character "c".
|
|
352
|
-
entryList = targetMap[entryKey];
|
|
353
402
|
|
|
354
403
|
if (enable) {
|
|
355
404
|
this.__registerAtHandler(target, type, capture);
|
|
@@ -378,18 +427,17 @@ qx.Class.define("qx.event.Manager", {
|
|
|
378
427
|
}
|
|
379
428
|
}
|
|
380
429
|
|
|
381
|
-
var targetKey =
|
|
382
|
-
|
|
383
|
-
var targetMap = this.__listeners[targetKey];
|
|
430
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
431
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
384
432
|
|
|
385
433
|
if (!targetMap) {
|
|
386
434
|
return false;
|
|
387
435
|
}
|
|
388
436
|
|
|
389
437
|
var entryKey = type + (capture ? "|capture" : "|bubble");
|
|
390
|
-
var
|
|
438
|
+
var entryMap = targetMap.get(entryKey);
|
|
391
439
|
|
|
392
|
-
return
|
|
440
|
+
return Boolean(entryMap && entryMap.size > 0);
|
|
393
441
|
},
|
|
394
442
|
|
|
395
443
|
/**
|
|
@@ -415,32 +463,40 @@ qx.Class.define("qx.event.Manager", {
|
|
|
415
463
|
}
|
|
416
464
|
}
|
|
417
465
|
|
|
418
|
-
var targetKey =
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
466
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
467
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
468
|
+
|
|
469
|
+
if (!targetMap) {
|
|
470
|
+
targetMap = new Map();
|
|
471
|
+
this.__listeners.set(targetKey, targetMap);
|
|
472
|
+
}
|
|
422
473
|
|
|
423
474
|
for (var listKey in list) {
|
|
424
475
|
var item = list[listKey];
|
|
425
476
|
|
|
426
477
|
var entryKey = item.type + (item.capture ? "|capture" : "|bubble");
|
|
427
|
-
var
|
|
478
|
+
var entryMap = targetMap.get(entryKey);
|
|
428
479
|
|
|
429
|
-
if (!
|
|
430
|
-
|
|
480
|
+
if (!entryMap) {
|
|
481
|
+
entryMap = new Map();
|
|
482
|
+
targetMap.set(entryKey, entryMap)
|
|
483
|
+
}
|
|
431
484
|
|
|
485
|
+
if (entryMap.size === 0) {
|
|
432
486
|
// This is the first event listener for this type and target
|
|
433
487
|
// Inform the event handler about the new event
|
|
434
488
|
// they perform the event registration at DOM level if needed
|
|
435
489
|
this.__registerAtHandler(target, item.type, item.capture);
|
|
436
490
|
}
|
|
437
491
|
|
|
438
|
-
//
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
492
|
+
// Add listener to map
|
|
493
|
+
var unique = item.unique || qx.event.Manager.getNextUniqueId();
|
|
494
|
+
entryMap.set(unique, {
|
|
495
|
+
handler: item.listener,
|
|
496
|
+
context: item.self,
|
|
497
|
+
unique: unique
|
|
498
|
+
}
|
|
499
|
+
);
|
|
444
500
|
}
|
|
445
501
|
},
|
|
446
502
|
|
|
@@ -486,37 +542,37 @@ qx.Class.define("qx.event.Manager", {
|
|
|
486
542
|
}
|
|
487
543
|
}
|
|
488
544
|
|
|
489
|
-
var targetKey =
|
|
490
|
-
|
|
491
|
-
var targetMap = this.__listeners[targetKey];
|
|
545
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
546
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
492
547
|
|
|
493
548
|
if (!targetMap) {
|
|
494
|
-
targetMap =
|
|
549
|
+
targetMap = new Map();
|
|
550
|
+
this.__listeners.set(targetKey, targetMap);
|
|
495
551
|
}
|
|
496
552
|
|
|
497
553
|
var entryKey = type + (capture ? "|capture" : "|bubble");
|
|
498
|
-
var
|
|
554
|
+
var entryMap = targetMap.get(entryKey);
|
|
499
555
|
|
|
500
|
-
if (!
|
|
501
|
-
|
|
556
|
+
if (!entryMap) {
|
|
557
|
+
entryMap = new Map();
|
|
558
|
+
targetMap.set(entryKey, entryMap)
|
|
502
559
|
}
|
|
503
560
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
561
|
+
if (entryMap.size === 0) {
|
|
562
|
+
// This is the first event listener for this type and target
|
|
563
|
+
// Inform the event handler about the new event
|
|
564
|
+
// they perform the event registration at DOM level if needed
|
|
508
565
|
this.__registerAtHandler(target, type, capture);
|
|
509
566
|
}
|
|
510
567
|
|
|
511
|
-
//
|
|
512
|
-
var unique = qx.event.Manager.
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
entryList.push(entry);
|
|
568
|
+
// Add listener to map
|
|
569
|
+
var unique = qx.event.Manager.getNextUniqueId();
|
|
570
|
+
entryMap.set(unique, {
|
|
571
|
+
handler: listener,
|
|
572
|
+
context: self,
|
|
573
|
+
unique: unique
|
|
574
|
+
}
|
|
575
|
+
);
|
|
520
576
|
|
|
521
577
|
return entryKey + "|" + unique;
|
|
522
578
|
},
|
|
@@ -524,7 +580,7 @@ qx.Class.define("qx.event.Manager", {
|
|
|
524
580
|
/**
|
|
525
581
|
* Get the event handler class matching the given event target and type
|
|
526
582
|
*
|
|
527
|
-
* @param target {
|
|
583
|
+
* @param target {Object} The event target
|
|
528
584
|
* @param type {String} The event type
|
|
529
585
|
* @return {qx.event.IEventHandler|null} The best matching event handler or
|
|
530
586
|
* <code>null</code>.
|
|
@@ -683,38 +739,29 @@ qx.Class.define("qx.event.Manager", {
|
|
|
683
739
|
}
|
|
684
740
|
}
|
|
685
741
|
|
|
686
|
-
var targetKey =
|
|
687
|
-
|
|
688
|
-
var targetMap = this.__listeners[targetKey];
|
|
742
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
743
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
689
744
|
|
|
690
745
|
if (!targetMap) {
|
|
691
746
|
return false;
|
|
692
747
|
}
|
|
693
|
-
|
|
694
748
|
var entryKey = type + (capture ? "|capture" : "|bubble");
|
|
695
|
-
var
|
|
749
|
+
var entryMap = targetMap.get(entryKey);
|
|
696
750
|
|
|
697
|
-
if (!
|
|
751
|
+
if (!entryMap) {
|
|
698
752
|
return false;
|
|
699
753
|
}
|
|
754
|
+
var deleted = false;
|
|
700
755
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
if (
|
|
706
|
-
|
|
707
|
-
this.__addToBlacklist(entry.unique);
|
|
708
|
-
|
|
709
|
-
if (entryList.length == 0) {
|
|
710
|
-
this.__unregisterAtHandler(target, type, capture);
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
return true;
|
|
756
|
+
for (const [entryKey, entry] of entryMap.entries().filter(([eK, e]) => e.handler === listener && e.context === self)) {
|
|
757
|
+
deleted = true;
|
|
758
|
+
entryMap.delete(entryKey);
|
|
759
|
+
this.__addToBlacklist(entryKey);
|
|
760
|
+
if (entryMap.size === 0) {
|
|
761
|
+
this.__unregisterAtHandler(target, type, capture);
|
|
714
762
|
}
|
|
715
763
|
}
|
|
716
|
-
|
|
717
|
-
return false;
|
|
764
|
+
return deleted;
|
|
718
765
|
},
|
|
719
766
|
|
|
720
767
|
/**
|
|
@@ -741,40 +788,32 @@ qx.Class.define("qx.event.Manager", {
|
|
|
741
788
|
|
|
742
789
|
var split = id.split("|");
|
|
743
790
|
var type = split[0];
|
|
744
|
-
var capture = split[1].charCodeAt(0)
|
|
791
|
+
var capture = split[1].charCodeAt(0) === 99; // detect leading "c"
|
|
745
792
|
var unique = split[2];
|
|
746
793
|
|
|
747
|
-
var targetKey =
|
|
748
|
-
|
|
749
|
-
var targetMap = this.__listeners[targetKey];
|
|
794
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
795
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
750
796
|
|
|
751
797
|
if (!targetMap) {
|
|
752
798
|
return false;
|
|
753
799
|
}
|
|
754
800
|
|
|
755
801
|
var entryKey = type + (capture ? "|capture" : "|bubble");
|
|
756
|
-
var
|
|
802
|
+
var entryMap = targetMap.get(entryKey);
|
|
757
803
|
|
|
758
|
-
if (!
|
|
804
|
+
if (!entryMap) {
|
|
759
805
|
return false;
|
|
760
806
|
}
|
|
761
807
|
|
|
762
|
-
var entry;
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
if (
|
|
767
|
-
|
|
768
|
-
this.__addToBlacklist(entry.unique);
|
|
769
|
-
|
|
770
|
-
if (entryList.length == 0) {
|
|
771
|
-
this.__unregisterAtHandler(target, type, capture);
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
return true;
|
|
808
|
+
var entry = entryMap.get(unique);
|
|
809
|
+
if (entry) {
|
|
810
|
+
entryMap.delete(unique);
|
|
811
|
+
this.__addToBlacklist(entry.unique);
|
|
812
|
+
if (entryMap.size === 0) {
|
|
813
|
+
this.__unregisterAtHandler(target, type, capture);
|
|
775
814
|
}
|
|
815
|
+
return true;
|
|
776
816
|
}
|
|
777
|
-
|
|
778
817
|
return false;
|
|
779
818
|
},
|
|
780
819
|
|
|
@@ -785,23 +824,23 @@ qx.Class.define("qx.event.Manager", {
|
|
|
785
824
|
* @return {Boolean} Whether the events were existant and were removed successfully.
|
|
786
825
|
*/
|
|
787
826
|
removeAllListeners(target) {
|
|
788
|
-
var targetKey =
|
|
789
|
-
|
|
790
|
-
var targetMap = this.__listeners[targetKey];
|
|
827
|
+
var targetKey = target.$$hash || qx.core.ObjectRegistry.toHashCode(target);
|
|
828
|
+
var targetMap = this.__listeners.get(targetKey);
|
|
791
829
|
if (!targetMap) {
|
|
792
830
|
return false;
|
|
793
831
|
}
|
|
794
832
|
|
|
795
833
|
// Deregister from event handlers
|
|
796
834
|
var split, type, capture;
|
|
797
|
-
for (
|
|
798
|
-
if (
|
|
835
|
+
for (const [entryKey, entryMap] of targetMap) {
|
|
836
|
+
if (entryMap && entryMap.size > 0) {
|
|
799
837
|
// This is quite expensive, see bug #1283
|
|
800
838
|
split = entryKey.split("|");
|
|
801
839
|
|
|
802
|
-
|
|
803
|
-
this.__addToBlacklist(
|
|
804
|
-
}
|
|
840
|
+
for (const uniqueKey of entryMap.keys()) {
|
|
841
|
+
this.__addToBlacklist(uniqueKey);
|
|
842
|
+
}
|
|
843
|
+
entryMap.clear();
|
|
805
844
|
|
|
806
845
|
type = split[0];
|
|
807
846
|
capture = split[1] === "capture";
|
|
@@ -810,7 +849,7 @@ qx.Class.define("qx.event.Manager", {
|
|
|
810
849
|
}
|
|
811
850
|
}
|
|
812
851
|
|
|
813
|
-
|
|
852
|
+
this.__listeners.delete(targetKey);
|
|
814
853
|
return true;
|
|
815
854
|
},
|
|
816
855
|
|
|
@@ -824,7 +863,7 @@ qx.Class.define("qx.event.Manager", {
|
|
|
824
863
|
* @internal
|
|
825
864
|
*/
|
|
826
865
|
deleteAllListeners(targetKey) {
|
|
827
|
-
|
|
866
|
+
this.__listeners.delete(targetKey);
|
|
828
867
|
},
|
|
829
868
|
|
|
830
869
|
/**
|
|
@@ -1002,7 +1041,7 @@ qx.Class.define("qx.event.Manager", {
|
|
|
1002
1041
|
/**
|
|
1003
1042
|
* Add event to blacklist.
|
|
1004
1043
|
*
|
|
1005
|
-
* @param uid {
|
|
1044
|
+
* @param uid {String} unique event id
|
|
1006
1045
|
*/
|
|
1007
1046
|
__addToBlacklist(uid) {
|
|
1008
1047
|
if (this.__blacklist === null) {
|
|
@@ -1015,7 +1054,7 @@ qx.Class.define("qx.event.Manager", {
|
|
|
1015
1054
|
/**
|
|
1016
1055
|
* Check if the event with the given id has been removed and is therefore blacklisted for event handling
|
|
1017
1056
|
*
|
|
1018
|
-
* @param uid {
|
|
1057
|
+
* @param uid {String} unique event id
|
|
1019
1058
|
* @return {boolean}
|
|
1020
1059
|
*/
|
|
1021
1060
|
isBlacklisted(uid) {
|
|
@@ -41,7 +41,7 @@ qx.Bootstrap.define("qx.io.ImageLoader", {
|
|
|
41
41
|
__knownImageTypesRegExp: /\.(png|gif|jpg|jpeg|bmp)\b/i,
|
|
42
42
|
|
|
43
43
|
/** @type {RegExp} Image types of a data URL */
|
|
44
|
-
__dataUrlRegExp: /^data:image\/(png|gif|jpg|jpeg|bmp)\b/i,
|
|
44
|
+
__dataUrlRegExp: /^data:image\/(png|gif|jpg|jpeg|bmp|svg)\b/i,
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Whether the given image has previously been loaded using the
|
|
@@ -161,12 +161,15 @@ qx.Bootstrap.define("qx.io.ImageLoader", {
|
|
|
161
161
|
* second parameter is the data entry which contains additional
|
|
162
162
|
* information about the image.
|
|
163
163
|
* @param context {Object?} Context in which the given callback should be executed
|
|
164
|
+
* @param options {Map?} Optional configuration options:
|
|
165
|
+
* - retryFailed {boolean} Whether to retry loading of a failed image source
|
|
164
166
|
*/
|
|
165
|
-
load(source, callback, context) {
|
|
167
|
+
load(source, callback, context, options) {
|
|
168
|
+
options ??= {};
|
|
166
169
|
// Shorthand
|
|
167
170
|
var entry = this.__data[source];
|
|
168
171
|
|
|
169
|
-
if (!entry) {
|
|
172
|
+
if (!entry || (options.retryFailed && entry.failed)) {
|
|
170
173
|
entry = this.__data[source] = {};
|
|
171
174
|
}
|
|
172
175
|
|
|
@@ -125,8 +125,8 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
125
125
|
},
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
|
-
* Fires "error" event and
|
|
129
|
-
*
|
|
128
|
+
* Fires "error" event and rejects the pending requests' promises.
|
|
129
|
+
* The method will be renamed and made private in v8.
|
|
130
130
|
* @param exception
|
|
131
131
|
* @private
|
|
132
132
|
*/
|
|
@@ -134,19 +134,37 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
134
134
|
this.fireDataEvent("error", exception);
|
|
135
135
|
this.__requests.forEach(request => {
|
|
136
136
|
if (request instanceof qx.io.jsonrpc.protocol.Request) {
|
|
137
|
+
// this rejects the request's promise
|
|
137
138
|
request.handleTransportException(exception);
|
|
138
139
|
}
|
|
139
140
|
});
|
|
140
|
-
|
|
141
|
+
if (!qx.core.Environment.get("qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest")){
|
|
142
|
+
throw exception; // will be removed in v8 since it is not caught anywhere
|
|
143
|
+
}
|
|
141
144
|
},
|
|
142
145
|
|
|
143
146
|
/**
|
|
144
147
|
* Send the given JSON-RPC message object using the configured transport
|
|
145
148
|
*
|
|
146
149
|
* @param {qx.io.jsonrpc.protocol.Message|qx.io.jsonrpc.protocol.Batch} message
|
|
147
|
-
* @return {qx.Promise} Promise that resolves (with no data)
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
+
* @return {qx.Promise} Promise that resolves (with no data) when the message has been successfully
|
|
151
|
+
* sent out. As this means different things depending on the transport implementation, it is best
|
|
152
|
+
* not to base any kind of business logic on the fulfillment of that promise.
|
|
153
|
+
*
|
|
154
|
+
* The current behavior is to return the promise from the transport `send()` implementation, which
|
|
155
|
+
* might be rejected with a {@link qx.io.exception.Transport} in case of a transport error.
|
|
156
|
+
* This has caused problems with "unhandled promise rejection" errors, so a new behaviour will be
|
|
157
|
+
* the default in v8: The returned promise is already resolved, and any rejection of the transport
|
|
158
|
+
* promise will only be forwarded to the promise(s) of the request(s) contained in the the `message`
|
|
159
|
+
* argument. The returned promise will never be rejected. This behavior can be enabled by setting
|
|
160
|
+
* the environment variable `qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest` to `true` in v7.
|
|
161
|
+
* In v8, the default of `qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest` will become `true`,
|
|
162
|
+
* and that environment variable will become deprecated.
|
|
163
|
+
*
|
|
164
|
+
* In any case, the result of the jsonrpc request is retrieved by awaiting {@link qx.io.jsonrpc.protocol.Request}'s
|
|
165
|
+
* promise, which is resolved with the jsonrpc server's response or is rejected either with a
|
|
166
|
+
* {@link qx.io.exception.Transport} in case of a transport error or with {@link qx.io.protocol.Error}
|
|
167
|
+
* in case of a jsonrpc error.
|
|
150
168
|
*/
|
|
151
169
|
async send(message) {
|
|
152
170
|
if (
|
|
@@ -191,7 +209,27 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
191
209
|
}
|
|
192
210
|
|
|
193
211
|
// send it async, using transport-specific implementation
|
|
194
|
-
|
|
212
|
+
const transportPromise = this.getTransport().send(message.toString())
|
|
213
|
+
|
|
214
|
+
if (qx.core.Environment.get("qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest")) {
|
|
215
|
+
// forward rejections to the requests' promises, which will be standard behavior in v8
|
|
216
|
+
transportPromise.catch(error => {
|
|
217
|
+
// wrap error in transport exception
|
|
218
|
+
if (!(error instanceof qx.io.exception.Transport)) {
|
|
219
|
+
error = new qx.io.exception.Transport(
|
|
220
|
+
error.toString(),
|
|
221
|
+
qx.io.exception.Transport.FORWARDED,
|
|
222
|
+
error
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
this._throwTransportException(error)
|
|
226
|
+
})
|
|
227
|
+
// return a resolved promise so that the actual completion of the transport is not awaited
|
|
228
|
+
return qx.Promise.resolve()
|
|
229
|
+
} else {
|
|
230
|
+
// default behavior in v7: return promise from transport
|
|
231
|
+
return transportPromise;
|
|
232
|
+
}
|
|
195
233
|
},
|
|
196
234
|
|
|
197
235
|
/**
|
|
@@ -208,7 +246,9 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
208
246
|
params
|
|
209
247
|
);
|
|
210
248
|
|
|
249
|
+
// await completion of transport
|
|
211
250
|
await this.send(request);
|
|
251
|
+
// await fulfillment of requests
|
|
212
252
|
return await request.getPromise();
|
|
213
253
|
},
|
|
214
254
|
|
|
@@ -243,7 +283,9 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
243
283
|
message.setMethod(this._prependMethodPrefix(message.getMethod()))
|
|
244
284
|
);
|
|
245
285
|
}
|
|
286
|
+
// await completion of transport
|
|
246
287
|
await this.send(batch);
|
|
288
|
+
// await fulfilment of requests
|
|
247
289
|
return await qx.Promise.all(batch.getPromises());
|
|
248
290
|
},
|
|
249
291
|
|
|
@@ -284,6 +326,7 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
284
326
|
/**
|
|
285
327
|
* Handle an incoming message or batch of messages
|
|
286
328
|
* @param {qx.io.jsonrpc.protocol.Message|qx.io.jsonrpc.protocol.Batch} message Message or Batch
|
|
329
|
+
* @throws {qx.io.exception.Transport} For transport-related errors
|
|
287
330
|
*/
|
|
288
331
|
handleMessage(message) {
|
|
289
332
|
// handle batches
|
|
@@ -324,6 +367,7 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
324
367
|
// resolve the individual promise
|
|
325
368
|
request.getPromise().resolve(message.getResult());
|
|
326
369
|
} else if (message instanceof qx.io.jsonrpc.protocol.Error) {
|
|
370
|
+
// handle jsonrpc (not transport-related) errors
|
|
327
371
|
let error = message.getError();
|
|
328
372
|
let ex = new qx.io.exception.Protocol(
|
|
329
373
|
error.message,
|
|
@@ -350,6 +394,18 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
350
394
|
},
|
|
351
395
|
|
|
352
396
|
environment: {
|
|
353
|
-
|
|
397
|
+
/**
|
|
398
|
+
* If true, log detailed information on the jsonrpc traffic in the console
|
|
399
|
+
*/
|
|
400
|
+
"qx.io.jsonrpc.debug": false,
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* If true, forward transport errors to the running jsonrpc requests' promise instead of rejecting
|
|
404
|
+
* the promise returned by {@link #send}. Default is `false`.
|
|
405
|
+
|
|
406
|
+
* @deprecated
|
|
407
|
+
* Behavior in v8 will be as if the environment variable value is `true`, but the environment variable will no longer be available.
|
|
408
|
+
*/
|
|
409
|
+
"qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest": false
|
|
354
410
|
}
|
|
355
411
|
});
|