Skip to content

Commit 3a9d970

Browse files
committed
feat: import
1 parent bfa3845 commit 3a9d970

File tree

7 files changed

+67
-24
lines changed

7 files changed

+67
-24
lines changed

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ clap = { version = "4.5.9", features = ["derive"] }
88
cliclack = "0.3.2"
99
console = "0.15.8"
1010
miette = { version = "7.2.0", features = ["fancy"] }
11-
nova_vm = { git = "https://github.com/marc2332/nova", branch = "feat/hold-global-values-across-gc-calls", features = ["typescript"] }
11+
nova_vm = { path = "../nova/nova_vm", features = ["typescript"] }
1212
oxc_ast = "0.20.0"
1313
oxc_parser = "0.20.0"
1414
oxc_span = "0.20.0"

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77
[dependencies]
88
nova_vm = { workspace = true }
99
oxc_allocator = { workspace = true }
10+
oxc_ast = { workspace = true }
1011
anymap = { workspace = true }
1112
tokio = { workspace = true }
1213
miette = { workspace = true }

core/src/runtime.rs

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::{
22
any::Any,
33
cell::RefCell,
44
collections::VecDeque,
5+
path::PathBuf,
56
sync::{atomic::Ordering, mpsc::Receiver},
67
};
78

@@ -11,17 +12,22 @@ use nova_vm::ecmascript::{
1112
agent::{HostHooks, Job, Options},
1213
initialize_host_defined_realm, Agent, JsResult, Realm,
1314
},
14-
scripts_and_modules::script::{parse_script, script_evaluation},
15+
scripts_and_modules::{
16+
script::{parse_script, script_evaluation},
17+
ScriptOrModule,
18+
},
1519
types::{Object, Value},
1620
};
1721
use oxc_allocator::Allocator;
22+
use oxc_ast::ast;
1823

1924
use crate::{
2025
exit_with_parse_errors, initialize_recommended_builtins, initialize_recommended_extensions,
2126
HostData, MacroTask,
2227
};
2328

2429
pub struct RuntimeHostHooks {
30+
allocator: Allocator,
2531
promise_job_queue: RefCell<VecDeque<Job>>,
2632
host_data: HostData,
2733
}
@@ -33,10 +39,11 @@ impl std::fmt::Debug for RuntimeHostHooks {
3339
}
3440

3541
impl RuntimeHostHooks {
36-
pub fn new(host_data: HostData) -> Self {
42+
pub fn new(host_data: HostData, allocator: Allocator) -> Self {
3743
Self {
3844
promise_job_queue: RefCell::default(),
3945
host_data,
46+
allocator,
4047
}
4148
}
4249

@@ -57,6 +64,43 @@ impl HostHooks for RuntimeHostHooks {
5764
fn get_host_data(&self) -> &dyn Any {
5865
&self.host_data
5966
}
67+
68+
// TODO: Implement a transport abstraction.
69+
fn import_module(&self, import: &ast::ImportDeclaration<'_>, agent: &mut Agent) {
70+
let realm_id = agent.current_realm_id();
71+
72+
let script_or_module = agent.running_execution_context().script_or_module.unwrap();
73+
let script_id = match script_or_module {
74+
ScriptOrModule::Script(script_id) => script_id,
75+
_ => todo!(),
76+
};
77+
let script = &agent[script_id];
78+
79+
let current_host_path = script.host_defined.as_ref().unwrap();
80+
let mut current_host_path = current_host_path
81+
.downcast_ref::<PathBuf>()
82+
.unwrap()
83+
.to_path_buf();
84+
current_host_path.pop(); // Use the parent folder
85+
let current_host_path = std::fs::canonicalize(&current_host_path).unwrap();
86+
87+
let import_path = import.source.value.as_str();
88+
let host_path = current_host_path.join(import_path);
89+
let host_path = std::fs::canonicalize(host_path).unwrap();
90+
91+
let file = std::fs::read_to_string(&host_path).unwrap();
92+
let script = match parse_script(
93+
&self.allocator,
94+
file.into(),
95+
realm_id,
96+
false,
97+
Some(Box::leak(Box::new(host_path))),
98+
) {
99+
Ok(script) => script,
100+
Err((file, errors)) => exit_with_parse_errors(errors, import_path, &file),
101+
};
102+
script_evaluation(agent, script).unwrap();
103+
}
60104
}
61105

62106
pub struct RuntimeConfig {
@@ -68,16 +112,16 @@ pub struct RuntimeConfig {
68112
pub struct Runtime {
69113
pub config: RuntimeConfig,
70114
pub agent: Agent,
71-
pub allocator: Allocator,
72115
pub host_hooks: &'static RuntimeHostHooks,
73116
pub macro_task_rx: Receiver<MacroTask>,
74117
}
75118

76119
impl Runtime {
77120
/// Create a new [Runtime] given a [RuntimeConfig]. Use [Runtime::run] to run it.
78121
pub fn new(config: RuntimeConfig) -> Self {
122+
let allocator = Allocator::default();
79123
let (host_data, macro_task_rx) = HostData::new();
80-
let host_hooks = RuntimeHostHooks::new(host_data);
124+
let host_hooks = RuntimeHostHooks::new(host_data, allocator);
81125

82126
let host_hooks: &RuntimeHostHooks = &*Box::leak(Box::new(host_hooks));
83127
let mut agent = Agent::new(
@@ -97,11 +141,9 @@ impl Runtime {
97141
Some(initialize_recommended_extensions),
98142
);
99143
}
100-
let allocator = Allocator::default();
101144

102145
Self {
103146
config,
104-
allocator,
105147
agent,
106148
host_hooks,
107149
macro_task_rx,
@@ -113,34 +155,37 @@ impl Runtime {
113155
let realm = self.agent.current_realm_id();
114156

115157
// LOad the builtins js sources
116-
initialize_recommended_builtins(&self.allocator, &mut self.agent, self.config.no_strict);
158+
initialize_recommended_builtins(
159+
&self.host_hooks.allocator,
160+
&mut self.agent,
161+
self.config.no_strict,
162+
);
117163

118164
let mut final_result = Value::Null;
119165

120166
// Fetch the runtime mod.ts file using a macro and add it to the paths
121167
for path in &self.config.paths {
122168
let file = std::fs::read_to_string(path).unwrap();
169+
let host_path = PathBuf::from(path);
123170
let script = match parse_script(
124-
&self.allocator,
171+
&self.host_hooks.allocator,
125172
file.into(),
126173
realm,
127174
!self.config.no_strict,
128-
None,
175+
Some(Box::leak(Box::new(host_path))),
129176
) {
130177
Ok(script) => script,
131178
Err((file, errors)) => exit_with_parse_errors(errors, path, &file),
132179
};
133180
final_result = match script_evaluation(&mut self.agent, script) {
134181
Ok(v) => v,
135-
err @ _ => return err,
182+
err => return err,
136183
}
137184
}
138185

139186
loop {
140187
while let Some(job) = self.host_hooks.pop_promise_job() {
141-
if let Err(err) = job.run(&mut self.agent) {
142-
return Err(err);
143-
}
188+
job.run(&mut self.agent)?;
144189
}
145190

146191
// If both the microtasks and macrotasks queues are empty we can end the event loop

examples/b.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("b.ts")

examples/main.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
/// <reference path="../runtime/global.d.ts" />
22

3-
const name = prompt("what is your name?");
4-
Andromeda.sleep(1000)
5-
.then(() => {
6-
console.log(`Hello, ${name}`);
7-
})
3+
import './sleep.ts'
84

5+
console.log("main.ts")

examples/sleep.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
[1,2,3,4].forEach((i) => {
2-
Andromeda.sleep(i * 1000).then(() => console.log(`${i}s`))
3-
})
1+
import "./b.ts"
2+
3+
console.log("sleep.ts")

0 commit comments

Comments
 (0)