DOMStringMap.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. "use strict";
  2. const conversions = require("webidl-conversions");
  3. const utils = require("./utils.js");
  4. const ceReactionsPreSteps_jsdom_living_helpers_custom_elements =
  5. require("../../jsdom/living/helpers/custom-elements.js").ceReactionsPreSteps;
  6. const ceReactionsPostSteps_jsdom_living_helpers_custom_elements =
  7. require("../../jsdom/living/helpers/custom-elements.js").ceReactionsPostSteps;
  8. const implSymbol = utils.implSymbol;
  9. const ctorRegistrySymbol = utils.ctorRegistrySymbol;
  10. const interfaceName = "DOMStringMap";
  11. exports.is = value => {
  12. return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
  13. };
  14. exports.isImpl = value => {
  15. return utils.isObject(value) && value instanceof Impl.implementation;
  16. };
  17. exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
  18. if (exports.is(value)) {
  19. return utils.implForWrapper(value);
  20. }
  21. throw new globalObject.TypeError(`${context} is not of type 'DOMStringMap'.`);
  22. };
  23. function makeWrapper(globalObject, newTarget) {
  24. let proto;
  25. if (newTarget !== undefined) {
  26. proto = newTarget.prototype;
  27. }
  28. if (!utils.isObject(proto)) {
  29. proto = globalObject[ctorRegistrySymbol]["DOMStringMap"].prototype;
  30. }
  31. return Object.create(proto);
  32. }
  33. function makeProxy(wrapper, globalObject) {
  34. let proxyHandler = proxyHandlerCache.get(globalObject);
  35. if (proxyHandler === undefined) {
  36. proxyHandler = new ProxyHandler(globalObject);
  37. proxyHandlerCache.set(globalObject, proxyHandler);
  38. }
  39. return new Proxy(wrapper, proxyHandler);
  40. }
  41. exports.create = (globalObject, constructorArgs, privateData) => {
  42. const wrapper = makeWrapper(globalObject);
  43. return exports.setup(wrapper, globalObject, constructorArgs, privateData);
  44. };
  45. exports.createImpl = (globalObject, constructorArgs, privateData) => {
  46. const wrapper = exports.create(globalObject, constructorArgs, privateData);
  47. return utils.implForWrapper(wrapper);
  48. };
  49. exports._internalSetup = (wrapper, globalObject) => {};
  50. exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
  51. privateData.wrapper = wrapper;
  52. exports._internalSetup(wrapper, globalObject);
  53. Object.defineProperty(wrapper, implSymbol, {
  54. value: new Impl.implementation(globalObject, constructorArgs, privateData),
  55. configurable: true
  56. });
  57. wrapper = makeProxy(wrapper, globalObject);
  58. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  59. if (Impl.init) {
  60. Impl.init(wrapper[implSymbol]);
  61. }
  62. return wrapper;
  63. };
  64. exports.new = (globalObject, newTarget) => {
  65. let wrapper = makeWrapper(globalObject, newTarget);
  66. exports._internalSetup(wrapper, globalObject);
  67. Object.defineProperty(wrapper, implSymbol, {
  68. value: Object.create(Impl.implementation.prototype),
  69. configurable: true
  70. });
  71. wrapper = makeProxy(wrapper, globalObject);
  72. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  73. if (Impl.init) {
  74. Impl.init(wrapper[implSymbol]);
  75. }
  76. return wrapper[implSymbol];
  77. };
  78. const exposed = new Set(["Window"]);
  79. exports.install = (globalObject, globalNames) => {
  80. if (!globalNames.some(globalName => exposed.has(globalName))) {
  81. return;
  82. }
  83. const ctorRegistry = utils.initCtorRegistry(globalObject);
  84. class DOMStringMap {
  85. constructor() {
  86. throw new globalObject.TypeError("Illegal constructor");
  87. }
  88. }
  89. Object.defineProperties(DOMStringMap.prototype, {
  90. [Symbol.toStringTag]: { value: "DOMStringMap", configurable: true }
  91. });
  92. ctorRegistry[interfaceName] = DOMStringMap;
  93. Object.defineProperty(globalObject, interfaceName, {
  94. configurable: true,
  95. writable: true,
  96. value: DOMStringMap
  97. });
  98. };
  99. const proxyHandlerCache = new WeakMap();
  100. class ProxyHandler {
  101. constructor(globalObject) {
  102. this._globalObject = globalObject;
  103. }
  104. get(target, P, receiver) {
  105. if (typeof P === "symbol") {
  106. return Reflect.get(target, P, receiver);
  107. }
  108. const desc = this.getOwnPropertyDescriptor(target, P);
  109. if (desc === undefined) {
  110. const parent = Object.getPrototypeOf(target);
  111. if (parent === null) {
  112. return undefined;
  113. }
  114. return Reflect.get(target, P, receiver);
  115. }
  116. if (!desc.get && !desc.set) {
  117. return desc.value;
  118. }
  119. const getter = desc.get;
  120. if (getter === undefined) {
  121. return undefined;
  122. }
  123. return Reflect.apply(getter, receiver, []);
  124. }
  125. has(target, P) {
  126. if (typeof P === "symbol") {
  127. return Reflect.has(target, P);
  128. }
  129. const desc = this.getOwnPropertyDescriptor(target, P);
  130. if (desc !== undefined) {
  131. return true;
  132. }
  133. const parent = Object.getPrototypeOf(target);
  134. if (parent !== null) {
  135. return Reflect.has(parent, P);
  136. }
  137. return false;
  138. }
  139. ownKeys(target) {
  140. const keys = new Set();
  141. for (const key of target[implSymbol][utils.supportedPropertyNames]) {
  142. if (!Object.hasOwn(target, key)) {
  143. keys.add(`${key}`);
  144. }
  145. }
  146. for (const key of Reflect.ownKeys(target)) {
  147. keys.add(key);
  148. }
  149. return [...keys];
  150. }
  151. getOwnPropertyDescriptor(target, P) {
  152. if (typeof P === "symbol") {
  153. return Reflect.getOwnPropertyDescriptor(target, P);
  154. }
  155. let ignoreNamedProps = false;
  156. const namedValue = target[implSymbol][utils.namedGet](P);
  157. if (namedValue !== undefined && !Object.hasOwn(target, P) && !ignoreNamedProps) {
  158. return {
  159. writable: true,
  160. enumerable: true,
  161. configurable: true,
  162. value: utils.tryWrapperForImpl(namedValue)
  163. };
  164. }
  165. return Reflect.getOwnPropertyDescriptor(target, P);
  166. }
  167. set(target, P, V, receiver) {
  168. if (typeof P === "symbol") {
  169. return Reflect.set(target, P, V, receiver);
  170. }
  171. // The `receiver` argument refers to the Proxy exotic object or an object
  172. // that inherits from it, whereas `target` refers to the Proxy target:
  173. if (target[implSymbol][utils.wrapperSymbol] === receiver) {
  174. const globalObject = this._globalObject;
  175. if (typeof P === "string") {
  176. let namedValue = V;
  177. namedValue = conversions["DOMString"](namedValue, {
  178. context: "Failed to set the '" + P + "' property on 'DOMStringMap': The provided value",
  179. globals: globalObject
  180. });
  181. ceReactionsPreSteps_jsdom_living_helpers_custom_elements(globalObject);
  182. try {
  183. const creating = !(target[implSymbol][utils.namedGet](P) !== undefined);
  184. if (creating) {
  185. target[implSymbol][utils.namedSetNew](P, namedValue);
  186. } else {
  187. target[implSymbol][utils.namedSetExisting](P, namedValue);
  188. }
  189. } finally {
  190. ceReactionsPostSteps_jsdom_living_helpers_custom_elements(globalObject);
  191. }
  192. return true;
  193. }
  194. }
  195. let ownDesc;
  196. if (ownDesc === undefined) {
  197. ownDesc = Reflect.getOwnPropertyDescriptor(target, P);
  198. }
  199. return utils.ordinarySetWithOwnDescriptor(target, P, V, receiver, ownDesc);
  200. }
  201. defineProperty(target, P, desc) {
  202. if (typeof P === "symbol") {
  203. return Reflect.defineProperty(target, P, desc);
  204. }
  205. const globalObject = this._globalObject;
  206. if (desc.get || desc.set) {
  207. return false;
  208. }
  209. let namedValue = desc.value;
  210. namedValue = conversions["DOMString"](namedValue, {
  211. context: "Failed to set the '" + P + "' property on 'DOMStringMap': The provided value",
  212. globals: globalObject
  213. });
  214. ceReactionsPreSteps_jsdom_living_helpers_custom_elements(globalObject);
  215. try {
  216. const creating = !(target[implSymbol][utils.namedGet](P) !== undefined);
  217. if (creating) {
  218. target[implSymbol][utils.namedSetNew](P, namedValue);
  219. } else {
  220. target[implSymbol][utils.namedSetExisting](P, namedValue);
  221. }
  222. } finally {
  223. ceReactionsPostSteps_jsdom_living_helpers_custom_elements(globalObject);
  224. }
  225. return true;
  226. }
  227. deleteProperty(target, P) {
  228. if (typeof P === "symbol") {
  229. return Reflect.deleteProperty(target, P);
  230. }
  231. const globalObject = this._globalObject;
  232. if (target[implSymbol][utils.namedGet](P) !== undefined && !Object.hasOwn(target, P)) {
  233. ceReactionsPreSteps_jsdom_living_helpers_custom_elements(globalObject);
  234. try {
  235. target[implSymbol][utils.namedDelete](P);
  236. return true;
  237. } finally {
  238. ceReactionsPostSteps_jsdom_living_helpers_custom_elements(globalObject);
  239. }
  240. }
  241. return Reflect.deleteProperty(target, P);
  242. }
  243. preventExtensions() {
  244. return false;
  245. }
  246. }
  247. const Impl = require("../../jsdom/living/nodes/DOMStringMap-impl.js");