diff --git a/src/compile.rs b/src/compile.rs index d5d591c..20c527d 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -4,6 +4,7 @@ use crate::{ runtime::{ModuleInstance, Runtime}, }; use anyhow::anyhow; +use core::panic; use std::{io::Result, path::PathBuf, sync::Arc}; use v8::Isolate; @@ -11,7 +12,7 @@ use v8::Isolate; pub struct ModuleDependency { pub deps: Vec, pub async_deps: Vec, - pub specifier: Vec, + pub specifiers: Vec, pub source: String, pub map: Option, pub filename: String, @@ -19,7 +20,7 @@ pub struct ModuleDependency { } impl ModuleDependency { - pub fn initialize(&self, isolate: &mut Isolate) -> Option<()> { + pub fn initialize(&self, isolate: &mut Isolate) -> anyhow::Result<()> { let graph_rc = Runtime::graph(isolate); { @@ -28,25 +29,25 @@ impl ModuleDependency { let module = module.borrow(); if module.get(&self.filename).is_some() { - return Some(()); + return Ok(()); } } // { - self.deps.iter().for_each(|url| { - let state = graph_rc.borrow(); - let graph = state.table.borrow(); + let state = graph_rc.borrow(); + let graph = state.table.borrow(); + for url in self.deps.iter() { let url = resolve(url, &self.filename); let dep = graph.get(&url).unwrap(); - dep.initialize(isolate); - }); + dep.initialize(isolate)? + } // } - self.instantiate_module(isolate); + self.instantiate_module(isolate)?; - return Some(()); + Ok(()) } - fn instantiate_module(&self, isolate: &mut Isolate) { + fn instantiate_module(&self, isolate: &mut Isolate) -> anyhow::Result<()> { let state_rc = Runtime::state(isolate); let graph_rc = Runtime::graph(isolate); @@ -80,9 +81,13 @@ impl ModuleDependency { .insert(module_id, self.filename.clone()); let tc_scope = &mut v8::TryCatch::new(scope); - module - .instantiate_module(tc_scope, Runtime::resolve_module_callback) - .unwrap(); + let result = module.instantiate_module(tc_scope, Runtime::resolve_module_callback); + if result.is_none() { + let expection = tc_scope.exception().unwrap(); + let msg = expection.to_rust_string_lossy(tc_scope); + return Err(anyhow!("{}", msg)); + } + let expose = &module.get_module_namespace(); let v8_module = v8::Global::new(tc_scope, module); let expose = v8::Global::new(tc_scope, expose); @@ -95,6 +100,7 @@ impl ModuleDependency { expose, }, ); + Ok(()) } pub fn evaluate(&self, isolate: &mut Isolate) { diff --git a/src/compile_oxc.rs b/src/compile_oxc.rs index 3d0c34f..e770f66 100644 --- a/src/compile_oxc.rs +++ b/src/compile_oxc.rs @@ -1,11 +1,12 @@ +use core::panic; + use anyhow::anyhow; use oxc_allocator::Allocator; -use oxc_ast::{AstKind, Visit}; +use oxc_ast::{ast::ImportAttribute, AstKind, Visit}; use oxc_codegen::{Codegen, CodegenOptions}; use oxc_semantic::SemanticBuilder; use oxc_span::{GetSpan, SourceType}; use oxc_transformer::{TransformOptions, TransformTarget, Transformer}; -use tracing::Instrument; use crate::compile::ModuleDependency; @@ -13,6 +14,9 @@ use crate::compile::ModuleDependency; struct ImportParser { sync_imports: Vec, async_imports: Vec, + specifiers: Vec, + namespaces: Vec, + default_import: bool, } impl<'a> oxc_ast::Visit<'a> for ImportParser { @@ -35,13 +39,17 @@ impl<'a> oxc_ast::Visit<'a> for ImportParser { use oxc_ast::ast::ImportDeclarationSpecifier; match specifier { ImportDeclarationSpecifier::ImportSpecifier(import_specifer) => { - println!("ImportDeclarationSpecifier: {:?}", import_specifer.span); + // println!("ImportSpecifier: {:?}", import_specifer.imported.name()); + self.specifiers + .push(import_specifer.imported.name().to_string()); } - ImportDeclarationSpecifier::ImportDefaultSpecifier(import_specfier) => { - println!("ImportDeclarationSpecifier: {:?}", import_specfier.span); + ImportDeclarationSpecifier::ImportDefaultSpecifier(_import_specfier) => { + // println!("ImportDefaultSpecifier: {:?}", import_specfier); + self.default_import = true; } ImportDeclarationSpecifier::ImportNamespaceSpecifier(import_specifer) => { - println!("ImportDeclarationSpecifier: {:?}", import_specifer.span); + // println!("ImportNamespaceSpecifier: {:?}", import_specifer); + self.namespaces.push(import_specifer.local.name.to_string()); } } } @@ -55,24 +63,24 @@ impl<'a> oxc_ast::Visit<'a> for ImportParser { } } -pub fn compile(file_name: &str, source_text: &str) -> anyhow::Result { +pub fn compile(file_name: &str, content: &str) -> anyhow::Result { let allo = Allocator::default(); let source_type = oxc_span::SourceType::from_path(file_name).unwrap(); - let ret = oxc_parser::Parser::new(&allo, &source_text, source_type).parse(); + let ret = oxc_parser::Parser::new(&allo, &content, source_type).parse(); if !ret.errors.is_empty() { for error in ret.errors { - let error = error.with_source_code(source_text.to_string()); + let error = error.with_source_code(content.to_string()); println!("{error:?}"); } return Err(anyhow!("compile error")); } - let mut pass = ImportParser::default(); - pass.visit_program(&ret.program); + let mut import_parser = ImportParser::default(); + import_parser.visit_program(&ret.program); - let semantic = SemanticBuilder::new(&source_text, source_type) + let semantic = SemanticBuilder::new(&content, source_type) .with_trivias(ret.trivias) .build(&ret.program) .semantic; @@ -80,16 +88,21 @@ pub fn compile(file_name: &str, source_text: &str) -> anyhow::Result::new(source_text.len(), CodegenOptions).build(program); + let code = Codegen::::new(content.len(), CodegenOptions).build(program); Ok(ModuleDependency { - deps: pass.sync_imports, - async_deps: pass.async_imports, - specifier: vec![], + deps: import_parser.sync_imports, + async_deps: import_parser.async_imports, + specifiers: import_parser.specifiers, source: code, map: None, filename: file_name.to_string(), diff --git a/src/main.rs b/src/main.rs index f9cc960..6415b95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,9 @@ mod compile_oxc; use graph::resolve; use graph::DependencyGraph; use runtime::Runtime; +use tokio::main; -#[tokio::main] +#[main] async fn main() -> anyhow::Result<()> { let args = env::args().collect::>(); if args.len() <= 1 { diff --git a/src/runtime/asynchronous.rs b/src/runtime/asynchronous.rs index ed94b53..fdc17d8 100644 --- a/src/runtime/asynchronous.rs +++ b/src/runtime/asynchronous.rs @@ -11,13 +11,10 @@ pub enum AsynchronousKind { } impl AsynchronousKind { - pub fn exec(&self, isolate: &mut Isolate) -> Poll<()> { - match match self { + pub fn exec(&self, isolate: &mut Isolate) -> anyhow::Result> { + match self { AsynchronousKind::Operation(id) => Self::operation(isolate, id.clone()), AsynchronousKind::Import((source, resolver)) => Self::import(isolate, source, resolver), - } { - Ok(v) => v, - Err(e) => panic!("error {}", e), } } @@ -83,7 +80,7 @@ impl AsynchronousKind { .get(source) .ok_or(anyhow!("source `{}` not found", source))?; - if dep.initialize(isolate).is_some() { + if dep.initialize(isolate).is_ok() { dep.evaluate(isolate); let scope = &mut v8::HandleScope::with_context(isolate, context); @@ -103,9 +100,9 @@ impl AsynchronousKind { let module = graph.module.borrow(); if module.get(source).is_none() { let t = table.get(source).unwrap(); - t.initialize(isolate); + t.initialize(isolate)?; } - return Ok(Poll::Ready(())); + Ok(Poll::Ready(())) } } diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 3fe1fae..f335731 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -6,6 +6,7 @@ use std::{ use crate::{compile, graph::DependencyGraph}; use futures::{stream::FuturesUnordered, Future, StreamExt}; use tokio::sync::mpsc::{self, Receiver, Sender}; +use tracing::Instrument; use v8::{Isolate, OwnedIsolate}; mod asynchronous; @@ -123,7 +124,7 @@ impl Runtime { &include_str!("../../bootstrap/main.ts").to_string(), )?; - dependency.initialize(isolate); + dependency.initialize(isolate)?; dependency.evaluate(isolate); // @@ -178,7 +179,11 @@ impl Runtime { } result } { - break op.exec(isolate); + match op.exec(isolate) { + Ok(v) => break v, + Err(err) => eprintln!("{err:?}"), + } + break Poll::Ready(()); } break Poll::Pending; }) diff --git a/src/runtime/static_fn.rs b/src/runtime/static_fn.rs index a8a719f..6ecdecf 100644 --- a/src/runtime/static_fn.rs +++ b/src/runtime/static_fn.rs @@ -6,7 +6,7 @@ use url::Url; impl Runtime { pub fn resolve_module_callback<'s>( context: v8::Local<'s, v8::Context>, - specifier: v8::Local<'s, v8::String>, + source: v8::Local<'s, v8::String>, _import_assertions: v8::Local<'s, v8::FixedArray>, referrer: v8::Local<'s, v8::Module>, ) -> Option> { @@ -16,7 +16,7 @@ impl Runtime { let state = graph_rc.borrow(); - let source = specifier.to_rust_string_lossy(scope); + let source = source.to_rust_string_lossy(scope); let url = if source.starts_with("http") { let url = Url::parse(&source).expect(format!("parse url failed: {}", source).as_str()); @@ -38,7 +38,7 @@ impl Runtime { .expect(format!("get module failure: {}", url).as_str()); let module = v8::Local::new(scope, &info.module); - return Some(module); + Some(module) } pub fn dynamically_import<'a>( diff --git a/test/test.ts b/test/test.ts index 8c1be76..3e6028d 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,9 +1,9 @@ -// import "https://deno.land/std@0.182.0/examples/welcome.ts"; -// import "https://deno.land/std@0.182.0/examples/welcome.ts"; -import "./welcome.ts" +// import {a ,b,c} from "https://deno.land/std@0.182.0/examples/welcome.ts"; +import "https://deno.land/std@0.182.0/examples/welcome.ts"; +import {a} from "./welcome.ts" // const res = await import("./test1.ts"); -// console.log("res", res); +console.log(a); // const text = await res.json(); // console.log("🚀 text", text); // test.copy(); diff --git a/test/welcome.ts b/test/welcome.ts index 998c238..e7fad9c 100644 --- a/test/welcome.ts +++ b/test/welcome.ts @@ -1 +1,4 @@ console.log("Welcome edon!"); + +const a = 1; +export {a}