mirror of
https://github.com/denoland/deno
synced 2024-08-25 02:57:22 +00:00
Add window.location
This commit is contained in:
parent
27afbd1351
commit
42408febe8
1
BUILD.gn
1
BUILD.gn
|
@ -80,6 +80,7 @@ ts_sources = [
|
|||
"js/io.ts",
|
||||
"js/libdeno.ts",
|
||||
"js/lib.web_assembly.d.ts",
|
||||
"js/location.ts",
|
||||
"js/main.ts",
|
||||
"js/make_temp_dir.ts",
|
||||
"js/metrics.ts",
|
||||
|
|
|
@ -536,3 +536,73 @@ export interface Response extends Body {
|
|||
/** Creates a clone of a `Response` object. */
|
||||
clone(): Response;
|
||||
}
|
||||
|
||||
export interface Location {
|
||||
/**
|
||||
* Returns a DOMStringList object listing the origins of the ancestor browsing
|
||||
* contexts, from the parent browsing context to the top-level browsing
|
||||
* context.
|
||||
*/
|
||||
readonly ancestorOrigins: string[];
|
||||
/**
|
||||
* Returns the Location object's URL's fragment (includes leading "#" if
|
||||
* non-empty).
|
||||
* Can be set, to navigate to the same URL with a changed fragment (ignores
|
||||
* leading "#").
|
||||
*/
|
||||
hash: string;
|
||||
/**
|
||||
* Returns the Location object's URL's host and port (if different from the
|
||||
* default port for the scheme). Can be set, to navigate to the same URL with
|
||||
* a changed host and port.
|
||||
*/
|
||||
host: string;
|
||||
/**
|
||||
* Returns the Location object's URL's host. Can be set, to navigate to the
|
||||
* same URL with a changed host.
|
||||
*/
|
||||
hostname: string;
|
||||
/**
|
||||
* Returns the Location object's URL. Can be set, to navigate to the given
|
||||
* URL.
|
||||
*/
|
||||
href: string;
|
||||
/** Returns the Location object's URL's origin. */
|
||||
readonly origin: string;
|
||||
/**
|
||||
* Returns the Location object's URL's path.
|
||||
* Can be set, to navigate to the same URL with a changed path.
|
||||
*/
|
||||
pathname: string;
|
||||
/**
|
||||
* Returns the Location object's URL's port.
|
||||
* Can be set, to navigate to the same URL with a changed port.
|
||||
*/
|
||||
port: string;
|
||||
/**
|
||||
* Returns the Location object's URL's scheme.
|
||||
* Can be set, to navigate to the same URL with a changed scheme.
|
||||
*/
|
||||
protocol: string;
|
||||
/**
|
||||
* Returns the Location object's URL's query (includes leading "?" if
|
||||
* non-empty). Can be set, to navigate to the same URL with a changed query
|
||||
* (ignores leading "?").
|
||||
*/
|
||||
search: string;
|
||||
/**
|
||||
* Navigates to the given URL.
|
||||
*/
|
||||
assign(url: string): void;
|
||||
/**
|
||||
* Reloads the current page.
|
||||
*/
|
||||
reload(): void;
|
||||
/** @deprecated */
|
||||
reload(forcedReload: boolean): void;
|
||||
/**
|
||||
* Removes the current page from the session history and navigates to the
|
||||
* given URL.
|
||||
*/
|
||||
replace(url: string): void;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ window.clearInterval = timers.clearTimer;
|
|||
window.console = new consoleTypes.Console(libdeno.print);
|
||||
window.setTimeout = timers.setTimeout;
|
||||
window.setInterval = timers.setInterval;
|
||||
// tslint:disable-next-line:no-any
|
||||
window.location = (undefined as unknown) as domTypes.Location;
|
||||
|
||||
// When creating the runtime type library, we use modifications to `window` to
|
||||
// determine what is in the global namespace. When we put a class in the
|
||||
|
|
5
js/lib.web_assembly.d.ts
vendored
5
js/lib.web_assembly.d.ts
vendored
|
@ -161,3 +161,8 @@ declare namespace WebAssembly {
|
|||
constructor(message: string, fileName?: string, lineNumber?: string);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Move ImportMeta intos its own lib.import_meta.d.ts file?
|
||||
interface ImportMeta {
|
||||
url: string;
|
||||
}
|
||||
|
|
52
js/location.ts
Normal file
52
js/location.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { URL } from "./url";
|
||||
import { notImplemented } from "./util";
|
||||
import { Location } from "./dom_types";
|
||||
import { window } from "./globals";
|
||||
|
||||
export function setLocation(url: string): void {
|
||||
window.location = new LocationImpl(url);
|
||||
Object.freeze(window.location);
|
||||
}
|
||||
|
||||
export class LocationImpl implements Location {
|
||||
constructor(url: string) {
|
||||
const u = new URL(url);
|
||||
this.url = u;
|
||||
this.hash = u.hash;
|
||||
this.host = u.host;
|
||||
this.href = u.href;
|
||||
this.hostname = u.hostname;
|
||||
this.origin = u.protocol + "//" + u.host;
|
||||
this.pathname = u.pathname;
|
||||
this.protocol = u.protocol;
|
||||
this.port = u.port;
|
||||
this.search = u.search;
|
||||
}
|
||||
|
||||
private url: URL;
|
||||
|
||||
toString(): string {
|
||||
return this.url.toString();
|
||||
}
|
||||
|
||||
readonly ancestorOrigins: string[] = [];
|
||||
hash: string;
|
||||
host: string;
|
||||
hostname: string;
|
||||
href: string;
|
||||
readonly origin: string;
|
||||
pathname: string;
|
||||
port: string;
|
||||
protocol: string;
|
||||
search: string;
|
||||
assign(url: string): void {
|
||||
throw notImplemented();
|
||||
}
|
||||
reload(): void {
|
||||
throw notImplemented();
|
||||
}
|
||||
replace(url: string): void {
|
||||
throw notImplemented();
|
||||
}
|
||||
}
|
8
js/location_test.ts
Normal file
8
js/location_test.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { test, assert } from "./test_util.ts";
|
||||
|
||||
test(function locationBasic() {
|
||||
// location example: file:///Users/rld/src/deno/js/unit_tests.ts
|
||||
console.log("location", window.location.toString());
|
||||
assert(window.location.toString().endsWith("unit_tests.ts"));
|
||||
});
|
12
js/main.ts
12
js/main.ts
|
@ -4,12 +4,13 @@
|
|||
|
||||
import "./globals";
|
||||
|
||||
import { log } from "./util";
|
||||
import { assert, log } from "./util";
|
||||
import * as os from "./os";
|
||||
import { libdeno } from "./libdeno";
|
||||
import { args } from "./deno";
|
||||
import { replLoop } from "./repl";
|
||||
import { setVersions } from "./version";
|
||||
import { setLocation } from "./location";
|
||||
|
||||
// builtin modules
|
||||
import * as deno from "./deno";
|
||||
|
@ -42,6 +43,12 @@ export default function denoMain() {
|
|||
os.exit(0);
|
||||
}
|
||||
|
||||
const mainModule = startResMsg.mainModule();
|
||||
if (mainModule) {
|
||||
assert(mainModule.length > 0);
|
||||
setLocation(mainModule);
|
||||
}
|
||||
|
||||
const cwd = startResMsg.cwd();
|
||||
log("cwd", cwd);
|
||||
|
||||
|
@ -51,8 +58,7 @@ export default function denoMain() {
|
|||
log("args", args);
|
||||
Object.freeze(args);
|
||||
|
||||
const inputFn = args[0];
|
||||
if (!inputFn) {
|
||||
if (!mainModule) {
|
||||
replLoop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import "./files_test.ts";
|
|||
import "./form_data_test.ts";
|
||||
import "./globals_test.ts";
|
||||
import "./headers_test.ts";
|
||||
import "./location_test.ts";
|
||||
import "./make_temp_dir_test.ts";
|
||||
import "./metrics_test.ts";
|
||||
import "./mixins/dom_iterable_test.ts";
|
||||
|
|
|
@ -400,14 +400,11 @@ impl DenoDir {
|
|||
}
|
||||
|
||||
/// Returns (module name, local filename)
|
||||
pub fn resolve_module(
|
||||
pub fn resolve_module_url(
|
||||
self: &Self,
|
||||
specifier: &str,
|
||||
referrer: &str,
|
||||
) -> Result<(String, String), url::ParseError> {
|
||||
let module_name;
|
||||
let filename;
|
||||
|
||||
) -> Result<Url, url::ParseError> {
|
||||
let specifier = self.src_file_to_url(specifier);
|
||||
let mut referrer = self.src_file_to_url(referrer);
|
||||
|
||||
|
@ -422,8 +419,7 @@ impl DenoDir {
|
|||
referrer = referrer_path.to_str().unwrap().to_string() + "/";
|
||||
}
|
||||
|
||||
let j: Url = if is_remote(&specifier) || Path::new(&specifier).is_absolute()
|
||||
{
|
||||
let j = if is_remote(&specifier) || Path::new(&specifier).is_absolute() {
|
||||
parse_local_or_remote(&specifier)?
|
||||
} else if referrer.ends_with('/') {
|
||||
let r = Url::from_directory_path(&referrer);
|
||||
|
@ -437,21 +433,29 @@ impl DenoDir {
|
|||
let base = parse_local_or_remote(&referrer)?;
|
||||
base.join(specifier.as_ref())?
|
||||
};
|
||||
Ok(j)
|
||||
}
|
||||
|
||||
/// Returns (module name, local filename)
|
||||
pub fn resolve_module(
|
||||
self: &Self,
|
||||
specifier: &str,
|
||||
referrer: &str,
|
||||
) -> Result<(String, String), url::ParseError> {
|
||||
let j = self.resolve_module_url(specifier, referrer)?;
|
||||
|
||||
let module_name = j.to_string();
|
||||
let filename;
|
||||
match j.scheme() {
|
||||
"file" => {
|
||||
let p = deno_fs::normalize_path(j.to_file_path().unwrap().as_ref());
|
||||
module_name = p.clone();
|
||||
filename = p;
|
||||
filename = deno_fs::normalize_path(j.to_file_path().unwrap().as_ref());
|
||||
}
|
||||
"https" => {
|
||||
module_name = j.to_string();
|
||||
filename = deno_fs::normalize_path(
|
||||
get_cache_filename(self.deps_https.as_path(), &j).as_ref(),
|
||||
)
|
||||
}
|
||||
"http" => {
|
||||
module_name = j.to_string();
|
||||
filename = deno_fs::normalize_path(
|
||||
get_cache_filename(self.deps_http.as_path(), &j).as_ref(),
|
||||
)
|
||||
|
@ -517,7 +521,7 @@ fn is_remote(module_name: &str) -> bool {
|
|||
}
|
||||
|
||||
fn parse_local_or_remote(p: &str) -> Result<url::Url, url::ParseError> {
|
||||
if is_remote(p) {
|
||||
if is_remote(p) || p.starts_with("file:") {
|
||||
Url::parse(p)
|
||||
} else {
|
||||
Url::from_file_path(p).map_err(|_err| url::ParseError::IdnaError)
|
||||
|
@ -605,6 +609,16 @@ mod tests {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! file_url {
|
||||
($path:expr) => {
|
||||
if cfg!(target_os = "windows") {
|
||||
concat!("file:///C:", $path)
|
||||
} else {
|
||||
concat!("file://", $path)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_cache_filename() {
|
||||
let url = Url::parse("http://example.com:1234/path/to/file.ts").unwrap();
|
||||
|
@ -1019,25 +1033,25 @@ mod tests {
|
|||
(
|
||||
"./subdir/print_hello.ts",
|
||||
add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/006_url_imports.ts"),
|
||||
add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/subdir/print_hello.ts"),
|
||||
file_url!("/Users/rld/go/src/github.com/denoland/deno/testdata/subdir/print_hello.ts"),
|
||||
add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/subdir/print_hello.ts"),
|
||||
),
|
||||
(
|
||||
"testdata/001_hello.js",
|
||||
add_root!("/Users/rld/go/src/github.com/denoland/deno/"),
|
||||
add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/001_hello.js"),
|
||||
file_url!("/Users/rld/go/src/github.com/denoland/deno/testdata/001_hello.js"),
|
||||
add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/001_hello.js"),
|
||||
),
|
||||
(
|
||||
add_root!("/Users/rld/src/deno/hello.js"),
|
||||
".",
|
||||
add_root!("/Users/rld/src/deno/hello.js"),
|
||||
file_url!("/Users/rld/src/deno/hello.js"),
|
||||
add_root!("/Users/rld/src/deno/hello.js"),
|
||||
),
|
||||
(
|
||||
add_root!("/this/module/got/imported.js"),
|
||||
add_root!("/that/module/did/it.js"),
|
||||
add_root!("/this/module/got/imported.js"),
|
||||
file_url!("/this/module/got/imported.js"),
|
||||
add_root!("/this/module/got/imported.js"),
|
||||
),
|
||||
];
|
||||
|
@ -1169,8 +1183,7 @@ mod tests {
|
|||
|
||||
let specifier = "http_test.ts";
|
||||
let referrer = add_root!("/Users/rld/src/deno_net/");
|
||||
let expected_module_name =
|
||||
add_root!("/Users/rld/src/deno_net/http_test.ts");
|
||||
let expected_module_name = file_url!("/Users/rld/src/deno_net/http_test.ts");
|
||||
let expected_filename = add_root!("/Users/rld/src/deno_net/http_test.ts");
|
||||
|
||||
let (module_name, filename) =
|
||||
|
@ -1187,8 +1200,9 @@ mod tests {
|
|||
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
let expected_path = cwd.join(specifier);
|
||||
let expected_module_name = deno_fs::normalize_path(&expected_path);
|
||||
let expected_filename = expected_module_name.clone();
|
||||
let expected_module_name =
|
||||
Url::from_file_path(&expected_path).unwrap().to_string();
|
||||
let expected_filename = deno_fs::normalize_path(&expected_path);
|
||||
|
||||
let (module_name, filename) =
|
||||
deno_dir.resolve_module(specifier, ".").unwrap();
|
||||
|
@ -1209,8 +1223,9 @@ mod tests {
|
|||
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
let expected_path = cwd.join("..").join(specifier);
|
||||
let expected_module_name = deno_fs::normalize_path(&expected_path);
|
||||
let expected_filename = expected_module_name.clone();
|
||||
let expected_module_name =
|
||||
Url::from_file_path(&expected_path).unwrap().to_string();
|
||||
let expected_filename = deno_fs::normalize_path(&expected_path);
|
||||
|
||||
let (module_name, filename) =
|
||||
deno_dir.resolve_module(specifier, "..").unwrap();
|
||||
|
|
|
@ -100,6 +100,22 @@ impl IsolateState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn main_module(&self) -> Option<String> {
|
||||
if self.argv.len() <= 1 {
|
||||
None
|
||||
} else {
|
||||
let specifier = self.argv[1].clone();
|
||||
let referrer = ".";
|
||||
match self.dir.resolve_module_url(&specifier, referrer) {
|
||||
Ok(url) => Some(url.to_string()),
|
||||
Err(e) => {
|
||||
debug!("Potentially swallowed error {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn mock() -> Arc<IsolateState> {
|
||||
let argv = vec![String::from("./deno"), String::from("hello.js")];
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -105,19 +105,18 @@ fn main() {
|
|||
.map_err(errors::RustOrJsError::from)
|
||||
.unwrap_or_else(print_err_and_exit);
|
||||
|
||||
// Execute input file.
|
||||
if isolate.state.argv.len() > 1 {
|
||||
let input_filename = isolate.state.argv[1].clone();
|
||||
// Execute main module.
|
||||
if let Some(main_module) = isolate.state.main_module() {
|
||||
debug!("main_module {}", main_module);
|
||||
isolate
|
||||
.execute_mod(&input_filename, should_prefetch)
|
||||
.execute_mod(&main_module, should_prefetch)
|
||||
.unwrap_or_else(print_err_and_exit);
|
||||
|
||||
if should_display_info {
|
||||
// Display file info and exit. Do not run file
|
||||
modules::print_file_info(
|
||||
&isolate.modules.borrow(),
|
||||
&isolate.state.dir,
|
||||
input_filename,
|
||||
main_module,
|
||||
);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ table StartRes {
|
|||
pid: uint32;
|
||||
argv: [string];
|
||||
exec_path: string;
|
||||
main_module: string; // Absolute URL.
|
||||
debug_flag: bool;
|
||||
deps_flag: bool;
|
||||
types_flag: bool;
|
||||
|
|
|
@ -261,12 +261,15 @@ fn op_start(
|
|||
let deno_version = version::DENO;
|
||||
let deno_version_off = builder.create_string(deno_version);
|
||||
|
||||
let main_module = state.main_module().map(|m| builder.create_string(&m));
|
||||
|
||||
let inner = msg::StartRes::create(
|
||||
&mut builder,
|
||||
&msg::StartResArgs {
|
||||
cwd: Some(cwd_off),
|
||||
pid: std::process::id(),
|
||||
argv: Some(argv_off),
|
||||
main_module,
|
||||
debug_flag: state.flags.log_debug,
|
||||
types_flag: state.flags.types,
|
||||
version_flag: state.flags.version,
|
||||
|
|
|
@ -1 +1 @@
|
|||
[WILDCARD]Cannot resolve module "not-a-valid-filename.ts" from "."
|
||||
[WILDCARD]Cannot resolve module "file:[WILDCARD]not-a-valid-filename.ts" from "."
|
||||
|
|
2
tests/if_main.test
Normal file
2
tests/if_main.test
Normal file
|
@ -0,0 +1,2 @@
|
|||
args: tests/if_main.ts --reload
|
||||
output: tests/if_main.ts.out
|
7
tests/if_main.ts
Normal file
7
tests/if_main.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
if (window.location.toString() == import.meta.url) {
|
||||
console.log("main");
|
||||
} else {
|
||||
console.log("import.meta.url", import.meta.url);
|
||||
console.log("window.location", window.location.toString());
|
||||
throw Error("not main");
|
||||
}
|
1
tests/if_main.ts.out
Normal file
1
tests/if_main.ts.out
Normal file
|
@ -0,0 +1 @@
|
|||
main
|
2
tests/import_meta.test
Normal file
2
tests/import_meta.test
Normal file
|
@ -0,0 +1,2 @@
|
|||
args: tests/import_meta.ts --reload
|
||||
output: tests/import_meta.ts.out
|
3
tests/import_meta.ts
Normal file
3
tests/import_meta.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
console.log("import_meta", import.meta.url);
|
||||
|
||||
import "import_meta2.ts";
|
2
tests/import_meta.ts.out
Normal file
2
tests/import_meta.ts.out
Normal file
|
@ -0,0 +1,2 @@
|
|||
import_meta2 [WILDCARD]import_meta2.ts
|
||||
import_meta [WILDCARD]import_meta.ts
|
1
tests/import_meta2.ts
Normal file
1
tests/import_meta2.ts
Normal file
|
@ -0,0 +1 @@
|
|||
console.log("import_meta2", import.meta.url);
|
|
@ -1,3 +0,0 @@
|
|||
console.log("imports_meta", import.meta.url);
|
||||
|
||||
import "imports_meta2.js";
|
|
@ -1,2 +0,0 @@
|
|||
imports_meta2 [WILDCARD]imports_meta2.js
|
||||
imports_meta [WILDCARD]imports_meta.js
|
|
@ -1,2 +0,0 @@
|
|||
args: tests/imports_meta.js --reload
|
||||
output: tests/imports_meta.js.out
|
|
@ -1 +0,0 @@
|
|||
console.log("imports_meta2", import.meta.url);
|
|
@ -466,6 +466,17 @@ import { test, assertEqual } from "./package.ts";
|
|||
This design circumvents a plethora of complexity spawned by package management
|
||||
software, centralized code repositories, and superfluous file formats.
|
||||
|
||||
### Testing if current file is the main program
|
||||
|
||||
By using `window.location` and `import.meta.url` one can test if the current
|
||||
script has been executed as the main input to the program.
|
||||
|
||||
```ts
|
||||
if (window.location.toString() == import.meta.url) {
|
||||
console.log("main");
|
||||
}
|
||||
```
|
||||
|
||||
## Command line interface
|
||||
|
||||
### Flags
|
||||
|
|
Loading…
Reference in a new issue