deprecate.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. let deprecationHandler: ElectronInternal.DeprecationHandler | null = null;
  2. function warnOnce (oldName: string, newName?: string) {
  3. let warned = false;
  4. const msg = newName
  5. ? `'${oldName}' is deprecated and will be removed. Please use '${newName}' instead.`
  6. : `'${oldName}' is deprecated and will be removed.`;
  7. return () => {
  8. if (!warned && !process.noDeprecation) {
  9. warned = true;
  10. deprecate.log(msg);
  11. }
  12. };
  13. }
  14. const deprecate: ElectronInternal.DeprecationUtil = {
  15. warnOnce,
  16. setHandler: (handler) => { deprecationHandler = handler; },
  17. getHandler: () => deprecationHandler,
  18. warn: (oldName, newName) => {
  19. if (!process.noDeprecation) {
  20. deprecate.log(`'${oldName}' is deprecated. Use '${newName}' instead.`);
  21. }
  22. },
  23. log: (message) => {
  24. if (typeof deprecationHandler === 'function') {
  25. deprecationHandler(message);
  26. } else if (process.throwDeprecation) {
  27. throw new Error(message);
  28. } else if (process.traceDeprecation) {
  29. return console.trace(message);
  30. } else {
  31. return console.warn(`(electron) ${message}`);
  32. }
  33. },
  34. // remove a function with no replacement
  35. removeFunction: (fn, removedName) => {
  36. if (!fn) { throw Error(`'${removedName} function' is invalid or does not exist.`); }
  37. // wrap the deprecated function to warn user
  38. const warn = warnOnce(`${fn.name} function`);
  39. return function (this: any) {
  40. warn();
  41. fn.apply(this, arguments);
  42. } as unknown as typeof fn;
  43. },
  44. // change the name of a function
  45. renameFunction: (fn, newName) => {
  46. const warn = warnOnce(`${fn.name} function`, `${newName} function`);
  47. return function (this: any) {
  48. warn();
  49. return fn.apply(this, arguments);
  50. } as unknown as typeof fn;
  51. },
  52. moveAPI<T extends Function> (fn: T, oldUsage: string, newUsage: string): T {
  53. const warn = warnOnce(oldUsage, newUsage);
  54. return function (this: any) {
  55. warn();
  56. return fn.apply(this, arguments);
  57. } as unknown as typeof fn;
  58. },
  59. // change the name of an event
  60. event: (emitter, oldName, newName) => {
  61. const warn = newName.startsWith('-') /* internal event */
  62. ? warnOnce(`${oldName} event`)
  63. : warnOnce(`${oldName} event`, `${newName} event`);
  64. return emitter.on(newName, function (this: NodeJS.EventEmitter, ...args) {
  65. if (this.listenerCount(oldName) !== 0) {
  66. warn();
  67. this.emit(oldName, ...args);
  68. }
  69. });
  70. },
  71. // remove a property with no replacement
  72. removeProperty: (o, removedName, onlyForValues) => {
  73. // if the property's already been removed, warn about it
  74. const info = Object.getOwnPropertyDescriptor((o as any).__proto__, removedName) // eslint-disable-line
  75. if (!info) {
  76. deprecate.log(`Unable to remove property '${removedName}' from an object that lacks it.`);
  77. return o;
  78. }
  79. if (!info.get || !info.set) {
  80. deprecate.log(`Unable to remove property '${removedName}' from an object does not have a getter / setter`);
  81. return o;
  82. }
  83. // wrap the deprecated property in an accessor to warn
  84. const warn = warnOnce(removedName);
  85. return Object.defineProperty(o, removedName, {
  86. configurable: true,
  87. get: () => {
  88. warn();
  89. return info.get!.call(o);
  90. },
  91. set: newVal => {
  92. if (!onlyForValues || onlyForValues.includes(newVal)) {
  93. warn();
  94. }
  95. return info.set!.call(o, newVal);
  96. }
  97. });
  98. },
  99. // change the name of a property
  100. renameProperty: (o, oldName, newName) => {
  101. const warn = warnOnce(oldName, newName);
  102. // if the new property isn't there yet,
  103. // inject it and warn about it
  104. if ((oldName in o) && !(newName in o)) {
  105. warn();
  106. o[newName] = (o as any)[oldName];
  107. }
  108. // wrap the deprecated property in an accessor to warn
  109. // and redirect to the new property
  110. return Object.defineProperty(o, oldName, {
  111. get: () => {
  112. warn();
  113. return o[newName];
  114. },
  115. set: value => {
  116. warn();
  117. o[newName] = value;
  118. }
  119. });
  120. }
  121. };
  122. export default deprecate;