mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
Add --prefetch flag for deps prefetch without running (#1475)
This commit is contained in:
parent
ac6ac5037f
commit
c870cf4082
13 changed files with 99 additions and 17 deletions
|
@ -127,7 +127,7 @@ int deno_execute(Deno* d_, void* user_data, const char* js_filename,
|
|||
}
|
||||
|
||||
int deno_execute_mod(Deno* d_, void* user_data, const char* js_filename,
|
||||
const char* js_source) {
|
||||
const char* js_source, int resolve_only) {
|
||||
auto* d = unwrap(d_);
|
||||
deno::UserDataScope user_data_scope(d, user_data);
|
||||
auto* isolate = d->isolate_;
|
||||
|
@ -136,7 +136,8 @@ int deno_execute_mod(Deno* d_, void* user_data, const char* js_filename,
|
|||
v8::HandleScope handle_scope(isolate);
|
||||
auto context = d->context_.Get(d->isolate_);
|
||||
CHECK(!context.IsEmpty());
|
||||
return deno::ExecuteMod(context, js_filename, js_source) ? 1 : 0;
|
||||
return deno::ExecuteMod(context, js_filename, js_source, resolve_only) ? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
int deno_respond(Deno* d_, void* user_data, int32_t req_id, deno_buf buf) {
|
||||
|
|
|
@ -590,7 +590,7 @@ void DenoIsolate::ResolveOk(const char* filename, const char* source) {
|
|||
}
|
||||
|
||||
bool ExecuteMod(v8::Local<v8::Context> context, const char* js_filename,
|
||||
const char* js_source) {
|
||||
const char* js_source, bool resolve_only) {
|
||||
auto* isolate = context->GetIsolate();
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
@ -616,6 +616,11 @@ bool ExecuteMod(v8::Local<v8::Context> context, const char* js_filename,
|
|||
}
|
||||
|
||||
CHECK_EQ(v8::Module::kInstantiated, module->GetStatus());
|
||||
|
||||
if (resolve_only) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto result = module->Evaluate(context);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
|
|
|
@ -75,8 +75,11 @@ int deno_execute(Deno* d, void* user_data, const char* js_filename,
|
|||
// when instantiating the Deno object.
|
||||
// Return value: 0 = fail, 1 = success
|
||||
// Get error text with deno_last_exception().
|
||||
// If resolve_only is 0, compile and evaluate the module.
|
||||
// If resolve_only is 1, compile and collect dependencies of the module
|
||||
// without running the code.
|
||||
int deno_execute_mod(Deno* d, void* user_data, const char* js_filename,
|
||||
const char* js_source);
|
||||
const char* js_source, int resolve_only);
|
||||
|
||||
// deno_respond sends up to one message back for every deno_recv_cb made.
|
||||
//
|
||||
|
|
|
@ -145,7 +145,7 @@ void DeleteDataRef(DenoIsolate* d, int32_t req_id);
|
|||
bool Execute(v8::Local<v8::Context> context, const char* js_filename,
|
||||
const char* js_source);
|
||||
bool ExecuteMod(v8::Local<v8::Context> context, const char* js_filename,
|
||||
const char* js_source);
|
||||
const char* js_source, bool resolve_only);
|
||||
|
||||
} // namespace deno
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ TEST(LibDenoTest, ModuleResolution) {
|
|||
deno_resolve_ok(d, "b.js", mod_b);
|
||||
};
|
||||
Deno* d = deno_new(deno_config{0, empty, empty, nullptr, resolve_cb});
|
||||
EXPECT_TRUE(deno_execute_mod(d, d, "a.js", mod_a));
|
||||
EXPECT_TRUE(deno_execute_mod(d, d, "a.js", mod_a, false));
|
||||
EXPECT_EQ(count, 1);
|
||||
deno_delete(d);
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ TEST(LibDenoTest, ModuleResolutionFail) {
|
|||
// Do not call deno_resolve_ok();
|
||||
};
|
||||
Deno* d = deno_new(deno_config{0, empty, empty, nullptr, resolve_cb});
|
||||
EXPECT_FALSE(deno_execute_mod(d, d, "a.js", mod_a));
|
||||
EXPECT_FALSE(deno_execute_mod(d, d, "a.js", mod_a, false));
|
||||
EXPECT_EQ(count, 1);
|
||||
deno_delete(d);
|
||||
}
|
||||
|
@ -309,7 +309,8 @@ TEST(LibDenoTest, ModuleSnapshot) {
|
|||
EXPECT_TRUE(deno_execute_mod(d1, nullptr, "x.js",
|
||||
"const globalEval = eval\n"
|
||||
"const global = globalEval('this')\n"
|
||||
"global.a = 1 + 2"));
|
||||
"global.a = 1 + 2",
|
||||
0));
|
||||
deno_buf test_snapshot = deno_get_snapshot(d1);
|
||||
deno_delete(d1);
|
||||
|
||||
|
@ -321,12 +322,32 @@ TEST(LibDenoTest, ModuleSnapshot) {
|
|||
deno_delete(d2);
|
||||
|
||||
Deno* d3 = deno_new(config);
|
||||
EXPECT_TRUE(deno_execute_mod(d3, nullptr, "y.js", y_src));
|
||||
EXPECT_TRUE(deno_execute_mod(d3, nullptr, "y.js", y_src, false));
|
||||
deno_delete(d3);
|
||||
|
||||
delete[] test_snapshot.data_ptr;
|
||||
}
|
||||
|
||||
TEST(LibDenoTest, ModuleResolveOnly) {
|
||||
static int count = 0;
|
||||
auto resolve_cb = [](void* user_data, const char* specifier,
|
||||
const char* referrer) {
|
||||
EXPECT_STREQ(specifier, "b.js");
|
||||
EXPECT_STREQ(referrer, "a.js");
|
||||
count++;
|
||||
auto d = reinterpret_cast<Deno*>(user_data);
|
||||
deno_resolve_ok(d, "b.js", mod_b);
|
||||
};
|
||||
Deno* d = deno_new(deno_config{0, empty, empty, nullptr, resolve_cb});
|
||||
// Code should not execute. If executed, the error would be thrown
|
||||
EXPECT_TRUE(deno_execute_mod(d, d, "a.js",
|
||||
"import { retb } from 'b.js'\n"
|
||||
"throw Error('unreachable');",
|
||||
true));
|
||||
EXPECT_EQ(count, 1);
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(LibDenoTest, BuiltinModules) {
|
||||
static int count = 0;
|
||||
auto resolve_cb = [](void* user_data, const char* specifier,
|
||||
|
@ -347,7 +368,8 @@ TEST(LibDenoTest, BuiltinModules) {
|
|||
"import * as deno from 'deno'\n"
|
||||
"if (retb() != 'b') throw Error('retb');\n"
|
||||
// " libdeno.print('deno ' + JSON.stringify(deno));\n"
|
||||
"if (deno.foo != 'bar') throw Error('foo');\n"));
|
||||
"if (deno.foo != 'bar') throw Error('foo');\n",
|
||||
false));
|
||||
EXPECT_EQ(count, 1);
|
||||
deno_delete(d);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ pub struct DenoFlags {
|
|||
pub allow_env: bool,
|
||||
pub allow_run: bool,
|
||||
pub types: bool,
|
||||
pub prefetch: bool,
|
||||
}
|
||||
|
||||
pub fn get_usage(opts: &Options) -> String {
|
||||
|
@ -107,6 +108,9 @@ fn set_recognized_flags(
|
|||
if matches.opt_present("types") {
|
||||
flags.types = true;
|
||||
}
|
||||
if matches.opt_present("prefetch") {
|
||||
flags.prefetch = true;
|
||||
}
|
||||
|
||||
if !matches.free.is_empty() {
|
||||
rest.extend(matches.free);
|
||||
|
@ -142,6 +146,7 @@ pub fn set_flags(
|
|||
opts.optflag("r", "reload", "Reload cached remote resources.");
|
||||
opts.optflag("", "v8-options", "Print V8 command line options.");
|
||||
opts.optflag("", "types", "Print runtime TypeScript declarations.");
|
||||
opts.optflag("", "prefetch", "Prefetch the dependencies.");
|
||||
|
||||
let mut flags = DenoFlags::default();
|
||||
|
||||
|
|
|
@ -254,7 +254,11 @@ impl Isolate {
|
|||
}
|
||||
|
||||
/// Executes the provided JavaScript module.
|
||||
pub fn execute_mod(&self, js_filename: &str) -> Result<(), JSError> {
|
||||
pub fn execute_mod(
|
||||
&self,
|
||||
js_filename: &str,
|
||||
is_prefetch: bool,
|
||||
) -> Result<(), JSError> {
|
||||
let out =
|
||||
code_fetch_and_maybe_compile(&self.state, js_filename, ".").unwrap();
|
||||
|
||||
|
@ -271,6 +275,7 @@ impl Isolate {
|
|||
self.as_raw_ptr(),
|
||||
filename_ptr,
|
||||
js_source_ptr,
|
||||
if is_prefetch { 1 } else { 0 },
|
||||
)
|
||||
};
|
||||
if r == 0 {
|
||||
|
@ -662,7 +667,9 @@ mod tests {
|
|||
let snapshot = libdeno::deno_buf::empty();
|
||||
let isolate = Isolate::new(snapshot, state, dispatch_sync);
|
||||
tokio_util::init(|| {
|
||||
isolate.execute_mod(filename).expect("execute_mod error");
|
||||
isolate
|
||||
.execute_mod(filename, false)
|
||||
.expect("execute_mod error");
|
||||
isolate.event_loop().ok();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ extern "C" {
|
|||
user_data: *const c_void,
|
||||
js_filename: *const c_char,
|
||||
js_source: *const c_char,
|
||||
resolve_only: i32,
|
||||
) -> c_int;
|
||||
pub fn deno_resolve_ok(
|
||||
i: *const isolate,
|
||||
|
|
|
@ -79,6 +79,8 @@ fn main() {
|
|||
log::LevelFilter::Warn
|
||||
});
|
||||
|
||||
let should_prefetch = flags.prefetch;
|
||||
|
||||
let state = Arc::new(isolate::IsolateState::new(flags, rest_argv, None));
|
||||
let snapshot = snapshot::deno_snapshot();
|
||||
let isolate = isolate::Isolate::new(snapshot, state, ops::dispatch);
|
||||
|
@ -93,7 +95,7 @@ fn main() {
|
|||
if isolate.state.argv.len() > 1 {
|
||||
let input_filename = &isolate.state.argv[1];
|
||||
isolate
|
||||
.execute_mod(input_filename)
|
||||
.execute_mod(input_filename, should_prefetch)
|
||||
.unwrap_or_else(print_err_and_exit);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,7 @@ import os
|
|||
import re
|
||||
import sys
|
||||
import subprocess
|
||||
from util import pattern_match, green_ok, red_failed
|
||||
|
||||
root_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
tests_path = os.path.join(root_path, "tests")
|
||||
from util import root_path, tests_path, pattern_match, green_ok, red_failed
|
||||
|
||||
|
||||
def read_test(file_name):
|
||||
|
|
35
tools/prefetch_test.py
Executable file
35
tools/prefetch_test.py
Executable file
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||
import os
|
||||
import sys
|
||||
from util import tests_path, run_output, build_path, executable_suffix, green_ok
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
|
||||
def prefetch_test(deno_exe):
|
||||
sys.stdout.write("prefetch_test...")
|
||||
sys.stdout.flush()
|
||||
|
||||
# On Windows, set the base directory that mkdtemp() uses explicitly. If not,
|
||||
# it'll use the short (8.3) path to the temp dir, which triggers the error
|
||||
# 'TS5009: Cannot find the common subdirectory path for the input files.'
|
||||
temp_dir = os.environ["TEMP"] if os.name == 'nt' else None
|
||||
deno_dir = tempfile.mkdtemp(dir=temp_dir)
|
||||
try:
|
||||
t = os.path.join(tests_path, "006_url_imports.ts")
|
||||
output = run_output([deno_exe, "--prefetch", t],
|
||||
merge_env={"DENO_DIR": deno_dir})
|
||||
assert output == ""
|
||||
# Check that we actually did the prefetch.
|
||||
os.path.exists(
|
||||
os.path.join(deno_dir,
|
||||
"deps/http/localhost_PORT4545/tests/subdir/mod2.ts"))
|
||||
finally:
|
||||
shutil.rmtree(deno_dir)
|
||||
|
||||
print green_ok()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
prefetch_test(sys.argv[1])
|
|
@ -12,6 +12,7 @@ from unit_tests import unit_tests
|
|||
from util_test import util_test
|
||||
from benchmark_test import benchmark_test
|
||||
from repl_test import repl_tests
|
||||
from prefetch_test import prefetch_test
|
||||
import subprocess
|
||||
import http_server
|
||||
|
||||
|
@ -59,6 +60,8 @@ def main(argv):
|
|||
|
||||
unit_tests(deno_exe)
|
||||
|
||||
prefetch_test(deno_exe)
|
||||
|
||||
integration_tests(deno_exe)
|
||||
|
||||
# TODO We currently skip testing the prompt in Windows completely.
|
||||
|
|
|
@ -12,6 +12,7 @@ FG_GREEN = "\x1b[32m"
|
|||
|
||||
executable_suffix = ".exe" if os.name == "nt" else ""
|
||||
root_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
tests_path = os.path.join(root_path, "tests")
|
||||
|
||||
|
||||
def make_env(merge_env=None, env=None):
|
||||
|
|
Loading…
Reference in a new issue