utils.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. "use strict";
  2. const { domSymbolTree } = require("./living/helpers/internal-constants");
  3. const SYMBOL_TREE_POSITION = require("symbol-tree").TreePosition;
  4. /**
  5. * Define a set of properties on an object, by copying the property descriptors
  6. * from the original object.
  7. *
  8. * - `object` {Object} the target object
  9. * - `properties` {Object} the source from which to copy property descriptors
  10. */
  11. exports.define = function define(object, properties) {
  12. for (const name of Object.getOwnPropertyNames(properties)) {
  13. const propDesc = Object.getOwnPropertyDescriptor(properties, name);
  14. Object.defineProperty(object, name, propDesc);
  15. }
  16. };
  17. exports.mixin = (target, source) => {
  18. const keys = Reflect.ownKeys(source);
  19. for (let i = 0; i < keys.length; ++i) {
  20. if (keys[i] in target) {
  21. continue;
  22. }
  23. Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i]));
  24. }
  25. };
  26. let memoizeQueryTypeCounter = 0;
  27. /**
  28. * Returns a version of a method that memoizes specific types of calls on the object
  29. *
  30. * - `fn` {Function} the method to be memozied
  31. */
  32. exports.memoizeQuery = function memoizeQuery(fn) {
  33. // Only memoize query functions with arity <= 2
  34. if (fn.length > 2) {
  35. return fn;
  36. }
  37. const type = memoizeQueryTypeCounter++;
  38. return function (...args) {
  39. if (!this._memoizedQueries) {
  40. return fn.apply(this, args);
  41. }
  42. if (!this._memoizedQueries[type]) {
  43. this._memoizedQueries[type] = Object.create(null);
  44. }
  45. let key;
  46. if (args.length === 1 && typeof args[0] === "string") {
  47. key = args[0];
  48. } else if (args.length === 2 && typeof args[0] === "string" && typeof args[1] === "string") {
  49. key = args[0] + "::" + args[1];
  50. } else {
  51. return fn.apply(this, args);
  52. }
  53. if (!(key in this._memoizedQueries[type])) {
  54. this._memoizedQueries[type][key] = fn.apply(this, args);
  55. }
  56. return this._memoizedQueries[type][key];
  57. };
  58. };
  59. exports.simultaneousIterators = function* (first, second) {
  60. for (;;) {
  61. const firstResult = first.next();
  62. const secondResult = second.next();
  63. if (firstResult.done && secondResult.done) {
  64. return;
  65. }
  66. yield [
  67. firstResult.done ? null : firstResult.value,
  68. secondResult.done ? null : secondResult.value
  69. ];
  70. }
  71. };
  72. exports.treeOrderSorter = function (a, b) {
  73. const compare = domSymbolTree.compareTreePosition(a, b);
  74. if (compare & SYMBOL_TREE_POSITION.PRECEDING) { // b is preceding a
  75. return 1;
  76. }
  77. if (compare & SYMBOL_TREE_POSITION.FOLLOWING) {
  78. return -1;
  79. }
  80. // disconnected or equal:
  81. return 0;
  82. };
  83. try {
  84. exports.Canvas = require("canvas");
  85. } catch {
  86. exports.Canvas = null;
  87. }