URL.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. "use strict";
  2. const conversions = require("webidl-conversions");
  3. const utils = require("./utils.js");
  4. const implSymbol = utils.implSymbol;
  5. const ctorRegistrySymbol = utils.ctorRegistrySymbol;
  6. const interfaceName = "URL";
  7. exports.is = value => {
  8. return utils.isObject(value) && utils.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
  9. };
  10. exports.isImpl = value => {
  11. return utils.isObject(value) && value instanceof Impl.implementation;
  12. };
  13. exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
  14. if (exports.is(value)) {
  15. return utils.implForWrapper(value);
  16. }
  17. throw new globalObject.TypeError(`${context} is not of type 'URL'.`);
  18. };
  19. function makeWrapper(globalObject, newTarget) {
  20. let proto;
  21. if (newTarget !== undefined) {
  22. proto = newTarget.prototype;
  23. }
  24. if (!utils.isObject(proto)) {
  25. proto = globalObject[ctorRegistrySymbol]["URL"].prototype;
  26. }
  27. return Object.create(proto);
  28. }
  29. exports.create = (globalObject, constructorArgs, privateData) => {
  30. const wrapper = makeWrapper(globalObject);
  31. return exports.setup(wrapper, globalObject, constructorArgs, privateData);
  32. };
  33. exports.createImpl = (globalObject, constructorArgs, privateData) => {
  34. const wrapper = exports.create(globalObject, constructorArgs, privateData);
  35. return utils.implForWrapper(wrapper);
  36. };
  37. exports._internalSetup = (wrapper, globalObject) => {};
  38. exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
  39. privateData.wrapper = wrapper;
  40. exports._internalSetup(wrapper, globalObject);
  41. Object.defineProperty(wrapper, implSymbol, {
  42. value: new Impl.implementation(globalObject, constructorArgs, privateData),
  43. configurable: true
  44. });
  45. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  46. if (Impl.init) {
  47. Impl.init(wrapper[implSymbol]);
  48. }
  49. return wrapper;
  50. };
  51. exports.new = (globalObject, newTarget) => {
  52. const wrapper = makeWrapper(globalObject, newTarget);
  53. exports._internalSetup(wrapper, globalObject);
  54. Object.defineProperty(wrapper, implSymbol, {
  55. value: Object.create(Impl.implementation.prototype),
  56. configurable: true
  57. });
  58. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  59. if (Impl.init) {
  60. Impl.init(wrapper[implSymbol]);
  61. }
  62. return wrapper[implSymbol];
  63. };
  64. const exposed = new Set(["Window", "Worker"]);
  65. exports.install = (globalObject, globalNames) => {
  66. if (!globalNames.some(globalName => exposed.has(globalName))) {
  67. return;
  68. }
  69. const ctorRegistry = utils.initCtorRegistry(globalObject);
  70. class URL {
  71. constructor(url) {
  72. if (arguments.length < 1) {
  73. throw new globalObject.TypeError(
  74. `Failed to construct 'URL': 1 argument required, but only ${arguments.length} present.`
  75. );
  76. }
  77. const args = [];
  78. {
  79. let curArg = arguments[0];
  80. curArg = conversions["USVString"](curArg, {
  81. context: "Failed to construct 'URL': parameter 1",
  82. globals: globalObject
  83. });
  84. args.push(curArg);
  85. }
  86. {
  87. let curArg = arguments[1];
  88. if (curArg !== undefined) {
  89. curArg = conversions["USVString"](curArg, {
  90. context: "Failed to construct 'URL': parameter 2",
  91. globals: globalObject
  92. });
  93. }
  94. args.push(curArg);
  95. }
  96. return exports.setup(Object.create(new.target.prototype), globalObject, args);
  97. }
  98. toJSON() {
  99. const esValue = this !== null && this !== undefined ? this : globalObject;
  100. if (!exports.is(esValue)) {
  101. throw new globalObject.TypeError("'toJSON' called on an object that is not a valid instance of URL.");
  102. }
  103. return esValue[implSymbol].toJSON();
  104. }
  105. get href() {
  106. const esValue = this !== null && this !== undefined ? this : globalObject;
  107. if (!exports.is(esValue)) {
  108. throw new globalObject.TypeError("'get href' called on an object that is not a valid instance of URL.");
  109. }
  110. return esValue[implSymbol]["href"];
  111. }
  112. set href(V) {
  113. const esValue = this !== null && this !== undefined ? this : globalObject;
  114. if (!exports.is(esValue)) {
  115. throw new globalObject.TypeError("'set href' called on an object that is not a valid instance of URL.");
  116. }
  117. V = conversions["USVString"](V, {
  118. context: "Failed to set the 'href' property on 'URL': The provided value",
  119. globals: globalObject
  120. });
  121. esValue[implSymbol]["href"] = V;
  122. }
  123. toString() {
  124. const esValue = this;
  125. if (!exports.is(esValue)) {
  126. throw new globalObject.TypeError("'toString' called on an object that is not a valid instance of URL.");
  127. }
  128. return esValue[implSymbol]["href"];
  129. }
  130. get origin() {
  131. const esValue = this !== null && this !== undefined ? this : globalObject;
  132. if (!exports.is(esValue)) {
  133. throw new globalObject.TypeError("'get origin' called on an object that is not a valid instance of URL.");
  134. }
  135. return esValue[implSymbol]["origin"];
  136. }
  137. get protocol() {
  138. const esValue = this !== null && this !== undefined ? this : globalObject;
  139. if (!exports.is(esValue)) {
  140. throw new globalObject.TypeError("'get protocol' called on an object that is not a valid instance of URL.");
  141. }
  142. return esValue[implSymbol]["protocol"];
  143. }
  144. set protocol(V) {
  145. const esValue = this !== null && this !== undefined ? this : globalObject;
  146. if (!exports.is(esValue)) {
  147. throw new globalObject.TypeError("'set protocol' called on an object that is not a valid instance of URL.");
  148. }
  149. V = conversions["USVString"](V, {
  150. context: "Failed to set the 'protocol' property on 'URL': The provided value",
  151. globals: globalObject
  152. });
  153. esValue[implSymbol]["protocol"] = V;
  154. }
  155. get username() {
  156. const esValue = this !== null && this !== undefined ? this : globalObject;
  157. if (!exports.is(esValue)) {
  158. throw new globalObject.TypeError("'get username' called on an object that is not a valid instance of URL.");
  159. }
  160. return esValue[implSymbol]["username"];
  161. }
  162. set username(V) {
  163. const esValue = this !== null && this !== undefined ? this : globalObject;
  164. if (!exports.is(esValue)) {
  165. throw new globalObject.TypeError("'set username' called on an object that is not a valid instance of URL.");
  166. }
  167. V = conversions["USVString"](V, {
  168. context: "Failed to set the 'username' property on 'URL': The provided value",
  169. globals: globalObject
  170. });
  171. esValue[implSymbol]["username"] = V;
  172. }
  173. get password() {
  174. const esValue = this !== null && this !== undefined ? this : globalObject;
  175. if (!exports.is(esValue)) {
  176. throw new globalObject.TypeError("'get password' called on an object that is not a valid instance of URL.");
  177. }
  178. return esValue[implSymbol]["password"];
  179. }
  180. set password(V) {
  181. const esValue = this !== null && this !== undefined ? this : globalObject;
  182. if (!exports.is(esValue)) {
  183. throw new globalObject.TypeError("'set password' called on an object that is not a valid instance of URL.");
  184. }
  185. V = conversions["USVString"](V, {
  186. context: "Failed to set the 'password' property on 'URL': The provided value",
  187. globals: globalObject
  188. });
  189. esValue[implSymbol]["password"] = V;
  190. }
  191. get host() {
  192. const esValue = this !== null && this !== undefined ? this : globalObject;
  193. if (!exports.is(esValue)) {
  194. throw new globalObject.TypeError("'get host' called on an object that is not a valid instance of URL.");
  195. }
  196. return esValue[implSymbol]["host"];
  197. }
  198. set host(V) {
  199. const esValue = this !== null && this !== undefined ? this : globalObject;
  200. if (!exports.is(esValue)) {
  201. throw new globalObject.TypeError("'set host' called on an object that is not a valid instance of URL.");
  202. }
  203. V = conversions["USVString"](V, {
  204. context: "Failed to set the 'host' property on 'URL': The provided value",
  205. globals: globalObject
  206. });
  207. esValue[implSymbol]["host"] = V;
  208. }
  209. get hostname() {
  210. const esValue = this !== null && this !== undefined ? this : globalObject;
  211. if (!exports.is(esValue)) {
  212. throw new globalObject.TypeError("'get hostname' called on an object that is not a valid instance of URL.");
  213. }
  214. return esValue[implSymbol]["hostname"];
  215. }
  216. set hostname(V) {
  217. const esValue = this !== null && this !== undefined ? this : globalObject;
  218. if (!exports.is(esValue)) {
  219. throw new globalObject.TypeError("'set hostname' called on an object that is not a valid instance of URL.");
  220. }
  221. V = conversions["USVString"](V, {
  222. context: "Failed to set the 'hostname' property on 'URL': The provided value",
  223. globals: globalObject
  224. });
  225. esValue[implSymbol]["hostname"] = V;
  226. }
  227. get port() {
  228. const esValue = this !== null && this !== undefined ? this : globalObject;
  229. if (!exports.is(esValue)) {
  230. throw new globalObject.TypeError("'get port' called on an object that is not a valid instance of URL.");
  231. }
  232. return esValue[implSymbol]["port"];
  233. }
  234. set port(V) {
  235. const esValue = this !== null && this !== undefined ? this : globalObject;
  236. if (!exports.is(esValue)) {
  237. throw new globalObject.TypeError("'set port' called on an object that is not a valid instance of URL.");
  238. }
  239. V = conversions["USVString"](V, {
  240. context: "Failed to set the 'port' property on 'URL': The provided value",
  241. globals: globalObject
  242. });
  243. esValue[implSymbol]["port"] = V;
  244. }
  245. get pathname() {
  246. const esValue = this !== null && this !== undefined ? this : globalObject;
  247. if (!exports.is(esValue)) {
  248. throw new globalObject.TypeError("'get pathname' called on an object that is not a valid instance of URL.");
  249. }
  250. return esValue[implSymbol]["pathname"];
  251. }
  252. set pathname(V) {
  253. const esValue = this !== null && this !== undefined ? this : globalObject;
  254. if (!exports.is(esValue)) {
  255. throw new globalObject.TypeError("'set pathname' called on an object that is not a valid instance of URL.");
  256. }
  257. V = conversions["USVString"](V, {
  258. context: "Failed to set the 'pathname' property on 'URL': The provided value",
  259. globals: globalObject
  260. });
  261. esValue[implSymbol]["pathname"] = V;
  262. }
  263. get search() {
  264. const esValue = this !== null && this !== undefined ? this : globalObject;
  265. if (!exports.is(esValue)) {
  266. throw new globalObject.TypeError("'get search' called on an object that is not a valid instance of URL.");
  267. }
  268. return esValue[implSymbol]["search"];
  269. }
  270. set search(V) {
  271. const esValue = this !== null && this !== undefined ? this : globalObject;
  272. if (!exports.is(esValue)) {
  273. throw new globalObject.TypeError("'set search' called on an object that is not a valid instance of URL.");
  274. }
  275. V = conversions["USVString"](V, {
  276. context: "Failed to set the 'search' property on 'URL': The provided value",
  277. globals: globalObject
  278. });
  279. esValue[implSymbol]["search"] = V;
  280. }
  281. get searchParams() {
  282. const esValue = this !== null && this !== undefined ? this : globalObject;
  283. if (!exports.is(esValue)) {
  284. throw new globalObject.TypeError("'get searchParams' called on an object that is not a valid instance of URL.");
  285. }
  286. return utils.getSameObject(this, "searchParams", () => {
  287. return utils.tryWrapperForImpl(esValue[implSymbol]["searchParams"]);
  288. });
  289. }
  290. get hash() {
  291. const esValue = this !== null && this !== undefined ? this : globalObject;
  292. if (!exports.is(esValue)) {
  293. throw new globalObject.TypeError("'get hash' called on an object that is not a valid instance of URL.");
  294. }
  295. return esValue[implSymbol]["hash"];
  296. }
  297. set hash(V) {
  298. const esValue = this !== null && this !== undefined ? this : globalObject;
  299. if (!exports.is(esValue)) {
  300. throw new globalObject.TypeError("'set hash' called on an object that is not a valid instance of URL.");
  301. }
  302. V = conversions["USVString"](V, {
  303. context: "Failed to set the 'hash' property on 'URL': The provided value",
  304. globals: globalObject
  305. });
  306. esValue[implSymbol]["hash"] = V;
  307. }
  308. }
  309. Object.defineProperties(URL.prototype, {
  310. toJSON: { enumerable: true },
  311. href: { enumerable: true },
  312. toString: { enumerable: true },
  313. origin: { enumerable: true },
  314. protocol: { enumerable: true },
  315. username: { enumerable: true },
  316. password: { enumerable: true },
  317. host: { enumerable: true },
  318. hostname: { enumerable: true },
  319. port: { enumerable: true },
  320. pathname: { enumerable: true },
  321. search: { enumerable: true },
  322. searchParams: { enumerable: true },
  323. hash: { enumerable: true },
  324. [Symbol.toStringTag]: { value: "URL", configurable: true }
  325. });
  326. ctorRegistry[interfaceName] = URL;
  327. Object.defineProperty(globalObject, interfaceName, {
  328. configurable: true,
  329. writable: true,
  330. value: URL
  331. });
  332. if (globalNames.includes("Window")) {
  333. Object.defineProperty(globalObject, "webkitURL", {
  334. configurable: true,
  335. writable: true,
  336. value: URL
  337. });
  338. }
  339. };
  340. const Impl = require("./URL-impl.js");