summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/dts/lib.deno.window.d.ts72
-rw-r--r--cli/dts/lib.deno.worker.d.ts23
-rw-r--r--cli/flags.rs5
-rw-r--r--cli/tests/070_location.ts.out2
-rw-r--r--cli/tests/079_location_authentication.ts1
-rw-r--r--cli/tests/079_location_authentication.ts.out3
-rw-r--r--cli/tests/integration_tests.rs5
-rw-r--r--cli/tests/subdir/worker_location.ts4
-rw-r--r--cli/tests/workers_test.ts2
-rw-r--r--op_crates/web/12_location.js188
-rw-r--r--op_crates/web/lib.deno_web.d.ts66
-rw-r--r--runtime/js/99_main.js6
12 files changed, 277 insertions, 100 deletions
diff --git a/cli/dts/lib.deno.window.d.ts b/cli/dts/lib.deno.window.d.ts
index da1b25565..721c89af2 100644
--- a/cli/dts/lib.deno.window.d.ts
+++ b/cli/dts/lib.deno.window.d.ts
@@ -49,3 +49,75 @@ declare function confirm(message?: string): boolean;
* @param defaultValue
*/
declare function prompt(message?: string, defaultValue?: string): string | null;
+
+// TODO(nayeemrmn): Move this to `op_crates/web` where its implementation is.
+// The types there must first be split into window, worker and global types.
+/** The location (URL) of the object it is linked to. Changes done on it are
+ * reflected on the object it relates to. Accessible via
+ * `globalThis.location`. */
+declare class Location {
+ constructor();
+ /** Returns a DOMStringList object listing the origins of the ancestor
+ * browsing contexts, from the parent browsing context to the top-level
+ * browsing context.
+ *
+ * Always empty in Deno. */
+ readonly ancestorOrigins: DOMStringList;
+ /** Returns the Location object's URL's fragment (includes leading "#" if
+ * non-empty).
+ *
+ * Cannot be set in Deno. */
+ hash: string;
+ /** Returns the Location object's URL's host and port (if different from the
+ * default port for the scheme).
+ *
+ * Cannot be set in Deno. */
+ host: string;
+ /** Returns the Location object's URL's host.
+ *
+ * Cannot be set in Deno. */
+ hostname: string;
+ /** Returns the Location object's URL.
+ *
+ * Cannot be set in Deno. */
+ href: string;
+ toString(): string;
+ /** Returns the Location object's URL's origin. */
+ readonly origin: string;
+ /** Returns the Location object's URL's path.
+ *
+ * Cannot be set in Deno. */
+ pathname: string;
+ /** Returns the Location object's URL's port.
+ *
+ * Cannot be set in Deno. */
+ port: string;
+ /** Returns the Location object's URL's scheme.
+ *
+ * Cannot be set in Deno. */
+ protocol: string;
+ /** Returns the Location object's URL's query (includes leading "?" if
+ * non-empty).
+ *
+ * Cannot be set in Deno. */
+ search: string;
+ /** Navigates to the given URL.
+ *
+ * Cannot be set in Deno. */
+ assign(url: string): void;
+ /** Reloads the current page.
+ *
+ * Disabled in Deno. */
+ reload(): void;
+ /** @deprecated */
+ reload(forcedReload: boolean): void;
+ /** Removes the current page from the session history and navigates to the
+ * given URL.
+ *
+ * Disabled in Deno. */
+ replace(url: string): void;
+}
+
+// TODO(nayeemrmn): Move this to `op_crates/web` where its implementation is.
+// The types there must first be split into window, worker and global types.
+declare var location: Location;
diff --git a/cli/dts/lib.deno.worker.d.ts b/cli/dts/lib.deno.worker.d.ts
index 74609e8ab..a8f42f336 100644
--- a/cli/dts/lib.deno.worker.d.ts
+++ b/cli/dts/lib.deno.worker.d.ts
@@ -58,3 +58,26 @@ declare var onerror:
declare var close: () => void;
declare var name: string;
declare var postMessage: (message: any) => void;
+
+// TODO(nayeemrmn): Move this to `op_crates/web` where its implementation is.
+// The types there must first be split into window, worker and global types.
+/** The absolute location of the script executed by the Worker. Such an object
+ * is initialized for each worker and is available via the
+ * WorkerGlobalScope.location property obtained by calling self.location. */
+declare class WorkerLocation {
+ constructor();
+ readonly hash: string;
+ readonly host: string;
+ readonly hostname: string;
+ readonly href: string;
+ toString(): string;
+ readonly origin: string;
+ readonly pathname: string;
+ readonly port: string;
+ readonly protocol: string;
+ readonly search: string;
+}
+
+// TODO(nayeemrmn): Move this to `op_crates/web` where its implementation is.
+// The types there must first be split into window, worker and global types.
+declare var location: WorkerLocation;
diff --git a/cli/flags.rs b/cli/flags.rs
index a994b3f0c..9fe25df50 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -1437,7 +1437,10 @@ fn location_arg<'a, 'b>() -> Arg<'a, 'b> {
if url.is_err() {
return Err("Failed to parse URL".to_string());
}
- if !["http", "https"].contains(&url.unwrap().scheme()) {
+ let mut url = url.unwrap();
+ url.set_username("").unwrap();
+ url.set_password(None).unwrap();
+ if !["http", "https"].contains(&url.scheme()) {
return Err("Expected protocol \"http\" or \"https\"".to_string());
}
Ok(())
diff --git a/cli/tests/070_location.ts.out b/cli/tests/070_location.ts.out
index 66d470b6f..2ba0f259d 100644
--- a/cli/tests/070_location.ts.out
+++ b/cli/tests/070_location.ts.out
@@ -6,12 +6,10 @@ Location {
hostname: [Getter/Setter],
href: [Getter/Setter],
origin: [Getter],
- password: [Getter/Setter],
pathname: [Getter/Setter],
port: [Getter/Setter],
protocol: [Getter/Setter],
search: [Getter/Setter],
- username: [Getter/Setter],
ancestorOrigins: [Getter],
assign: [Function: assign],
reload: [Function: reload],
diff --git a/cli/tests/079_location_authentication.ts b/cli/tests/079_location_authentication.ts
new file mode 100644
index 000000000..4989312ac
--- /dev/null
+++ b/cli/tests/079_location_authentication.ts
@@ -0,0 +1 @@
+console.log(location.href);
diff --git a/cli/tests/079_location_authentication.ts.out b/cli/tests/079_location_authentication.ts.out
new file mode 100644
index 000000000..bb2458497
--- /dev/null
+++ b/cli/tests/079_location_authentication.ts.out
@@ -0,0 +1,3 @@
+[WILDCARD]
+https://baz/qux
+[WILDCARD]
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index 586c405e3..9c64a9e07 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -2651,6 +2651,11 @@ itest!(_078_unload_on_exit {
output: "078_unload_on_exit.ts.out",
});
+itest!(_079_location_authentication {
+ args: "run --location https://foo:bar@baz/qux 079_location_authentication.ts",
+ output: "079_location_authentication.ts.out",
+});
+
itest!(js_import_detect {
args: "run --quiet --reload js_import_detect.ts",
output: "js_import_detect.ts.out",
diff --git a/cli/tests/subdir/worker_location.ts b/cli/tests/subdir/worker_location.ts
index 480032350..89fa83036 100644
--- a/cli/tests/subdir/worker_location.ts
+++ b/cli/tests/subdir/worker_location.ts
@@ -1,4 +1,6 @@
onmessage = function (): void {
- postMessage(self.location.href);
+ postMessage(
+ `${location.href}, ${location instanceof WorkerLocation}`,
+ );
close();
};
diff --git a/cli/tests/workers_test.ts b/cli/tests/workers_test.ts
index 2ea6f6cf5..66444411e 100644
--- a/cli/tests/workers_test.ts
+++ b/cli/tests/workers_test.ts
@@ -648,7 +648,7 @@ Deno.test({
new URL("subdir/worker_location.ts", import.meta.url).href;
const w = new Worker(workerModuleHref, { type: "module" });
w.onmessage = (e): void => {
- assertEquals(e.data, workerModuleHref);
+ assertEquals(e.data, `${workerModuleHref}, true`);
promise.resolve();
};
w.postMessage("Hello, world!");
diff --git a/op_crates/web/12_location.js b/op_crates/web/12_location.js
index 79a9151f1..d6a132413 100644
--- a/op_crates/web/12_location.js
+++ b/op_crates/web/12_location.js
@@ -4,12 +4,19 @@
const { URL } = window.__bootstrap.url;
const locationConstructorKey = Symbol("locationConstuctorKey");
+ // The differences between the definitions of `Location` and `WorkerLocation`
+ // are because of the `LegacyUnforgeable` attribute only specified upon
+ // `Location`'s properties. See:
+ // - https://html.spec.whatwg.org/multipage/history.html#the-location-interface
+ // - https://heycam.github.io/webidl/#LegacyUnforgeable
class Location {
- constructor(href, key) {
+ constructor(href = null, key = null) {
if (key != locationConstructorKey) {
throw new TypeError("Illegal constructor.");
}
const url = new URL(href);
+ url.username = "";
+ url.password = "";
Object.defineProperties(this, {
hash: {
get() {
@@ -49,7 +56,7 @@
},
href: {
get() {
- return href;
+ return url.href;
},
set() {
throw new DOMException(
@@ -65,18 +72,6 @@
},
enumerable: true,
},
- password: {
- get() {
- return url.password;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.password".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
pathname: {
get() {
return url.pathname;
@@ -125,18 +120,6 @@
},
enumerable: true,
},
- username: {
- get() {
- return url.username;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.username".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
ancestorOrigins: {
get() {
// TODO(nayeemrmn): Replace with a `DOMStringList` instance.
@@ -177,7 +160,7 @@
},
toString: {
value: function toString() {
- return href;
+ return url.href;
},
enumerable: true,
},
@@ -192,10 +175,144 @@
},
});
+ const workerLocationUrls = new WeakMap();
+
+ class WorkerLocation {
+ constructor(href = null, key = null) {
+ if (key != locationConstructorKey) {
+ throw new TypeError("Illegal constructor.");
+ }
+ const url = new URL(href);
+ url.username = "";
+ url.password = "";
+ workerLocationUrls.set(this, url);
+ }
+ }
+
+ Object.defineProperties(WorkerLocation.prototype, {
+ hash: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.hash;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ host: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.host;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ hostname: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.hostname;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ href: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.href;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ origin: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.origin;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ pathname: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.pathname;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ port: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.port;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ protocol: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.protocol;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ search: {
+ get() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.search;
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ toString: {
+ value: function toString() {
+ const url = workerLocationUrls.get(this);
+ if (url == null) {
+ throw new TypeError("Illegal invocation.");
+ }
+ return url.href;
+ },
+ configurable: true,
+ enumerable: true,
+ writable: true,
+ },
+ [Symbol.toStringTag]: {
+ value: "WorkerLocation",
+ configurable: true,
+ },
+ });
+
let location = null;
+ let workerLocation = null;
function setLocationHref(href) {
location = new Location(href, locationConstructorKey);
+ workerLocation = new WorkerLocation(href, locationConstructorKey);
}
window.__bootstrap = (window.__bootstrap || {});
@@ -205,6 +322,11 @@
configurable: true,
writable: true,
},
+ workerLocationConstructorDescriptor: {
+ value: WorkerLocation,
+ configurable: true,
+ writable: true,
+ },
locationDescriptor: {
get() {
if (location == null) {
@@ -219,6 +341,18 @@
},
enumerable: true,
},
+ workerLocationDescriptor: {
+ get() {
+ if (workerLocation == null) {
+ throw new Error(
+ `Assertion: "globalThis.location" must be defined in a worker.`,
+ );
+ }
+ return workerLocation;
+ },
+ configurable: true,
+ enumerable: true,
+ },
setLocationHref,
getLocationHref() {
return location?.href;
diff --git a/op_crates/web/lib.deno_web.d.ts b/op_crates/web/lib.deno_web.d.ts
index e9a6bc8ee..79b56f68e 100644
--- a/op_crates/web/lib.deno_web.d.ts
+++ b/op_crates/web/lib.deno_web.d.ts
@@ -313,69 +313,3 @@ declare var FileReader: {
readonly EMPTY: number;
readonly LOADING: number;
};
-
-/** The location (URL) of the object it is linked to. Changes done on it are
- * reflected on the object it relates to. Accessible via
- * `globalThis.location`. */
-declare class Location {
- constructor();
- /** Returns a DOMStringList object listing the origins of the ancestor
- * browsing contexts, from the parent browsing context to the top-level
- * browsing context.
- *
- * Always empty in Deno. */
- readonly ancestorOrigins: DOMStringList;
- /** Returns the Location object's URL's fragment (includes leading "#" if non-empty).
- *
- * Cannot be set in Deno. */
- hash: string;
- /** Returns the Location object's URL's host and port (if different from the default port for the scheme).
- *
- * Cannot be set in Deno. */
- host: string;
- /** Returns the Location object's URL's host.
- *
- * Cannot be set in Deno. */
- hostname: string;
- /** Returns the Location object's URL.
- *
- * Cannot be set in Deno. */
- href: string;
- toString(): string;
- /** Returns the Location object's URL's origin. */
- readonly origin: string;
- /** Returns the Location object's URL's path.
- *
- * Cannot be set in Deno. */
- pathname: string;
- /** Returns the Location object's URL's port.
- *
- * Cannot be set in Deno. */
- port: string;
- /** Returns the Location object's URL's scheme.
- *
- * Cannot be set in Deno. */
- protocol: string;
- /** Returns the Location object's URL's query (includes leading "?" if
- * non-empty).
- *
- * Cannot be set in Deno. */
- search: string;
- /** Navigates to the given URL.
- *
- * Cannot be set in Deno. */
- assign(url: string): void;
- /** Reloads the current page.
- *
- * Disabled in Deno. */
- reload(): void;
- /** @deprecated */
- reload(forcedReload: boolean): void;
- /** Removes the current page from the session history and navigates to the
- * given URL.
- *
- * Disabled in Deno. */
- replace(url: string): void;
-}
-
-declare var location: Location;
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index b55074355..a6abc8d27 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -197,8 +197,6 @@ delete Object.prototype.__proto__;
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
const windowOrWorkerGlobalScope = {
- Location: location.locationConstructorDescriptor,
- location: location.locationDescriptor,
Blob: util.nonEnumerable(fetch.Blob),
ByteLengthQueuingStrategy: util.nonEnumerable(
streams.ByteLengthQueuingStrategy,
@@ -257,6 +255,8 @@ delete Object.prototype.__proto__;
windowOrWorkerGlobalScope.console.enumerable = false;
const mainRuntimeGlobalProperties = {
+ Location: location.locationConstructorDescriptor,
+ location: location.locationDescriptor,
Window: globalInterfaces.windowConstructorDescriptor,
window: util.readOnly(globalThis),
self: util.readOnly(globalThis),
@@ -272,6 +272,8 @@ delete Object.prototype.__proto__;
};
const workerRuntimeGlobalProperties = {
+ WorkerLocation: location.workerLocationConstructorDescriptor,
+ location: location.workerLocationDescriptor,
WorkerGlobalScope: globalInterfaces.workerGlobalScopeConstructorDescriptor,
DedicatedWorkerGlobalScope:
globalInterfaces.dedicatedWorkerGlobalScopeConstructorDescriptor,