Skip to content

Commit

Permalink
fixup! print js error in console.log
Browse files Browse the repository at this point in the history
  • Loading branch information
ofzo committed Feb 19, 2024
1 parent d216328 commit 8ef5c4f
Show file tree
Hide file tree
Showing 18 changed files with 452 additions and 92 deletions.
328 changes: 293 additions & 35 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ url = "2.5.0"
v8 = "0.82.0"
anyhow = "1.0.79"
tracing = "0.1.40"
# oxc
oxc_allocator = "^0.6.0"
oxc_codegen = "^0.6.0"
oxc_parser = "^0.6.0"
oxc_transformer = "^0.6.0"
oxc_span= "^0.6.0"
oxc_ast = "^0.6.0"
oxc_semantic = "^0.6.0"

[dependencies.tokio]
features = ["full"]
Expand Down
21 changes: 10 additions & 11 deletions bootstrap/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@ interface RuntimeData {
count: number
}

var runtimeData: RuntimeData = {
asyncHandle: [],
count: 0,
}

export default async function bootstrap(entry: string) {
var runtime: RuntimeData = {
asyncHandle: [],
count: 0,
}
//@ts-ignore
globalThis.setTimeout = (fn: Function, delay: number, ...arg: any[]) => {
runtimeData.asyncHandle[runtimeData.count] = () => {
runtime.asyncHandle[runtime.count] = () => {
fn(...arg)
}
this.timer.send(runtimeData.count, delay)
runtimeData.count++
this.timer.send(runtime.count, delay)
runtime.count++
}
globalThis.exec = (id: number) => {
if (runtimeData.asyncHandle[id]) {
let fn = runtimeData.asyncHandle[id]
delete runtimeData.asyncHandle[id]
if (runtime.asyncHandle[id]) {
let fn = runtime.asyncHandle[id]
delete runtime.asyncHandle[id]
fn()
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/runner/console.rs → src/builtin/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ pub fn console_format(
format!("")
}

pub fn console_log(
pub fn log(
scope: &mut v8::HandleScope,
args: v8::FunctionCallbackArguments,
mut _rv: v8::ReturnValue,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
16 changes: 6 additions & 10 deletions src/compile.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
compile_oxc,
graph::resolve,
runtime::{ModuleInstance, Runtime},
};
Expand All @@ -17,20 +18,12 @@ use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
use swc_ecma_visit::{Visit, VisitWith};
use v8::Isolate;

#[derive(Default, Debug)]
struct ImportParser {
sync_imports: Vec<String>,
async_imports: Vec<String>,
}

impl ImportParser {
pub fn new() -> Self {
Self {
sync_imports: vec![],
async_imports: vec![],
}
}
}

impl Visit for ImportParser {
fn visit_call_expr(&mut self, call_expr: &CallExpr) {
if !matches!(call_expr.callee, Callee::Import(_)) {
Expand Down Expand Up @@ -153,6 +146,7 @@ impl ModuleDependency {
},
);
}

pub fn evaluate(&self, isolate: &mut Isolate) {
let state_rc = Runtime::state(isolate);
let graph_rc = Runtime::graph(isolate);
Expand Down Expand Up @@ -188,6 +182,8 @@ impl ModuleDependency {
}

pub fn compile(file_name: &str, source: &str) -> anyhow::Result<ModuleDependency> {
return compile_oxc::compile(file_name, source);

let cm = Arc::<SourceMap>::default();
let handler = Arc::new(Handler::with_tty_emitter(
ColorConfig::Auto,
Expand Down Expand Up @@ -223,7 +219,7 @@ pub fn compile(file_name: &str, source: &str) -> anyhow::Result<ModuleDependency
.map_err(|e| anyhow!("parse {file_name} fail"))?;
// .expect(&format!("parse {file_name} fail"));

let mut import_parser = ImportParser::new();
let mut import_parser = ImportParser::default();
parsed.visit_with(&mut import_parser);

let config = Config {
Expand Down
98 changes: 98 additions & 0 deletions src/compile_oxc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use anyhow::anyhow;
use oxc_allocator::Allocator;
use oxc_ast::{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;

#[derive(Debug, Default)]
struct ImportParser {
sync_imports: Vec<String>,
async_imports: Vec<String>,
}

impl<'a> oxc_ast::Visit<'a> for ImportParser {
fn visit_import_declaration(&mut self, decl: &oxc_ast::ast::ImportDeclaration<'a>) {
let kind = AstKind::ImportDeclaration(self.alloc(decl));
self.enter_node(kind);
if let Some(specifiers) = &decl.specifiers {
for specifer in specifiers {
self.visit_import_declaration_specifier(specifer);
}
}
self.sync_imports.push(decl.source.value.to_string());
self.leave_node(kind);
}

fn visit_import_declaration_specifier(
&mut self,
specifier: &oxc_ast::ast::ImportDeclarationSpecifier,
) {
use oxc_ast::ast::ImportDeclarationSpecifier;
match specifier {
ImportDeclarationSpecifier::ImportSpecifier(import_specifer) => {
println!("ImportDeclarationSpecifier: {:?}", import_specifer.span);
}
ImportDeclarationSpecifier::ImportDefaultSpecifier(import_specfier) => {
println!("ImportDeclarationSpecifier: {:?}", import_specfier.span);
}
ImportDeclarationSpecifier::ImportNamespaceSpecifier(import_specifer) => {
println!("ImportDeclarationSpecifier: {:?}", import_specifer.span);
}
}
}
fn visit_import_expression(&mut self, expr: &oxc_ast::ast::ImportExpression<'a>) {
let kind = AstKind::ImportExpression(self.alloc(expr));
self.enter_node(kind);
if let oxc_ast::ast::Expression::StringLiteral(v) = &expr.source {
self.async_imports.push(v.value.to_string())
}
self.leave_node(kind);
}
}

pub fn compile(file_name: &str, source: &str) -> anyhow::Result<ModuleDependency> {
let allo = Allocator::default();
let source_type = oxc_span::SourceType::from_path(file_name).unwrap();

let ret = oxc_parser::Parser::new(&allo, &source, source_type).parse();

if !ret.errors.is_empty() {
for error in ret.errors {
let error = error.with_source_code(source.to_string());
println!("{error:?}");
}
return Err(anyhow!("compile error"));
}

let mut pass = ImportParser::default();
pass.visit_program(&ret.program);

let semantic = SemanticBuilder::new(&source, source_type)
.with_trivias(ret.trivias)
.build(&ret.program)
.semantic;

let program = allo.alloc(ret.program);
let transform_options = TransformOptions::default();

Transformer::new(&allo, source_type, semantic, transform_options)
.build(program)
.unwrap();

let code = Codegen::<false>::new(source.len(), CodegenOptions).build(program);

Ok(ModuleDependency {
deps: pass.sync_imports,
async_deps: pass.async_imports,
specifier: vec![],
source: code,
map: None,
filename: file_name.to_string(),
is_main: false,
})
}
14 changes: 7 additions & 7 deletions src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,19 @@ impl DependencyGraph {
dep.append(entry, base).await?;
Ok(dep)
}
pub async fn append(&mut self, entry: &String, base: &String) -> anyhow::Result<()> {
pub async fn append(&mut self, source: &String, base: &String) -> anyhow::Result<()> {
//
let mut preload = queue![(entry.clone(), base.clone())];
let mut preload = queue![(source.clone(), base.clone())];

let table = &mut self.0;

while let Ok((entry, base)) = preload.remove() {
let url = resolve(&entry, &base);
while let Ok((source, base)) = preload.remove() {
let url = resolve(&source, &base);
let dep = load(&url).await?;
let base = dep.filename.clone();
for specifier in &dep.deps {
if table.get(specifier).is_none() {
preload.add((specifier.clone(), base.clone())).unwrap();
for source in &dep.deps {
if table.get(source).is_none() {
preload.add((source.clone(), base.clone())).unwrap();
}
}
table.insert(dep.filename.clone(), dep);
Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::env;
mod compile;
mod graph;
mod runner;
mod builtin;
mod runtime;
mod compile_oxc;

use graph::resolve;
use graph::DependencyGraph;
Expand Down
16 changes: 7 additions & 9 deletions src/runtime/asynchronous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ impl AsynchronousKind {
pub fn exec(&self, isolate: &mut Isolate) -> Poll<()> {
match match self {
AsynchronousKind::Operation(id) => Self::operation(isolate, id.clone()),
AsynchronousKind::Import((specifier, resolver)) => {
Self::import(isolate, specifier, resolver)
}
AsynchronousKind::Import((source, resolver)) => Self::import(isolate, source, resolver),
} {
Ok(v) => v,
Err(e) => panic!("error {}", e),
Expand Down Expand Up @@ -59,7 +57,7 @@ impl AsynchronousKind {
}
fn import(
isolate: &mut Isolate,
specifier: &String,
source: &String,
resolver: &v8::Global<v8::PromiseResolver>,
) -> anyhow::Result<Poll<()>> {
let state_rc = Runtime::state(isolate);
Expand All @@ -73,17 +71,17 @@ impl AsynchronousKind {
if {
let graph = graph_rc.borrow();
let table = graph.table.borrow();
table.get(specifier).is_none()
table.get(source).is_none()
} {
let base = format!("");
let _ = futures::executor::block_on(Runtime::import(isolate, specifier, &base));
let _ = futures::executor::block_on(Runtime::import(isolate, source, &base));
};

let graph = graph_rc.borrow();
let table = graph.table.borrow();
let dep = table
.get(specifier)
.ok_or(anyhow!("specifier `{}` not found", specifier))?;
.get(source)
.ok_or(anyhow!("specifier `{}` not found", source))?;
// .expect(&format!("specifier `{}` not found", specifier));

if dep.initialize(isolate).is_some() {
Expand All @@ -96,7 +94,7 @@ impl AsynchronousKind {

let graph = graph_rc.borrow();
let module = graph.module.borrow();
if let Some(instance) = module.get(specifier) {
if let Some(instance) = module.get(source) {
let expose = v8::Local::new(tc_scope, &instance.expose);
let obj = expose.to_object(tc_scope).unwrap();
resolver.resolve(tc_scope, obj.into());
Expand Down
10 changes: 5 additions & 5 deletions src/runtime/init.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::runner::console::console_log;
use crate::builtin::console::log;

use super::Runtime;

Expand All @@ -14,10 +14,10 @@ impl Runtime {
let console_object = v8::Object::new(scope);
global.set(scope, console_key.into(), console_object.into());

Self::set_func(scope, console_object, "log", console_log);
Self::set_func(scope, console_object, "info", console_log);
Self::set_func(scope, console_object, "error", console_log);
Self::set_func(scope, console_object, "warn", console_log);
Self::set_func(scope, console_object, "log", log);
Self::set_func(scope, console_object, "info", log);
Self::set_func(scope, console_object, "error", log);
Self::set_func(scope, console_object, "warn", log);

scope.escape(context)
}
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl Runtime {

// bootstrap.js
let mut bootstrap_js = PathBuf::new();
bootstrap_js.push("bootstrap.js");
bootstrap_js.push("bootstrap.ts");
let dependency = compile::compile(
&bootstrap_js.to_string_lossy().to_string(),
&include_str!("../../bootstrap/main.ts").to_string(),
Expand Down Expand Up @@ -186,11 +186,11 @@ impl Runtime {
}
}

async fn import(isolate: &mut Isolate, entry: &String, base: &String) -> anyhow::Result<()> {
async fn import(isolate: &mut Isolate, source: &String, base: &String) -> anyhow::Result<()> {
let graph_rc = Self::graph(isolate);
let graph = graph_rc.borrow();
let mut table = graph.table.borrow_mut();

table.append(entry, base).await
table.append(source, base).await
}
}
8 changes: 4 additions & 4 deletions src/runtime/static_fn.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{asynchronous::AsynchronousKind, Runtime};
use crate::{graph::resolve, runner::console::console_format};
use crate::{graph::resolve, builtin::console::console_format};
use std::{task::Poll, time::Duration};
use url::Url;

Expand Down Expand Up @@ -44,12 +44,12 @@ impl Runtime {
scope: &mut v8::HandleScope<'a>,
_host_defined_options: v8::Local<'a, v8::Data>,
resource: v8::Local<'a, v8::Value>,
specifier: v8::Local<'a, v8::String>,
source: v8::Local<'a, v8::String>,
_import_assertions: v8::Local<'a, v8::FixedArray>,
) -> Option<v8::Local<'a, v8::Promise>> {
let state_rc = Self::state(scope);
let resource = resource.to_rust_string_lossy(scope).to_string();
let specifier = specifier.to_rust_string_lossy(scope).to_string();
let source = source.to_rust_string_lossy(scope).to_string();

let resolver = v8::PromiseResolver::new(scope).unwrap();
let promise = resolver.get_promise(scope);
Expand All @@ -59,7 +59,7 @@ impl Runtime {

state.pending_ops.push(Box::pin(async move {
Poll::Ready(AsynchronousKind::Import((
resolve(&specifier, &resource),
resolve(&source, &resource),
resolver,
)))
}));
Expand Down
13 changes: 7 additions & 6 deletions test/test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// import "https://deno.land/[email protected]/examples/welcome.ts";
// import "https://deno.land/[email protected]/examples/welcome.ts";
import "./welcome.ts"

const res = await import("./test1.ts");
console.log("res", res);
const text = await res.json();
console.log("🚀 text", text);
test.copy();

// const res = await import("./test1.ts");
// console.log("res", res);
// const text = await res.json();
// console.log("🚀 text", text);
// test.copy();
// import("./welcome.ts")
1 change: 1 addition & 0 deletions test/welcome.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Welcome edon!");

0 comments on commit 8ef5c4f

Please sign in to comment.