Skip to content

Commit 5a4f9a5

Browse files
committed
fix: use object_id for repl internal
1 parent 9f363c0 commit 5a4f9a5

File tree

4 files changed

+105
-82
lines changed

4 files changed

+105
-82
lines changed

cli/tools/jupyter/server.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use uuid::Uuid;
3636

3737
use super::JupyterReplProxy;
3838
use crate::cdp;
39-
use crate::tools::repl;
4039

4140
pub struct JupyterServer {
4241
execution_count: ExecutionCount,
@@ -322,11 +321,7 @@ impl JupyterServer {
322321
)
323322
.await
324323
.into_iter()
325-
.filter(|n| {
326-
!n.starts_with("Symbol(")
327-
&& n.starts_with(prop_name)
328-
&& n != &*repl::REPL_INTERNALS_NAME
329-
})
324+
.filter(|n| !n.starts_with("Symbol(") && n.starts_with(prop_name))
330325
.collect();
331326

332327
if prop_name.len() > cursor_pos {
@@ -347,7 +342,7 @@ impl JupyterServer {
347342
get_global_lexical_scope_names(&mut self.repl_session_proxy)
348343
.await,
349344
)
350-
.filter(|n| n.starts_with(expr) && n != &*repl::REPL_INTERNALS_NAME)
345+
.filter(|n| n.starts_with(expr))
351346
.collect::<Vec<_>>();
352347

353348
// sort and remove duplicates

cli/tools/repl/editor.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use rustyline_derive::Helper;
3838
use rustyline_derive::Hinter;
3939

4040
use super::channel::RustylineSyncMessageSender;
41-
use super::session::REPL_INTERNALS_NAME;
4241
use crate::cdp;
4342
use crate::colors;
4443

@@ -209,11 +208,7 @@ impl Completer for EditorHelper {
209208
let candidates = self
210209
.get_expression_property_names(sub_expr)
211210
.into_iter()
212-
.filter(|n| {
213-
!n.starts_with("Symbol(")
214-
&& n.starts_with(prop_name)
215-
&& n != &*REPL_INTERNALS_NAME
216-
})
211+
.filter(|n| !n.starts_with("Symbol(") && n.starts_with(prop_name))
217212
.collect();
218213

219214
Ok((pos - prop_name.len(), candidates))
@@ -223,7 +218,7 @@ impl Completer for EditorHelper {
223218
.get_expression_property_names("globalThis")
224219
.into_iter()
225220
.chain(self.get_global_lexical_scope_names())
226-
.filter(|n| n.starts_with(expr) && n != &*REPL_INTERNALS_NAME)
221+
.filter(|n| n.starts_with(expr))
227222
.collect::<Vec<_>>();
228223

229224
// sort and remove duplicates

cli/tools/repl/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ use editor::ReplEditor;
3535
pub use session::EvaluationOutput;
3636
pub use session::ReplSession;
3737
pub use session::TsEvaluateResponse;
38-
pub use session::REPL_INTERNALS_NAME;
3938

4039
use super::test::create_single_test_event_channel;
4140

cli/tools/repl/session.rs

Lines changed: 101 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright 2018-2025 the Deno authors. MIT license.
22

3+
use std::cell::RefCell;
34
use std::sync::Arc;
45

56
use deno_ast::diagnostics::Diagnostic;
@@ -45,6 +46,7 @@ use tokio::sync::Mutex;
4546
use crate::args::deno_json::TsConfigResolver;
4647
use crate::args::CliOptions;
4748
use crate::cdp;
49+
use crate::cdp::RemoteObjectId;
4850
use crate::colors;
4951
use crate::lsp::ReplLanguageServer;
5052
use crate::npm::installer::NpmInstaller;
@@ -82,67 +84,59 @@ fn comment_source_to_position_range(
8284
}
8385
}
8486

85-
/// We store functions used in the repl on this object because
86-
/// the user might modify the `Deno` global or delete it outright.
87-
pub static REPL_INTERNALS_NAME: Lazy<String> = Lazy::new(|| {
88-
let now = std::time::SystemTime::now();
89-
let seconds = now
90-
.duration_since(std::time::SystemTime::UNIX_EPOCH)
91-
.unwrap()
92-
.as_secs();
93-
// use a changing variable name to make it hard to depend on this
94-
format!("__DENO_REPL_INTERNALS_{seconds}__")
95-
});
96-
87+
thread_local! {
88+
/// We store functions used in the repl on this object because
89+
/// the user might modify the `Deno` global or delete it outright.
90+
pub static REPL_INTERNAL_OBJECT_ID: RefCell<Option<RemoteObjectId>> = const { RefCell::new(None) };
91+
}
9792
fn get_prelude() -> String {
98-
format!(
99-
r#"
100-
Object.defineProperty(globalThis, "{0}", {{
101-
enumerable: false,
102-
writable: false,
103-
value: {{
93+
r#"
94+
const repl_internal = {
10495
lastEvalResult: undefined,
10596
lastThrownError: undefined,
10697
inspectArgs: Deno[Deno.internal].inspectArgs,
10798
noColor: Deno.noColor,
108-
get closed() {{
109-
return typeof globalThis.closed === 'undefined' ? false : globalThis.closed;
110-
}}
111-
}},
112-
}});
113-
Object.defineProperty(globalThis, "_", {{
99+
get closed() {
100+
try {
101+
return typeof globalThis.closed === 'undefined' ? false : globalThis.closed;
102+
} catch {
103+
return false;
104+
}
105+
}
106+
}
107+
Object.defineProperty(globalThis, "_", {
114108
configurable: true,
115-
get: () => {0}.lastEvalResult,
116-
set: (value) => {{
117-
Object.defineProperty(globalThis, "_", {{
109+
get: () => repl_internal.lastEvalResult,
110+
set: (value) => {
111+
Object.defineProperty(globalThis, "_", {
118112
value: value,
119113
writable: true,
120114
enumerable: true,
121115
configurable: true,
122-
}});
116+
});
123117
console.log("Last evaluation result is no longer saved to _.");
124-
}},
125-
}});
118+
},
119+
});
126120
127-
Object.defineProperty(globalThis, "_error", {{
121+
Object.defineProperty(globalThis, "_error", {
128122
configurable: true,
129-
get: () => {0}.lastThrownError,
130-
set: (value) => {{
131-
Object.defineProperty(globalThis, "_error", {{
123+
get: () => repl_internal.lastThrownError,
124+
set: (value) => {
125+
Object.defineProperty(globalThis, "_error", {
132126
value: value,
133127
writable: true,
134128
enumerable: true,
135129
configurable: true,
136-
}});
130+
});
137131
138132
console.log("Last thrown error is no longer saved to _error.");
139-
}},
140-
}});
133+
},
134+
});
141135
142136
globalThis.clear = console.clear.bind(console);
143-
"#,
144-
*REPL_INTERNALS_NAME
145-
)
137+
138+
repl_internal
139+
"#.to_string()
146140
}
147141

148142
pub enum EvaluationOutput {
@@ -299,7 +293,8 @@ impl ReplSession {
299293
};
300294

301295
// inject prelude
302-
repl_session.evaluate_expression(&get_prelude()).await?;
296+
let evaluated = repl_session.evaluate_expression(&get_prelude()).await?;
297+
REPL_INTERNAL_OBJECT_ID.replace(evaluated.result.object_id);
303298

304299
Ok(repl_session)
305300
}
@@ -312,8 +307,13 @@ impl ReplSession {
312307
}
313308

314309
pub async fn closing(&mut self) -> Result<bool, AnyError> {
315-
let expression = format!(r#"{}.closed"#, *REPL_INTERNALS_NAME);
316-
let result = self.evaluate_expression(&expression).await?.result;
310+
let result = self
311+
.call_function_on_args_internal(
312+
r#"function () { return this.closed; }"#.to_string(),
313+
&[],
314+
)
315+
.await?
316+
.result;
317317
let closed = result
318318
.value
319319
.ok_or_else(|| anyhow!(result.description.unwrap()))?
@@ -500,18 +500,18 @@ impl ReplSession {
500500
.post_message_with_event_loop(
501501
"Runtime.callFunctionOn",
502502
Some(cdp::CallFunctionOnArgs {
503-
function_declaration: format!(
504-
r#"function (object) {{ {}.lastThrownError = object; }}"#,
505-
*REPL_INTERNALS_NAME
506-
),
507-
object_id: None,
503+
function_declaration:
504+
r#"function (object) { this.lastThrownError = object; }"#
505+
.to_string(),
506+
object_id: REPL_INTERNAL_OBJECT_ID.with_borrow(Clone::clone),
508507
arguments: Some(vec![error.into()]),
509508
silent: None,
510509
return_by_value: None,
511510
generate_preview: None,
512511
user_gesture: None,
513512
await_promise: None,
514-
execution_context_id: Some(self.context_id),
513+
// execution_context_id: Some(self.context_id),
514+
execution_context_id: None,
515515
object_group: None,
516516
throw_on_side_effect: None,
517517
}),
@@ -528,18 +528,16 @@ impl ReplSession {
528528
.post_message_with_event_loop(
529529
"Runtime.callFunctionOn",
530530
Some(cdp::CallFunctionOnArgs {
531-
function_declaration: format!(
532-
r#"function (object) {{ {}.lastEvalResult = object; }}"#,
533-
*REPL_INTERNALS_NAME
534-
),
535-
object_id: None,
531+
function_declaration: r#"function (object) { this.lastEvalResult = object; }"#.to_string(),
532+
object_id: REPL_INTERNAL_OBJECT_ID.with_borrow(Clone::clone),
536533
arguments: Some(vec![evaluate_result.into()]),
537534
silent: None,
538535
return_by_value: None,
539536
generate_preview: None,
540537
user_gesture: None,
541538
await_promise: None,
542-
execution_context_id: Some(self.context_id),
539+
// execution_context_id: Some(self.context_id),
540+
execution_context_id: None,
543541
object_group: None,
544542
throw_on_side_effect: None,
545543
}),
@@ -583,6 +581,41 @@ impl ReplSession {
583581
Ok(response)
584582
}
585583

584+
pub async fn call_function_on_args_internal(
585+
&mut self,
586+
function_declaration: String,
587+
args: &[cdp::RemoteObject],
588+
) -> Result<cdp::CallFunctionOnResponse, AnyError> {
589+
let arguments: Option<Vec<cdp::CallArgument>> = if args.is_empty() {
590+
None
591+
} else {
592+
Some(args.iter().map(|a| a.into()).collect())
593+
};
594+
595+
let inspect_response = self
596+
.post_message_with_event_loop(
597+
"Runtime.callFunctionOn",
598+
Some(cdp::CallFunctionOnArgs {
599+
function_declaration,
600+
object_id: REPL_INTERNAL_OBJECT_ID.with_borrow(Clone::clone),
601+
arguments,
602+
silent: None,
603+
return_by_value: None,
604+
generate_preview: None,
605+
user_gesture: None,
606+
await_promise: None,
607+
execution_context_id: None,
608+
object_group: None,
609+
throw_on_side_effect: None,
610+
}),
611+
)
612+
.await?;
613+
614+
let response: cdp::CallFunctionOnResponse =
615+
serde_json::from_value(inspect_response)?;
616+
Ok(response)
617+
}
618+
586619
pub async fn get_eval_value(
587620
&mut self,
588621
evaluate_result: &cdp::RemoteObject,
@@ -591,21 +624,22 @@ impl ReplSession {
591624
// consistent with the previous implementation we just get the preview result from
592625
// Deno.inspectArgs.
593626
let response = self
594-
.call_function_on_args(
595-
format!(
596-
r#"function (object) {{
597-
try {{
598-
return {0}.inspectArgs(["%o", object], {{ colors: !{0}.noColor }});
599-
}} catch (err) {{
600-
return {0}.inspectArgs(["%o", err]);
601-
}}
602-
}}"#,
603-
*REPL_INTERNALS_NAME
604-
),
627+
.call_function_on_args_internal(
628+
r#"function (object) {
629+
try {
630+
return this.inspectArgs(["%o", object], { colors: !this.noColor });
631+
} catch (err) {
632+
return this.inspectArgs(["%o", err]);
633+
}
634+
}"#
635+
.to_string(),
605636
&[evaluate_result.clone()],
606637
)
607638
.await?;
608-
let value = response.result.value.unwrap();
639+
let value = response
640+
.result
641+
.value
642+
.ok_or_else(|| anyhow!("failed to evaluate expression"))?;
609643
let s = value.as_str().unwrap();
610644

611645
Ok(s.to_string())

0 commit comments

Comments
 (0)