type-utils.ts 3.8 KB

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