You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

457 lines
15 KiB

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