URLSearchParams.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. "use strict";
  2. const conversions = require("webidl-conversions");
  3. const utils = require("./utils.js");
  4. const Function = require("./Function.js");
  5. const newObjectInRealm = utils.newObjectInRealm;
  6. const implSymbol = utils.implSymbol;
  7. const ctorRegistrySymbol = utils.ctorRegistrySymbol;
  8. const interfaceName = "URLSearchParams";
  9. exports.is = value => {
  10. return utils.isObject(value) && utils.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
  11. };
  12. exports.isImpl = value => {
  13. return utils.isObject(value) && value instanceof Impl.implementation;
  14. };
  15. exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
  16. if (exports.is(value)) {
  17. return utils.implForWrapper(value);
  18. }
  19. throw new globalObject.TypeError(`${context} is not of type 'URLSearchParams'.`);
  20. };
  21. exports.createDefaultIterator = (globalObject, target, kind) => {
  22. const ctorRegistry = globalObject[ctorRegistrySymbol];
  23. const iteratorPrototype = ctorRegistry["URLSearchParams Iterator"];
  24. const iterator = Object.create(iteratorPrototype);
  25. Object.defineProperty(iterator, utils.iterInternalSymbol, {
  26. value: { target, kind, index: 0 },
  27. configurable: true
  28. });
  29. return iterator;
  30. };
  31. function makeWrapper(globalObject, newTarget) {
  32. let proto;
  33. if (newTarget !== undefined) {
  34. proto = newTarget.prototype;
  35. }
  36. if (!utils.isObject(proto)) {
  37. proto = globalObject[ctorRegistrySymbol]["URLSearchParams"].prototype;
  38. }
  39. return Object.create(proto);
  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[implSymbol][utils.wrapperSymbol] = wrapper;
  58. if (Impl.init) {
  59. Impl.init(wrapper[implSymbol]);
  60. }
  61. return wrapper;
  62. };
  63. exports.new = (globalObject, newTarget) => {
  64. const wrapper = makeWrapper(globalObject, newTarget);
  65. exports._internalSetup(wrapper, globalObject);
  66. Object.defineProperty(wrapper, implSymbol, {
  67. value: Object.create(Impl.implementation.prototype),
  68. configurable: true
  69. });
  70. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  71. if (Impl.init) {
  72. Impl.init(wrapper[implSymbol]);
  73. }
  74. return wrapper[implSymbol];
  75. };
  76. const exposed = new Set(["Window", "Worker"]);
  77. exports.install = (globalObject, globalNames) => {
  78. if (!globalNames.some(globalName => exposed.has(globalName))) {
  79. return;
  80. }
  81. const ctorRegistry = utils.initCtorRegistry(globalObject);
  82. class URLSearchParams {
  83. constructor() {
  84. const args = [];
  85. {
  86. let curArg = arguments[0];
  87. if (curArg !== undefined) {
  88. if (utils.isObject(curArg)) {
  89. if (curArg[Symbol.iterator] !== undefined) {
  90. if (!utils.isObject(curArg)) {
  91. throw new globalObject.TypeError(
  92. "Failed to construct 'URLSearchParams': parameter 1" + " sequence" + " is not an iterable object."
  93. );
  94. } else {
  95. const V = [];
  96. const tmp = curArg;
  97. for (let nextItem of tmp) {
  98. if (!utils.isObject(nextItem)) {
  99. throw new globalObject.TypeError(
  100. "Failed to construct 'URLSearchParams': parameter 1" +
  101. " sequence" +
  102. "'s element" +
  103. " is not an iterable object."
  104. );
  105. } else {
  106. const V = [];
  107. const tmp = nextItem;
  108. for (let nextItem of tmp) {
  109. nextItem = conversions["USVString"](nextItem, {
  110. context:
  111. "Failed to construct 'URLSearchParams': parameter 1" +
  112. " sequence" +
  113. "'s element" +
  114. "'s element",
  115. globals: globalObject
  116. });
  117. V.push(nextItem);
  118. }
  119. nextItem = V;
  120. }
  121. V.push(nextItem);
  122. }
  123. curArg = V;
  124. }
  125. } else {
  126. if (!utils.isObject(curArg)) {
  127. throw new globalObject.TypeError(
  128. "Failed to construct 'URLSearchParams': parameter 1" + " record" + " is not an object."
  129. );
  130. } else {
  131. const result = Object.create(null);
  132. for (const key of Reflect.ownKeys(curArg)) {
  133. const desc = Object.getOwnPropertyDescriptor(curArg, key);
  134. if (desc && desc.enumerable) {
  135. let typedKey = key;
  136. typedKey = conversions["USVString"](typedKey, {
  137. context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s key",
  138. globals: globalObject
  139. });
  140. let typedValue = curArg[key];
  141. typedValue = conversions["USVString"](typedValue, {
  142. context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s value",
  143. globals: globalObject
  144. });
  145. result[typedKey] = typedValue;
  146. }
  147. }
  148. curArg = result;
  149. }
  150. }
  151. } else {
  152. curArg = conversions["USVString"](curArg, {
  153. context: "Failed to construct 'URLSearchParams': parameter 1",
  154. globals: globalObject
  155. });
  156. }
  157. } else {
  158. curArg = "";
  159. }
  160. args.push(curArg);
  161. }
  162. return exports.setup(Object.create(new.target.prototype), globalObject, args);
  163. }
  164. append(name, value) {
  165. const esValue = this !== null && this !== undefined ? this : globalObject;
  166. if (!exports.is(esValue)) {
  167. throw new globalObject.TypeError(
  168. "'append' called on an object that is not a valid instance of URLSearchParams."
  169. );
  170. }
  171. if (arguments.length < 2) {
  172. throw new globalObject.TypeError(
  173. `Failed to execute 'append' on 'URLSearchParams': 2 arguments required, but only ${arguments.length} present.`
  174. );
  175. }
  176. const args = [];
  177. {
  178. let curArg = arguments[0];
  179. curArg = conversions["USVString"](curArg, {
  180. context: "Failed to execute 'append' on 'URLSearchParams': parameter 1",
  181. globals: globalObject
  182. });
  183. args.push(curArg);
  184. }
  185. {
  186. let curArg = arguments[1];
  187. curArg = conversions["USVString"](curArg, {
  188. context: "Failed to execute 'append' on 'URLSearchParams': parameter 2",
  189. globals: globalObject
  190. });
  191. args.push(curArg);
  192. }
  193. return utils.tryWrapperForImpl(esValue[implSymbol].append(...args));
  194. }
  195. delete(name) {
  196. const esValue = this !== null && this !== undefined ? this : globalObject;
  197. if (!exports.is(esValue)) {
  198. throw new globalObject.TypeError(
  199. "'delete' called on an object that is not a valid instance of URLSearchParams."
  200. );
  201. }
  202. if (arguments.length < 1) {
  203. throw new globalObject.TypeError(
  204. `Failed to execute 'delete' on 'URLSearchParams': 1 argument required, but only ${arguments.length} present.`
  205. );
  206. }
  207. const args = [];
  208. {
  209. let curArg = arguments[0];
  210. curArg = conversions["USVString"](curArg, {
  211. context: "Failed to execute 'delete' on 'URLSearchParams': parameter 1",
  212. globals: globalObject
  213. });
  214. args.push(curArg);
  215. }
  216. return utils.tryWrapperForImpl(esValue[implSymbol].delete(...args));
  217. }
  218. get(name) {
  219. const esValue = this !== null && this !== undefined ? this : globalObject;
  220. if (!exports.is(esValue)) {
  221. throw new globalObject.TypeError("'get' called on an object that is not a valid instance of URLSearchParams.");
  222. }
  223. if (arguments.length < 1) {
  224. throw new globalObject.TypeError(
  225. `Failed to execute 'get' on 'URLSearchParams': 1 argument required, but only ${arguments.length} present.`
  226. );
  227. }
  228. const args = [];
  229. {
  230. let curArg = arguments[0];
  231. curArg = conversions["USVString"](curArg, {
  232. context: "Failed to execute 'get' on 'URLSearchParams': parameter 1",
  233. globals: globalObject
  234. });
  235. args.push(curArg);
  236. }
  237. return esValue[implSymbol].get(...args);
  238. }
  239. getAll(name) {
  240. const esValue = this !== null && this !== undefined ? this : globalObject;
  241. if (!exports.is(esValue)) {
  242. throw new globalObject.TypeError(
  243. "'getAll' called on an object that is not a valid instance of URLSearchParams."
  244. );
  245. }
  246. if (arguments.length < 1) {
  247. throw new globalObject.TypeError(
  248. `Failed to execute 'getAll' on 'URLSearchParams': 1 argument required, but only ${arguments.length} present.`
  249. );
  250. }
  251. const args = [];
  252. {
  253. let curArg = arguments[0];
  254. curArg = conversions["USVString"](curArg, {
  255. context: "Failed to execute 'getAll' on 'URLSearchParams': parameter 1",
  256. globals: globalObject
  257. });
  258. args.push(curArg);
  259. }
  260. return utils.tryWrapperForImpl(esValue[implSymbol].getAll(...args));
  261. }
  262. has(name) {
  263. const esValue = this !== null && this !== undefined ? this : globalObject;
  264. if (!exports.is(esValue)) {
  265. throw new globalObject.TypeError("'has' called on an object that is not a valid instance of URLSearchParams.");
  266. }
  267. if (arguments.length < 1) {
  268. throw new globalObject.TypeError(
  269. `Failed to execute 'has' on 'URLSearchParams': 1 argument required, but only ${arguments.length} present.`
  270. );
  271. }
  272. const args = [];
  273. {
  274. let curArg = arguments[0];
  275. curArg = conversions["USVString"](curArg, {
  276. context: "Failed to execute 'has' on 'URLSearchParams': parameter 1",
  277. globals: globalObject
  278. });
  279. args.push(curArg);
  280. }
  281. return esValue[implSymbol].has(...args);
  282. }
  283. set(name, value) {
  284. const esValue = this !== null && this !== undefined ? this : globalObject;
  285. if (!exports.is(esValue)) {
  286. throw new globalObject.TypeError("'set' called on an object that is not a valid instance of URLSearchParams.");
  287. }
  288. if (arguments.length < 2) {
  289. throw new globalObject.TypeError(
  290. `Failed to execute 'set' on 'URLSearchParams': 2 arguments required, but only ${arguments.length} present.`
  291. );
  292. }
  293. const args = [];
  294. {
  295. let curArg = arguments[0];
  296. curArg = conversions["USVString"](curArg, {
  297. context: "Failed to execute 'set' on 'URLSearchParams': parameter 1",
  298. globals: globalObject
  299. });
  300. args.push(curArg);
  301. }
  302. {
  303. let curArg = arguments[1];
  304. curArg = conversions["USVString"](curArg, {
  305. context: "Failed to execute 'set' on 'URLSearchParams': parameter 2",
  306. globals: globalObject
  307. });
  308. args.push(curArg);
  309. }
  310. return utils.tryWrapperForImpl(esValue[implSymbol].set(...args));
  311. }
  312. sort() {
  313. const esValue = this !== null && this !== undefined ? this : globalObject;
  314. if (!exports.is(esValue)) {
  315. throw new globalObject.TypeError("'sort' called on an object that is not a valid instance of URLSearchParams.");
  316. }
  317. return utils.tryWrapperForImpl(esValue[implSymbol].sort());
  318. }
  319. toString() {
  320. const esValue = this !== null && this !== undefined ? this : globalObject;
  321. if (!exports.is(esValue)) {
  322. throw new globalObject.TypeError(
  323. "'toString' called on an object that is not a valid instance of URLSearchParams."
  324. );
  325. }
  326. return esValue[implSymbol].toString();
  327. }
  328. keys() {
  329. if (!exports.is(this)) {
  330. throw new globalObject.TypeError("'keys' called on an object that is not a valid instance of URLSearchParams.");
  331. }
  332. return exports.createDefaultIterator(globalObject, this, "key");
  333. }
  334. values() {
  335. if (!exports.is(this)) {
  336. throw new globalObject.TypeError(
  337. "'values' called on an object that is not a valid instance of URLSearchParams."
  338. );
  339. }
  340. return exports.createDefaultIterator(globalObject, this, "value");
  341. }
  342. entries() {
  343. if (!exports.is(this)) {
  344. throw new globalObject.TypeError(
  345. "'entries' called on an object that is not a valid instance of URLSearchParams."
  346. );
  347. }
  348. return exports.createDefaultIterator(globalObject, this, "key+value");
  349. }
  350. forEach(callback) {
  351. if (!exports.is(this)) {
  352. throw new globalObject.TypeError(
  353. "'forEach' called on an object that is not a valid instance of URLSearchParams."
  354. );
  355. }
  356. if (arguments.length < 1) {
  357. throw new globalObject.TypeError(
  358. "Failed to execute 'forEach' on 'iterable': 1 argument required, but only 0 present."
  359. );
  360. }
  361. callback = Function.convert(globalObject, callback, {
  362. context: "Failed to execute 'forEach' on 'iterable': The callback provided as parameter 1"
  363. });
  364. const thisArg = arguments[1];
  365. let pairs = Array.from(this[implSymbol]);
  366. let i = 0;
  367. while (i < pairs.length) {
  368. const [key, value] = pairs[i].map(utils.tryWrapperForImpl);
  369. callback.call(thisArg, value, key, this);
  370. pairs = Array.from(this[implSymbol]);
  371. i++;
  372. }
  373. }
  374. }
  375. Object.defineProperties(URLSearchParams.prototype, {
  376. append: { enumerable: true },
  377. delete: { enumerable: true },
  378. get: { enumerable: true },
  379. getAll: { enumerable: true },
  380. has: { enumerable: true },
  381. set: { enumerable: true },
  382. sort: { enumerable: true },
  383. toString: { enumerable: true },
  384. keys: { enumerable: true },
  385. values: { enumerable: true },
  386. entries: { enumerable: true },
  387. forEach: { enumerable: true },
  388. [Symbol.toStringTag]: { value: "URLSearchParams", configurable: true },
  389. [Symbol.iterator]: { value: URLSearchParams.prototype.entries, configurable: true, writable: true }
  390. });
  391. ctorRegistry[interfaceName] = URLSearchParams;
  392. ctorRegistry["URLSearchParams Iterator"] = Object.create(ctorRegistry["%IteratorPrototype%"], {
  393. [Symbol.toStringTag]: {
  394. configurable: true,
  395. value: "URLSearchParams Iterator"
  396. }
  397. });
  398. utils.define(ctorRegistry["URLSearchParams Iterator"], {
  399. next() {
  400. const internal = this && this[utils.iterInternalSymbol];
  401. if (!internal) {
  402. throw new globalObject.TypeError("next() called on a value that is not a URLSearchParams iterator object");
  403. }
  404. const { target, kind, index } = internal;
  405. const values = Array.from(target[implSymbol]);
  406. const len = values.length;
  407. if (index >= len) {
  408. return newObjectInRealm(globalObject, { value: undefined, done: true });
  409. }
  410. const pair = values[index];
  411. internal.index = index + 1;
  412. return newObjectInRealm(globalObject, utils.iteratorResult(pair.map(utils.tryWrapperForImpl), kind));
  413. }
  414. });
  415. Object.defineProperty(globalObject, interfaceName, {
  416. configurable: true,
  417. writable: true,
  418. value: URLSearchParams
  419. });
  420. };
  421. const Impl = require("./URLSearchParams-impl.js");