utils.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. "use strict";
  2. // Returns "Type(value) is Object" in ES terminology.
  3. function isObject(value) {
  4. return (typeof value === "object" && value !== null) || typeof value === "function";
  5. }
  6. const call = Function.call.bind(Function.call);
  7. // Like `Object.assign`, but using `[[GetOwnProperty]]` and `[[DefineOwnProperty]]`
  8. // instead of `[[Get]]` and `[[Set]]` and only allowing objects
  9. function define(target, source) {
  10. for (const key of Reflect.ownKeys(source)) {
  11. const descriptor = Reflect.getOwnPropertyDescriptor(source, key);
  12. if (descriptor && !Reflect.defineProperty(target, key, descriptor)) {
  13. throw new TypeError(`Cannot redefine property: ${String(key)}`);
  14. }
  15. }
  16. }
  17. function newObjectInRealm(globalObject, object) {
  18. const ctorRegistry = initCtorRegistry(globalObject);
  19. return Object.defineProperties(
  20. Object.create(ctorRegistry["%Object.prototype%"]),
  21. Object.getOwnPropertyDescriptors(object)
  22. );
  23. }
  24. const wrapperSymbol = Symbol("wrapper");
  25. const implSymbol = Symbol("impl");
  26. const sameObjectCaches = Symbol("SameObject caches");
  27. const ctorRegistrySymbol = Symbol.for("[webidl2js] constructor registry");
  28. const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype);
  29. function initCtorRegistry(globalObject) {
  30. if (Object.hasOwn(globalObject, ctorRegistrySymbol)) {
  31. return globalObject[ctorRegistrySymbol];
  32. }
  33. const ctorRegistry = Object.create(null);
  34. // In addition to registering all the WebIDL2JS-generated types in the constructor registry,
  35. // we also register a few intrinsics that we make use of in generated code, since they are not
  36. // easy to grab from the globalObject variable.
  37. ctorRegistry["%Object.prototype%"] = globalObject.Object.prototype;
  38. ctorRegistry["%IteratorPrototype%"] = Object.getPrototypeOf(
  39. Object.getPrototypeOf(new globalObject.Array()[Symbol.iterator]())
  40. );
  41. try {
  42. ctorRegistry["%AsyncIteratorPrototype%"] = Object.getPrototypeOf(
  43. Object.getPrototypeOf(
  44. globalObject.eval("(async function* () {})").prototype
  45. )
  46. );
  47. } catch {
  48. ctorRegistry["%AsyncIteratorPrototype%"] = AsyncIteratorPrototype;
  49. }
  50. globalObject[ctorRegistrySymbol] = ctorRegistry;
  51. return ctorRegistry;
  52. }
  53. function getSameObject(wrapper, prop, creator) {
  54. if (!wrapper[sameObjectCaches]) {
  55. wrapper[sameObjectCaches] = Object.create(null);
  56. }
  57. if (prop in wrapper[sameObjectCaches]) {
  58. return wrapper[sameObjectCaches][prop];
  59. }
  60. wrapper[sameObjectCaches][prop] = creator();
  61. return wrapper[sameObjectCaches][prop];
  62. }
  63. function wrapperForImpl(impl) {
  64. return impl ? impl[wrapperSymbol] : null;
  65. }
  66. function implForWrapper(wrapper) {
  67. return wrapper ? wrapper[implSymbol] : null;
  68. }
  69. function tryWrapperForImpl(impl) {
  70. const wrapper = wrapperForImpl(impl);
  71. return wrapper ? wrapper : impl;
  72. }
  73. function tryImplForWrapper(wrapper) {
  74. const impl = implForWrapper(wrapper);
  75. return impl ? impl : wrapper;
  76. }
  77. const iterInternalSymbol = Symbol("internal");
  78. function isArrayIndexPropName(P) {
  79. if (typeof P !== "string") {
  80. return false;
  81. }
  82. const i = P >>> 0;
  83. if (i === 2 ** 32 - 1) {
  84. return false;
  85. }
  86. const s = `${i}`;
  87. if (P !== s) {
  88. return false;
  89. }
  90. return true;
  91. }
  92. const arrayBufferByteLengthGetter =
  93. Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
  94. function isArrayBuffer(value) {
  95. try {
  96. arrayBufferByteLengthGetter.call(value);
  97. return true;
  98. } catch {
  99. return false;
  100. }
  101. }
  102. const sharedArrayBufferByteLengthGetter =
  103. Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, "byteLength").get;
  104. function isSharedArrayBuffer(value) {
  105. try {
  106. sharedArrayBufferByteLengthGetter.call(value);
  107. return true;
  108. } catch {
  109. return false;
  110. }
  111. }
  112. function iteratorResult([key, value], kind) {
  113. let result;
  114. switch (kind) {
  115. case "key":
  116. result = key;
  117. break;
  118. case "value":
  119. result = value;
  120. break;
  121. case "key+value":
  122. result = [key, value];
  123. break;
  124. }
  125. return { value: result, done: false };
  126. }
  127. function ordinarySetWithOwnDescriptor(target, property, value, receiver, ownDesc) {
  128. if (ownDesc === undefined) {
  129. const parent = Reflect.getPrototypeOf(target);
  130. if (parent !== null) {
  131. return Reflect.set(parent, property, value, receiver);
  132. }
  133. ownDesc = { writable: true, enumerable: true, configurable: true, value: undefined };
  134. }
  135. if (isDataDescriptor(ownDesc)) {
  136. if (!ownDesc.writable) {
  137. return false;
  138. }
  139. if (!isObject(receiver)) {
  140. return false;
  141. }
  142. const existingDesc = Reflect.getOwnPropertyDescriptor(receiver, property);
  143. if (existingDesc !== undefined) {
  144. if (isAccessorDescriptor(existingDesc)) {
  145. return false;
  146. }
  147. if (existingDesc.writable === false) {
  148. return false;
  149. }
  150. const valueDesc = { value };
  151. return Reflect.defineProperty(receiver, property, valueDesc);
  152. }
  153. return Reflect.defineProperty(
  154. receiver,
  155. property,
  156. { value, writable: true, enumerable: true, configurable: true }
  157. );
  158. }
  159. const setter = ownDesc.set;
  160. if (setter === undefined) {
  161. return false;
  162. }
  163. call(setter, receiver, value);
  164. return true;
  165. }
  166. function isDataDescriptor(desc) {
  167. return Object.hasOwn(desc, "value") || Object.hasOwn(desc, "writable");
  168. }
  169. function isAccessorDescriptor(desc) {
  170. return Object.hasOwn(desc, "get") || Object.hasOwn(desc, "set");
  171. }
  172. const supportsPropertyIndex = Symbol("supports property index");
  173. const supportedPropertyIndices = Symbol("supported property indices");
  174. const supportsPropertyName = Symbol("supports property name");
  175. const supportedPropertyNames = Symbol("supported property names");
  176. const indexedGet = Symbol("indexed property get");
  177. const indexedSetNew = Symbol("indexed property set new");
  178. const indexedSetExisting = Symbol("indexed property set existing");
  179. const namedGet = Symbol("named property get");
  180. const namedSetNew = Symbol("named property set new");
  181. const namedSetExisting = Symbol("named property set existing");
  182. const namedDelete = Symbol("named property delete");
  183. const asyncIteratorNext = Symbol("async iterator get the next iteration result");
  184. const asyncIteratorReturn = Symbol("async iterator return steps");
  185. const asyncIteratorInit = Symbol("async iterator initialization steps");
  186. const asyncIteratorEOI = Symbol("async iterator end of iteration");
  187. module.exports = exports = {
  188. isObject,
  189. define,
  190. newObjectInRealm,
  191. wrapperSymbol,
  192. implSymbol,
  193. getSameObject,
  194. ctorRegistrySymbol,
  195. initCtorRegistry,
  196. wrapperForImpl,
  197. implForWrapper,
  198. tryWrapperForImpl,
  199. tryImplForWrapper,
  200. iterInternalSymbol,
  201. isArrayBuffer,
  202. isSharedArrayBuffer,
  203. isArrayIndexPropName,
  204. supportsPropertyIndex,
  205. supportedPropertyIndices,
  206. supportsPropertyName,
  207. supportedPropertyNames,
  208. indexedGet,
  209. indexedSetNew,
  210. indexedSetExisting,
  211. namedGet,
  212. namedSetNew,
  213. namedSetExisting,
  214. namedDelete,
  215. asyncIteratorNext,
  216. asyncIteratorReturn,
  217. asyncIteratorInit,
  218. asyncIteratorEOI,
  219. iteratorResult,
  220. ordinarySetWithOwnDescriptor
  221. };