type-utils.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const { nativeImage } = process._linkedBinding('electron_common_native_image');
  2. export function isPromise (val: any) {
  3. return (
  4. val &&
  5. val.then &&
  6. val.then instanceof Function &&
  7. val.constructor &&
  8. val.constructor.reject &&
  9. val.constructor.reject instanceof Function &&
  10. val.constructor.resolve &&
  11. val.constructor.resolve instanceof Function
  12. );
  13. }
  14. const serializableTypes = [
  15. Boolean,
  16. Number,
  17. String,
  18. Date,
  19. Error,
  20. RegExp,
  21. ArrayBuffer
  22. ];
  23. // https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#Supported_types
  24. export function isSerializableObject (value: any) {
  25. return value === null || ArrayBuffer.isView(value) || serializableTypes.some(type => value instanceof type);
  26. }
  27. const objectMap = function (source: Object, mapper: (value: any) => any) {
  28. const sourceEntries = Object.entries(source);
  29. const targetEntries = sourceEntries.map(([key, val]) => [key, mapper(val)]);
  30. return Object.fromEntries(targetEntries);
  31. };
  32. function serializeNativeImage (image: Electron.NativeImage) {
  33. const representations = [];
  34. const scaleFactors = image.getScaleFactors();
  35. // Use Buffer when there's only one representation for better perf.
  36. // This avoids compressing to/from PNG where it's not necessary to
  37. // ensure uniqueness of dataURLs (since there's only one).
  38. if (scaleFactors.length === 1) {
  39. const scaleFactor = scaleFactors[0];
  40. const size = image.getSize(scaleFactor);
  41. const buffer = image.toBitmap({ scaleFactor });
  42. representations.push({ scaleFactor, size, buffer });
  43. } else {
  44. // Construct from dataURLs to ensure that they are not lost in creation.
  45. for (const scaleFactor of scaleFactors) {
  46. const size = image.getSize(scaleFactor);
  47. const dataURL = image.toDataURL({ scaleFactor });
  48. representations.push({ scaleFactor, size, dataURL });
  49. }
  50. }
  51. return { __ELECTRON_SERIALIZED_NativeImage__: true, representations };
  52. }
  53. function deserializeNativeImage (value: any) {
  54. const image = nativeImage.createEmpty();
  55. // Use Buffer when there's only one representation for better perf.
  56. // This avoids compressing to/from PNG where it's not necessary to
  57. // ensure uniqueness of dataURLs (since there's only one).
  58. if (value.representations.length === 1) {
  59. const { buffer, size, scaleFactor } = value.representations[0];
  60. const { width, height } = size;
  61. image.addRepresentation({ buffer, scaleFactor, width, height });
  62. } else {
  63. // Construct from dataURLs to ensure that they are not lost in creation.
  64. for (const rep of value.representations) {
  65. const { dataURL, size, scaleFactor } = rep;
  66. const { width, height } = size;
  67. image.addRepresentation({ dataURL, scaleFactor, width, height });
  68. }
  69. }
  70. return image;
  71. }
  72. export function serialize (value: any): any {
  73. if (value && value.constructor && value.constructor.name === 'NativeImage') {
  74. return serializeNativeImage(value);
  75. } if (Array.isArray(value)) {
  76. return value.map(serialize);
  77. } else if (isSerializableObject(value)) {
  78. return value;
  79. } else if (value instanceof Object) {
  80. return objectMap(value, serialize);
  81. } else {
  82. return value;
  83. }
  84. }
  85. export function deserialize (value: any): any {
  86. if (value && value.__ELECTRON_SERIALIZED_NativeImage__) {
  87. return deserializeNativeImage(value);
  88. } else if (Array.isArray(value)) {
  89. return value.map(deserialize);
  90. } else if (isSerializableObject(value)) {
  91. return value;
  92. } else if (value instanceof Object) {
  93. return objectMap(value, deserialize);
  94. } else {
  95. return value;
  96. }
  97. }