Skip to content

Commit ccffaea

Browse files
committed
chore(by-ai): Follow new deno_core API
1 parent 25d633c commit ccffaea

14 files changed

Lines changed: 694 additions & 382 deletions

File tree

pkgs/ai-deno/Cargo.lock

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

pkgs/ai-deno/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ deno_package_json = "=0.21.0"
4747
deno_semver = "=0.9.0"
4848
deno_cache_dir = "=0.25.0"
4949
deno_permissions = "=0.78.0"
50+
deno_bundle_runtime = "0.6.0"
5051

5152
tokio = { version = "1.47.1", features = ["full"] }
5253
tokio-util = "0.7.16"

pkgs/ai-deno/src/deno/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ map_error!(JsError, |e| Error::Runtime(format!(
5050
"{}\n{}",
5151
e.message.unwrap_or("".to_string()).to_string(), e.stack.unwrap_or("".to_string()).to_string()
5252
)));
53+
map_error!(Box<JsError>, |e| Error::Runtime(format!(
54+
"{}\n{}",
55+
e.message.clone().unwrap_or("".to_string()).to_string(), e.stack.clone().unwrap_or("".to_string()).to_string()
56+
)));
5357
map_error!(std::io::Error, |e| Error::Runtime(e.to_string()));
5458
map_error!(deno_core::error::CoreError, |e| Error::CoreError(
5559
e.to_string()

pkgs/ai-deno/src/deno/module.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::path::Path;
1111
use crate::deno::error::Error;
1212
use crate::deno::runtime::Runtime;
1313
use crate::deno::traits::{ToDefinedValue, ToV8String};
14+
use crate::deno_println;
1415

1516
#[derive(Debug, Clone)]
1617
pub struct Module {
@@ -64,9 +65,10 @@ fn resolve_path(
6465
path_str: impl AsRef<Path>,
6566
current_dir: &Path,
6667
) -> Result<ModuleSpecifier, JsErrorBox> {
68+
use std::borrow::Cow;
6769
let path = current_dir.join(path_str);
68-
let path = deno_core::normalize_path(path);
69-
deno_core::url::Url::from_file_path(&path).map_err(|()| {
70+
let path = deno_core::normalize_path(Cow::Borrowed(path.as_path()));
71+
deno_core::url::Url::from_file_path(path.as_ref()).map_err(|()| {
7072
JsErrorBox::generic(format!(
7173
"Failed to resolve path: {}",
7274
path.to_string_lossy().to_string()
@@ -109,7 +111,12 @@ impl ModuleHandle {
109111
) -> Result<v8::Global<v8::Function>, Error> {
110112
let value = self.get_value_ref(runtime, name)?;
111113

112-
let mut scope = runtime.deno_runtime().handle_scope();
114+
let deno_runtime = runtime.deno_runtime();
115+
let context = deno_runtime.main_context();
116+
let isolate = deno_runtime.v8_isolate();
117+
v8::scope!(handle_scope, isolate);
118+
let context_local = v8::Local::new(handle_scope, context);
119+
let mut scope = v8::ContextScope::new(handle_scope, context_local);
113120
let local = v8::Local::<v8::Value>::new(&mut scope, value);
114121

115122
if !local.is_function() {
@@ -141,11 +148,18 @@ impl ModuleHandle {
141148
));
142149
};
143150

144-
let mut scope = runtime.deno_runtime().handle_scope();
151+
let deno_runtime = runtime.deno_runtime();
152+
let context = deno_runtime.main_context();
153+
let isolate = deno_runtime.v8_isolate();
154+
v8::scope!(handle_scope, isolate);
155+
let context_local = v8::Local::new(handle_scope, context);
156+
let mut scope = v8::ContextScope::new(handle_scope, context_local);
145157
let module_namespace = module_namespace.open(&mut scope);
146158
assert!(module_namespace.is_module_namespace_object());
147159

148-
let key = name.to_v8_string(&mut scope)?.cast::<v8::Value>();
160+
let key = v8::String::new(&scope, name)
161+
.ok_or_else(|| Error::V8Encoding(name.to_string()))?
162+
.cast::<v8::Value>();
149163
let value = module_namespace.get(&mut scope, key);
150164

151165
match value.if_defined() {
@@ -155,14 +169,25 @@ impl ModuleHandle {
155169
}
156170

157171
pub fn get_module_exports(&self, runtime: &mut Runtime) -> Result<Vec<String>, Error> {
172+
println!("[DEBUG] get_module_exports: trying to get namespace for module_id: {}", self.module_id);
173+
158174
let module_namespace =
159175
if let Ok(namespace) = runtime.deno_runtime().get_module_namespace(self.module_id) {
176+
println!("[DEBUG] get_module_exports: successfully got namespace");
160177
namespace
161178
} else {
179+
println!("[DEBUG] get_module_exports: failed to get namespace for module_id: {}", self.module_id);
180+
// Try to get more information about why it failed
181+
eprintln!("[DEBUG] Module {} namespace not available - module may not be fully evaluated", self.module_id);
162182
return Err(Error::Runtime(self.module_id().to_string()));
163183
};
164184

165-
let mut scope = runtime.deno_runtime().handle_scope();
185+
let deno_runtime = runtime.deno_runtime();
186+
let context = deno_runtime.main_context();
187+
let isolate = deno_runtime.v8_isolate();
188+
v8::scope!(handle_scope, isolate);
189+
let context_local = v8::Local::new(handle_scope, context);
190+
let mut scope = v8::ContextScope::new(handle_scope, context_local);
166191
let module_namespace = module_namespace.open(&mut scope);
167192
assert!(module_namespace.is_module_namespace_object());
168193

pkgs/ai-deno/src/deno/module_loader.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,17 @@ impl AiDenoModuleLoader {
135135
deno_resolver::cjs::IsCjsResolutionMode::ImplicitTypeCommonJs,
136136
);
137137

138-
let cjs_translator = NodeCodeTranslator::new(MaybeArc::new(CjsModuleExportAnalyzer::new(
139-
AiDenoCjsCodeAnalyzer::new(MaybeArc::new(RealFs::default()), cjs_tracker),
140-
pkg_manager.clone(),
141-
node_resolver.clone(),
142-
pkg_manager.clone(),
143-
pkg_json_resolver.clone(),
144-
real_sys.clone(),
145-
)));
138+
let cjs_translator = NodeCodeTranslator::new(
139+
MaybeArc::new(CjsModuleExportAnalyzer::new(
140+
AiDenoCjsCodeAnalyzer::new(MaybeArc::new(RealFs::default()), cjs_tracker),
141+
pkg_manager.clone(),
142+
node_resolver.clone(),
143+
pkg_manager.clone(),
144+
pkg_json_resolver.clone(),
145+
real_sys.clone(),
146+
)),
147+
node_resolver::analyze::NodeCodeTranslatorMode::ModuleLoader,
148+
);
146149

147150
// let module_graph = ModuleGraph::new(deno_graph::GraphKind::All);
148151

@@ -230,7 +233,7 @@ impl AiDenoModuleLoader {
230233
let package_name = specifier.strip_prefix("npm:").unwrap_or(specifier);
231234

232235
let npm_client = self.pkg_manager.npm_client.clone();
233-
let (name, version, _sub_path) = parse_npm_specifier(package_name).map_err(|err| {
236+
let (name, version, sub_path) = parse_npm_specifier(package_name).map_err(|err| {
234237
ModuleLoaderError::from(JsErrorBox::generic(format!(
235238
"Failed to parse npm specifier: {} - {}",
236239
package_name, err
@@ -271,7 +274,14 @@ impl AiDenoModuleLoader {
271274
deno_println!("Package already installed: {}@{:?}", name, resolved_version);
272275
}
273276

274-
return Ok(ModuleSpecifier::parse(specifier).unwrap());
277+
// Return specifier with resolved version
278+
let resolved_specifier = if sub_path.is_empty() {
279+
format!("npm:{}@{}", name, resolved_version)
280+
} else {
281+
format!("npm:{}@{}/{}", name, resolved_version, sub_path)
282+
};
283+
284+
return Ok(ModuleSpecifier::parse(&resolved_specifier).unwrap());
275285
}
276286

277287
pub fn resolve_npm_module(
@@ -380,7 +390,13 @@ impl AiDenoModuleLoader {
380390
let path = self
381391
.pkg_manager
382392
.resolve_specifier_to_file_path(module_specifier.as_str(), None)
383-
.unwrap();
393+
.map_err(|err| {
394+
ModuleLoaderError::from(JsErrorBox::generic(format!(
395+
"Failed to resolve npm package: {} - {:?}",
396+
module_specifier,
397+
err
398+
)))
399+
})?;
384400

385401
let content = std::fs::read_to_string(&path).map_err(|err| {
386402
ModuleLoaderError::from(JsErrorBox::generic(format!(

pkgs/ai-deno/src/deno/module_loader/cjs_code_analyzer.rs

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
use deno_ast::{MediaType, ModuleExportsAndReExports, ModuleSpecifier, ParsedSource};
55
use deno_error::JsErrorBox;
6-
use deno_graph::{CapturingEsParser, DefaultEsParser, EsParser, ParseOptions, ParsedSourceStore};
76
use deno_resolver::{cjs::CjsTracker, npm::DenoInNpmPackageChecker};
87
use deno_runtime::deno_fs;
98
use node_resolver::analyze::EsmAnalysisMode;
@@ -157,8 +156,10 @@ impl node_resolver::analyze::CjsCodeAnalyzer for AiDenoCjsCodeAnalyzer {
157156
Some(source) => source,
158157
None => {
159158
if let Ok(path) = specifier.to_file_path() {
160-
if let Ok(source_from_file) =
161-
self.fs.read_text_file_lossy_async(path, None).await
159+
if let Ok(source_from_file) = self
160+
.fs
161+
.read_text_file_lossy_async(deno_permissions::CheckedPathBuf::unsafe_new(path))
162+
.await
162163
{
163164
source_from_file
164165
} else {
@@ -235,7 +236,7 @@ pub struct ParsedSourceCache {
235236
/// and in LSP settings the concurrency will be enforced
236237
/// at a higher level to ensure this will have the latest
237238
/// parsed source.
238-
impl deno_graph::ParsedSourceStore for ParsedSourceCache {
239+
impl ParsedSourceCache {
239240
fn set_parsed_source(
240241
&self,
241242
specifier: ModuleSpecifier,
@@ -251,7 +252,7 @@ impl deno_graph::ParsedSourceStore for ParsedSourceCache {
251252
self.sources.lock().unwrap().get(specifier).cloned()
252253
}
253254

254-
fn remove_parsed_source(&self, specifier: &ModuleSpecifier) -> Option<ParsedSource> {
255+
pub fn remove_parsed_source(&self, specifier: &ModuleSpecifier) -> Option<ParsedSource> {
255256
self.sources.lock().unwrap().remove(specifier)
256257
}
257258

@@ -265,66 +266,20 @@ impl deno_graph::ParsedSourceStore for ParsedSourceCache {
265266
Some(parsed_source.clone())
266267
} else {
267268
// upgrade to have scope analysis
268-
let parsed_source = sources.remove(specifier).unwrap();
269+
let parsed_source = sources.remove(specifier)?;
269270
let parsed_source = parsed_source.into_with_scope_analysis();
270271
sources.insert(specifier.clone(), parsed_source.clone());
271272
Some(parsed_source)
272273
}
273274
}
274-
}
275-
276-
impl ParsedSourceCache {
277-
pub fn get_parsed_source_from_js_module(
278-
&self,
279-
module: &deno_graph::JsModule,
280-
) -> Result<ParsedSource, deno_ast::ParseDiagnostic> {
281-
let parser = self.as_capturing_parser();
282-
// this will conditionally parse because it's using a CapturingEsParser
283-
parser.parse_program(ParseOptions {
284-
specifier: &module.specifier,
285-
source: module.source.clone(),
286-
media_type: module.media_type,
287-
scope_analysis: false,
288-
})
289-
}
290-
291-
pub fn remove_or_parse_module(
292-
&self,
293-
specifier: &ModuleSpecifier,
294-
source: Arc<str>,
295-
media_type: MediaType,
296-
) -> Result<ParsedSource, deno_ast::ParseDiagnostic> {
297-
if let Some(parsed_source) = self.remove_parsed_source(specifier) {
298-
if parsed_source.media_type() == media_type
299-
&& parsed_source.text().as_ref() == source.as_ref()
300-
{
301-
// note: message used tests
302-
// log::debug!("Removed parsed source: {}", specifier);
303-
return Ok(parsed_source);
304-
}
305-
}
306-
let options = ParseOptions {
307-
specifier,
308-
source,
309-
media_type,
310-
scope_analysis: false,
311-
};
312-
DefaultEsParser.parse_program(options)
313-
}
314275

315276
/// Frees the parsed source from memory.
316277
pub fn free(&self, specifier: &ModuleSpecifier) {
317278
self.sources.lock().unwrap().remove(specifier);
318279
}
319280

320-
/// Fress all parsed sources from memory.
281+
/// Frees all parsed sources from memory.
321282
pub fn free_all(&self) {
322283
self.sources.lock().unwrap().clear();
323284
}
324-
325-
/// Creates a parser that will reuse a ParsedSource from the store
326-
/// if it exists, or else parse.
327-
pub fn as_capturing_parser(&self) -> CapturingEsParser {
328-
CapturingEsParser::new(None, self)
329-
}
330285
}

pkgs/ai-deno/src/deno/module_loader/http_client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl AiDenoHttpClient {
6363

6464
if !status.is_success() {
6565
return Err(deno_npm_cache::DownloadError {
66-
status_code: Some(StatusCode::from_u16(status.as_u16()).unwrap()),
66+
status_code: Some(status.as_u16()),
6767
error: JsErrorBox::generic(format!("Failed to load url: {}", url)),
6868
});
6969
}
@@ -72,7 +72,7 @@ impl AiDenoHttpClient {
7272
.bytes()
7373
.await
7474
.map_err(|e| deno_npm_cache::DownloadError {
75-
status_code: Some(StatusCode::from_u16(status.as_u16()).unwrap()),
75+
status_code: Some(status.as_u16()),
7676
error: JsErrorBox::generic(format!(
7777
"Failed to receive bytes: {}; {}",
7878
url,

pkgs/ai-deno/src/deno/module_loader/npm_client.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl From<NpmPackageError> for JsErrorBox {
3838
}
3939
}
4040

41+
#[derive(Debug)]
4142
pub struct NpmClient {
4243
pub registry_url: String,
4344
pub http_client: reqwest::Client,
@@ -151,16 +152,40 @@ impl NpmCacheHttpClient for NpmClient {
151152
async fn download_with_retries_on_any_tokio_runtime(
152153
&self,
153154
url: Url,
154-
maybe_auth_header: Option<(HeaderName, HeaderValue)>,
155-
) -> Result<Option<Vec<u8>>, deno_npm_cache::DownloadError> {
156-
let headers = if let Some((name, value)) = maybe_auth_header {
157-
Some(vec![(name, value.to_str().unwrap().to_string())])
158-
} else {
159-
None
155+
maybe_header_name: Option<String>,
156+
maybe_header_value: Option<String>,
157+
) -> Result<deno_npm_cache::NpmCacheHttpClientResponse, deno_npm_cache::DownloadError> {
158+
let headers = match (maybe_header_name, maybe_header_value) {
159+
(Some(name), Some(value)) => {
160+
let header_name = HeaderName::from_bytes(name.as_bytes())
161+
.map_err(|e| deno_npm_cache::DownloadError {
162+
status_code: None,
163+
error: JsErrorBox::generic(format!("Invalid header name: {}", e)),
164+
})?;
165+
let header_value = HeaderValue::from_str(&value)
166+
.map_err(|e| deno_npm_cache::DownloadError {
167+
status_code: None,
168+
error: JsErrorBox::generic(format!("Invalid header value: {}", e)),
169+
})?;
170+
Some(vec![(header_name, value)])
171+
}
172+
_ => None,
160173
};
161174

162175
AiDenoHttpClient::new()
163176
.download_with_retries_on_any_tokio_runtime(&url, headers)
164177
.await
178+
.map(|opt_bytes| {
179+
if let Some(bytes) = opt_bytes {
180+
deno_npm_cache::NpmCacheHttpClientResponse::Bytes(
181+
deno_npm_cache::NpmCacheHttpClientBytesResponse {
182+
bytes,
183+
etag: None,
184+
}
185+
)
186+
} else {
187+
deno_npm_cache::NpmCacheHttpClientResponse::NotFound
188+
}
189+
})
165190
}
166191
}

0 commit comments

Comments
 (0)