1
1
// Copyright 2018-2025 the Deno authors. MIT license.
2
2
3
+ use std:: cell:: RefCell ;
3
4
use std:: sync:: Arc ;
4
5
5
6
use deno_ast:: diagnostics:: Diagnostic ;
@@ -45,6 +46,7 @@ use tokio::sync::Mutex;
45
46
use crate :: args:: deno_json:: TsConfigResolver ;
46
47
use crate :: args:: CliOptions ;
47
48
use crate :: cdp;
49
+ use crate :: cdp:: RemoteObjectId ;
48
50
use crate :: colors;
49
51
use crate :: lsp:: ReplLanguageServer ;
50
52
use crate :: npm:: installer:: NpmInstaller ;
@@ -82,67 +84,59 @@ fn comment_source_to_position_range(
82
84
}
83
85
}
84
86
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
+ }
97
92
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 = {
104
95
lastEvalResult: undefined,
105
96
lastThrownError: undefined,
106
97
inspectArgs: Deno[Deno.internal].inspectArgs,
107
98
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, "_", {
114
108
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, "_", {
118
112
value: value,
119
113
writable: true,
120
114
enumerable: true,
121
115
configurable: true,
122
- }} );
116
+ });
123
117
console.log("Last evaluation result is no longer saved to _.");
124
- }} ,
125
- }} );
118
+ },
119
+ });
126
120
127
- Object.defineProperty(globalThis, "_error", {{
121
+ Object.defineProperty(globalThis, "_error", {
128
122
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", {
132
126
value: value,
133
127
writable: true,
134
128
enumerable: true,
135
129
configurable: true,
136
- }} );
130
+ });
137
131
138
132
console.log("Last thrown error is no longer saved to _error.");
139
- }} ,
140
- }} );
133
+ },
134
+ });
141
135
142
136
globalThis.clear = console.clear.bind(console);
143
- "# ,
144
- * REPL_INTERNALS_NAME
145
- )
137
+
138
+ repl_internal
139
+ "# . to_string ( )
146
140
}
147
141
148
142
pub enum EvaluationOutput {
@@ -299,7 +293,8 @@ impl ReplSession {
299
293
} ;
300
294
301
295
// 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 ) ;
303
298
304
299
Ok ( repl_session)
305
300
}
@@ -312,8 +307,13 @@ impl ReplSession {
312
307
}
313
308
314
309
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 ;
317
317
let closed = result
318
318
. value
319
319
. ok_or_else ( || anyhow ! ( result. description. unwrap( ) ) ) ?
@@ -500,18 +500,18 @@ impl ReplSession {
500
500
. post_message_with_event_loop (
501
501
"Runtime.callFunctionOn" ,
502
502
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) ,
508
507
arguments : Some ( vec ! [ error. into( ) ] ) ,
509
508
silent : None ,
510
509
return_by_value : None ,
511
510
generate_preview : None ,
512
511
user_gesture : None ,
513
512
await_promise : None ,
514
- execution_context_id : Some ( self . context_id ) ,
513
+ // execution_context_id: Some(self.context_id),
514
+ execution_context_id : None ,
515
515
object_group : None ,
516
516
throw_on_side_effect : None ,
517
517
} ) ,
@@ -528,18 +528,16 @@ impl ReplSession {
528
528
. post_message_with_event_loop (
529
529
"Runtime.callFunctionOn" ,
530
530
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) ,
536
533
arguments : Some ( vec ! [ evaluate_result. into( ) ] ) ,
537
534
silent : None ,
538
535
return_by_value : None ,
539
536
generate_preview : None ,
540
537
user_gesture : None ,
541
538
await_promise : None ,
542
- execution_context_id : Some ( self . context_id ) ,
539
+ // execution_context_id: Some(self.context_id),
540
+ execution_context_id : None ,
543
541
object_group : None ,
544
542
throw_on_side_effect : None ,
545
543
} ) ,
@@ -583,6 +581,41 @@ impl ReplSession {
583
581
Ok ( response)
584
582
}
585
583
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
+
586
619
pub async fn get_eval_value (
587
620
& mut self ,
588
621
evaluate_result : & cdp:: RemoteObject ,
@@ -591,21 +624,22 @@ impl ReplSession {
591
624
// consistent with the previous implementation we just get the preview result from
592
625
// Deno.inspectArgs.
593
626
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 ( ) ,
605
636
& [ evaluate_result. clone ( ) ] ,
606
637
)
607
638
. 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" ) ) ?;
609
643
let s = value. as_str ( ) . unwrap ( ) ;
610
644
611
645
Ok ( s. to_string ( ) )
0 commit comments