Skip to content

Commit fd9e3c5

Browse files
committed
feat: Upgrade to Deno 1.40.3
1 parent 5cfa578 commit fd9e3c5

File tree

2 files changed

+376
-0
lines changed

2 files changed

+376
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2+
3+
// deno-lint-ignore-file prefer-primordials
4+
5+
import { op_node_cp, op_node_cp_sync } from "ext:core/ops";
6+
7+
import {
8+
getValidatedPath,
9+
validateCpOptions,
10+
} from "ext:deno_node/internal/fs/utils.mjs";
11+
import { promisify } from "ext:deno_node/internal/util.mjs";
12+
13+
export function cpSync(src, dest, options) {
14+
validateCpOptions(options);
15+
const srcPath = getValidatedPath(src, "src");
16+
const destPath = getValidatedPath(dest, "dest");
17+
18+
op_node_cp_sync(srcPath, destPath);
19+
}
20+
21+
export function cp(src, dest, options, callback) {
22+
if (typeof options === "function") {
23+
callback = options;
24+
options = {};
25+
}
26+
validateCpOptions(options);
27+
const srcPath = getValidatedPath(src, "src");
28+
const destPath = getValidatedPath(dest, "dest");
29+
30+
op_node_cp(
31+
srcPath,
32+
destPath,
33+
).then(
34+
(res) => callback(null, res),
35+
(err) => callback(err, null),
36+
);
37+
}
38+
39+
export const cpPromise = promisify(cp);
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2+
3+
use std::sync::Arc;
4+
5+
use deno_ast::MediaType;
6+
use deno_ast::ModuleSpecifier;
7+
use deno_core::error::AnyError;
8+
use deno_core::serde_json;
9+
use deno_graph::DefaultModuleAnalyzer;
10+
use deno_graph::ModuleInfo;
11+
use deno_graph::ModuleParser;
12+
use deno_runtime::deno_webstorage::rusqlite::params;
13+
14+
use super::cache_db::CacheDB;
15+
use super::cache_db::CacheDBConfiguration;
16+
use super::cache_db::CacheFailure;
17+
use super::FastInsecureHasher;
18+
19+
const SELECT_MODULE_INFO: &str = "
20+
SELECT
21+
module_info
22+
FROM
23+
moduleinfocache
24+
WHERE
25+
specifier=?1
26+
AND media_type=?2
27+
AND source_hash=?3
28+
LIMIT 1";
29+
30+
pub static MODULE_INFO_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
31+
table_initializer: "CREATE TABLE IF NOT EXISTS moduleinfocache (
32+
specifier TEXT PRIMARY KEY,
33+
media_type TEXT NOT NULL,
34+
source_hash TEXT NOT NULL,
35+
module_info TEXT NOT NULL
36+
);",
37+
on_version_change: "DELETE FROM moduleinfocache;",
38+
preheat_queries: &[SELECT_MODULE_INFO],
39+
on_failure: CacheFailure::InMemory,
40+
};
41+
42+
pub struct ModuleInfoCacheSourceHash(String);
43+
44+
impl ModuleInfoCacheSourceHash {
45+
pub fn new(hash: u64) -> Self {
46+
Self(hash.to_string())
47+
}
48+
49+
pub fn from_source(source: &[u8]) -> Self {
50+
Self::new(FastInsecureHasher::hash(source))
51+
}
52+
53+
pub fn as_str(&self) -> &str {
54+
&self.0
55+
}
56+
}
57+
58+
/// A cache of `deno_graph::ModuleInfo` objects. Using this leads to a considerable
59+
/// performance improvement because when it exists we can skip parsing a module for
60+
/// deno_graph.
61+
pub struct ModuleInfoCache {
62+
conn: CacheDB,
63+
}
64+
65+
impl ModuleInfoCache {
66+
#[cfg(test)]
67+
pub fn new_in_memory(version: &'static str) -> Self {
68+
Self::new(CacheDB::in_memory(&MODULE_INFO_CACHE_DB, version))
69+
}
70+
71+
pub fn new(conn: CacheDB) -> Self {
72+
Self { conn }
73+
}
74+
75+
/// Useful for testing: re-create this cache DB with a different current version.
76+
#[cfg(test)]
77+
pub(crate) fn recreate_with_version(self, version: &'static str) -> Self {
78+
Self {
79+
conn: self.conn.recreate_with_version(version),
80+
}
81+
}
82+
83+
pub fn get_module_info(
84+
&self,
85+
specifier: &ModuleSpecifier,
86+
media_type: MediaType,
87+
expected_source_hash: &ModuleInfoCacheSourceHash,
88+
) -> Result<Option<ModuleInfo>, AnyError> {
89+
let query = SELECT_MODULE_INFO;
90+
let res = self.conn.query_row(
91+
query,
92+
params![
93+
&specifier.as_str(),
94+
serialize_media_type(media_type),
95+
expected_source_hash.as_str(),
96+
],
97+
|row| {
98+
let module_info: String = row.get(0)?;
99+
let module_info = serde_json::from_str(&module_info)?;
100+
Ok(module_info)
101+
},
102+
)?;
103+
Ok(res)
104+
}
105+
106+
pub fn set_module_info(
107+
&self,
108+
specifier: &ModuleSpecifier,
109+
media_type: MediaType,
110+
source_hash: &ModuleInfoCacheSourceHash,
111+
module_info: &ModuleInfo,
112+
) -> Result<(), AnyError> {
113+
let sql = "
114+
INSERT OR REPLACE INTO
115+
moduleinfocache (specifier, media_type, source_hash, module_info)
116+
VALUES
117+
(?1, ?2, ?3, ?4)";
118+
self.conn.execute(
119+
sql,
120+
params![
121+
specifier.as_str(),
122+
serialize_media_type(media_type),
123+
source_hash.as_str(),
124+
&serde_json::to_string(&module_info)?,
125+
],
126+
)?;
127+
Ok(())
128+
}
129+
130+
pub fn as_module_analyzer<'a>(
131+
&'a self,
132+
parser: &'a dyn ModuleParser,
133+
) -> ModuleInfoCacheModuleAnalyzer<'a> {
134+
ModuleInfoCacheModuleAnalyzer {
135+
module_info_cache: self,
136+
parser,
137+
}
138+
}
139+
}
140+
141+
pub struct ModuleInfoCacheModuleAnalyzer<'a> {
142+
module_info_cache: &'a ModuleInfoCache,
143+
parser: &'a dyn ModuleParser,
144+
}
145+
146+
impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
147+
fn analyze(
148+
&self,
149+
specifier: &ModuleSpecifier,
150+
source: Arc<str>,
151+
media_type: MediaType,
152+
) -> Result<ModuleInfo, deno_ast::Diagnostic> {
153+
// attempt to load from the cache
154+
let source_hash = ModuleInfoCacheSourceHash::from_source(source.as_bytes());
155+
match self.module_info_cache.get_module_info(
156+
specifier,
157+
media_type,
158+
&source_hash,
159+
) {
160+
Ok(Some(info)) => return Ok(info),
161+
Ok(None) => {}
162+
Err(err) => {
163+
log::debug!(
164+
"Error loading module cache info for {}. {:#}",
165+
specifier,
166+
err
167+
);
168+
}
169+
}
170+
171+
// otherwise, get the module info from the parsed source cache
172+
let analyzer = DefaultModuleAnalyzer::new(self.parser);
173+
let module_info = analyzer.analyze(specifier, source, media_type)?;
174+
175+
// then attempt to cache it
176+
if let Err(err) = self.module_info_cache.set_module_info(
177+
specifier,
178+
media_type,
179+
&source_hash,
180+
&module_info,
181+
) {
182+
log::debug!(
183+
"Error saving module cache info for {}. {:#}",
184+
specifier,
185+
err
186+
);
187+
}
188+
189+
Ok(module_info)
190+
}
191+
}
192+
193+
// todo(dsherret): change this to be stored as an integer next time
194+
// the cache version is bumped
195+
fn serialize_media_type(media_type: MediaType) -> &'static str {
196+
use MediaType::*;
197+
match media_type {
198+
JavaScript => "1",
199+
Jsx => "2",
200+
Mjs => "3",
201+
Cjs => "4",
202+
TypeScript => "5",
203+
Mts => "6",
204+
Cts => "7",
205+
Dts => "8",
206+
Dmts => "9",
207+
Dcts => "10",
208+
Tsx => "11",
209+
Json => "12",
210+
Wasm => "13",
211+
TsBuildInfo => "14",
212+
SourceMap => "15",
213+
Unknown => "16",
214+
}
215+
}
216+
217+
#[cfg(test)]
218+
mod test {
219+
use deno_graph::PositionRange;
220+
use deno_graph::SpecifierWithRange;
221+
222+
use super::*;
223+
224+
#[test]
225+
pub fn module_info_cache_general_use() {
226+
let cache = ModuleInfoCache::new_in_memory("1.0.0");
227+
let specifier1 =
228+
ModuleSpecifier::parse("https://localhost/mod.ts").unwrap();
229+
let specifier2 =
230+
ModuleSpecifier::parse("https://localhost/mod2.ts").unwrap();
231+
assert_eq!(
232+
cache
233+
.get_module_info(
234+
&specifier1,
235+
MediaType::JavaScript,
236+
&ModuleInfoCacheSourceHash::new(1)
237+
)
238+
.unwrap(),
239+
None
240+
);
241+
242+
let mut module_info = ModuleInfo::default();
243+
module_info.jsdoc_imports.push(SpecifierWithRange {
244+
range: PositionRange {
245+
start: deno_graph::Position {
246+
line: 0,
247+
character: 3,
248+
},
249+
end: deno_graph::Position {
250+
line: 1,
251+
character: 2,
252+
},
253+
},
254+
text: "test".to_string(),
255+
});
256+
cache
257+
.set_module_info(
258+
&specifier1,
259+
MediaType::JavaScript,
260+
&ModuleInfoCacheSourceHash::new(1),
261+
&module_info,
262+
)
263+
.unwrap();
264+
assert_eq!(
265+
cache
266+
.get_module_info(
267+
&specifier1,
268+
MediaType::JavaScript,
269+
&ModuleInfoCacheSourceHash::new(1)
270+
)
271+
.unwrap(),
272+
Some(module_info.clone())
273+
);
274+
assert_eq!(
275+
cache
276+
.get_module_info(
277+
&specifier2,
278+
MediaType::JavaScript,
279+
&ModuleInfoCacheSourceHash::new(1)
280+
)
281+
.unwrap(),
282+
None,
283+
);
284+
// different media type
285+
assert_eq!(
286+
cache
287+
.get_module_info(
288+
&specifier1,
289+
MediaType::TypeScript,
290+
&ModuleInfoCacheSourceHash::new(1)
291+
)
292+
.unwrap(),
293+
None,
294+
);
295+
// different source hash
296+
assert_eq!(
297+
cache
298+
.get_module_info(
299+
&specifier1,
300+
MediaType::JavaScript,
301+
&ModuleInfoCacheSourceHash::new(2)
302+
)
303+
.unwrap(),
304+
None,
305+
);
306+
307+
// try recreating with the same version
308+
let cache = cache.recreate_with_version("1.0.0");
309+
310+
// should get it
311+
assert_eq!(
312+
cache
313+
.get_module_info(
314+
&specifier1,
315+
MediaType::JavaScript,
316+
&ModuleInfoCacheSourceHash::new(1)
317+
)
318+
.unwrap(),
319+
Some(module_info)
320+
);
321+
322+
// try recreating with a different version
323+
let cache = cache.recreate_with_version("1.0.1");
324+
325+
// should no longer exist
326+
assert_eq!(
327+
cache
328+
.get_module_info(
329+
&specifier1,
330+
MediaType::JavaScript,
331+
&ModuleInfoCacheSourceHash::new(1)
332+
)
333+
.unwrap(),
334+
None,
335+
);
336+
}
337+
}

0 commit comments

Comments
 (0)