1use std::any::Any;
6use std::rc::Rc;
7
8use oxide_core::heap::string::StringRepr;
9use oxide_core::{Intrinsic, NativeCx, RootMark};
10
11use super::RuntimeError;
12use super::buffer::{TypedArrayKind, TypedArrayView};
13use super::compile::{ScriptCompileError, compile_script, syntax_location};
14use super::context::{Context, EvalOptions, FunctionBytecodeRef, ModuleBytecodeRef, QjsHelpers};
15use super::function::{FunctionOptions, HostFunction, Raw, Scope, host_body};
16use super::promise::PromiseCapability;
17use super::property::{
18 AccessorValue, CompleteOrdinaryPropertyDescriptor, DescriptorField, Key,
19 OrdinaryPropertyDescriptor, PropertyKey, WellKnownSymbol,
20};
21use super::runtime::{Preloaded, PromiseSnapshot, PromiseState, Shared, slot};
22use super::value::{CallableRef, ObjectRef, Slot, SymbolRef, Value};
23use crate::engine::api::error::{Error, NativeErrorKind};
24use crate::engine::compiler::CompileOptions;
25use crate::engine::value::JsString;
26use crate::engine::value::bigint::JsBigInt;
27
28pub type JsResult<T> = Result<T, RuntimeError>;
30
31pub(crate) struct View<'a> {
35 pub(crate) core: NativeCx<'a>,
36 pub(crate) shared: &'a Rc<Shared>,
37 mark: RootMark,
38}
39
40impl Drop for View<'_> {
41 fn drop(&mut self) {
42 self.core.heap_mut().roots().truncate(self.mark);
43 }
44}
45
46impl<'a> View<'a> {
47 pub(crate) fn new(mut core: NativeCx<'a>, shared: &'a Rc<Shared>) -> Self {
48 let mark = core.heap_mut().roots().mark();
49 View { core, shared, mark }
50 }
51}
52
53impl View<'_> {
54 pub(crate) fn lift(&mut self, value: oxide_core::Value) -> JsResult<Value> {
59 use oxide_core::value::Kind;
60 Ok(match value.kind() {
61 Kind::Undefined => Value::Undefined,
62 Kind::Null => Value::Null,
63 Kind::Bool => Value::Bool(value.as_bool().unwrap_or(false)),
64 Kind::Int32 => Value::Int(value.as_int32().unwrap_or(0)),
65 Kind::Number => Value::Float(value.as_f64().unwrap_or(f64::NAN)),
66 Kind::String => Value::String(match self.core.string_repr(value) {
67 Some(StringRepr::OneByte(units)) => JsString::try_from_latin1(units)?,
68 Some(StringRepr::TwoByte(units)) => JsString::try_from_utf16_slice(units)?,
69 None => JsString::from_static(""),
70 }),
71 Kind::BigInt => {
72 let decimal = self.core.bigint_decimal(value).unwrap_or_default();
73 Value::BigInt(
74 JsBigInt::from_decimal_unchecked(&decimal)
75 .ok_or(RuntimeError::Invariant("a BigInt's decimal text"))?,
76 )
77 }
78 Kind::Symbol => Value::Symbol(SymbolRef {
79 slot: slot(self.shared, self.core.hold(value), value),
80 }),
81 Kind::Object => Value::Object(ObjectRef {
82 slot: slot(self.shared, self.core.hold(value), value),
83 }),
84 _ => Value::Undefined,
85 })
86 }
87
88 pub(crate) fn lift_object(&mut self, object: oxide_core::ObjectId) -> ObjectRef {
89 let value = oxide_core::Value::object(object);
90 ObjectRef {
91 slot: slot(self.shared, self.core.hold(value), value),
92 }
93 }
94
95 pub(crate) fn lower(&mut self, value: &Value) -> JsResult<oxide_core::Value> {
97 let lowered = match value {
98 Value::Undefined => oxide_core::Value::UNDEFINED,
99 Value::Null => oxide_core::Value::NULL,
100 Value::Bool(value) => oxide_core::Value::bool(*value),
101 Value::Int(value) => oxide_core::Value::int32(*value),
102 Value::Float(value) => oxide_core::Value::number(*value),
103 Value::String(text) => {
104 let value = match (text.flat_latin1(), text.flat_utf16()) {
105 (Some(units), _) => {
106 self.core.new_string_repr(StringRepr::OneByte(units.into()))
107 }
108 (_, Some(units)) => self.core.new_string_units(units),
109 _ => self
110 .core
111 .new_string_units(&text.utf16_units().collect::<Vec<_>>()),
112 }?;
113 self.temp(value);
114 value
115 }
116 Value::BigInt(big) => {
117 let decimal = big
118 .to_string_radix(10)
119 .map_err(|error| RuntimeError::Internal(format!("{error:?}")))?;
120 let value = self
121 .core
122 .new_bigint(&decimal)
123 .ok_or(RuntimeError::Invariant("a BigInt's decimal text"))??;
124 self.temp(value);
125 value
126 }
127 Value::Symbol(symbol) => self.own(symbol.slot.as_ref())?,
128 Value::Object(object) => self.own(object.slot.as_ref())?,
129 };
130 Ok(lowered)
131 }
132
133 pub(crate) fn lower_all(&mut self, values: &[Value]) -> JsResult<Vec<oxide_core::Value>> {
134 values.iter().map(|value| self.lower(value)).collect()
135 }
136
137 pub(crate) fn own(&self, slot: &Slot) -> JsResult<oxide_core::Value> {
139 if slot.of(self.shared) {
140 Ok(slot.value)
141 } else if slot.shared.strong_count() == 0 {
142 Err(RuntimeError::Invariant("a value of a dropped runtime"))
143 } else {
144 Err(RuntimeError::Invariant("a value of another runtime"))
145 }
146 }
147
148 pub(crate) fn object(&self, object: &ObjectRef) -> JsResult<oxide_core::ObjectId> {
149 self.own(&object.slot)?
150 .as_object()
151 .ok_or(RuntimeError::Invariant("an object reference"))
152 }
153
154 fn function(&mut self, callable: &CallableRef) -> JsResult<oxide_core::Value> {
155 Ok(oxide_core::Value::object(
156 self.object(callable.as_object())?,
157 ))
158 }
159
160 fn temp(&mut self, value: oxide_core::Value) {
161 self.core.heap_mut().roots().push(value);
162 }
163
164 pub(crate) fn key(&mut self, key: &PropertyKey) -> JsResult<oxide_core::PropertyKey> {
166 let key = match &key.0 {
167 Key::Index(index) => oxide_core::PropertyKey::index(*index).map_or_else(
168 || {
169 let units: Vec<u16> = index.to_string().encode_utf16().collect();
170 self.core.key_from_units(&units)
171 },
172 Ok,
173 )?,
174 Key::String(text) => {
175 let units: Vec<u16> = text.utf16_units().collect();
176 self.core.key_from_units(&units)?
177 }
178 Key::Symbol(symbol) => {
180 let value = self.own(&symbol.slot)?;
181 return self
182 .core
183 .key_from_symbol(value)
184 .ok_or(RuntimeError::Invariant("a symbol reference"));
185 }
186 };
187 if let Some(value) = key.heap_value() {
189 self.temp(value);
190 }
191 Ok(key)
192 }
193
194 pub(crate) fn lift_key(&mut self, key: oxide_core::PropertyKey) -> JsResult<PropertyKey> {
196 Ok(match self.core.key_name(key) {
197 oxide_core::KeyName::Index(index) => PropertyKey(Key::Index(index)),
198 oxide_core::KeyName::String(units) => {
199 PropertyKey(Key::String(JsString::try_from_utf16(units)?))
200 }
201 oxide_core::KeyName::Symbol(symbol) => match self.lift(symbol)? {
202 Value::Symbol(symbol) => PropertyKey(Key::Symbol(symbol)),
203 _ => return Err(RuntimeError::Invariant("a symbol key")),
204 },
205 })
206 }
207
208 pub(crate) fn thrown(&mut self, thrown: oxide_core::Throw) -> RuntimeError {
211 if self.core.is_interrupted() {
212 if self.core.owns_code() {
213 self.core.clear_interrupted();
214 }
215 return RuntimeError::Interrupted;
216 }
217 let out_of_memory = self.core.intrinsic(Intrinsic::OutOfMemoryError);
218 if thrown.0.as_object() == Some(out_of_memory) {
219 return RuntimeError::OutOfMemory;
220 }
221 match self.lift(thrown.0) {
222 Ok(value) => RuntimeError::Exception(value),
223 Err(error) => error,
224 }
225 }
226
227 pub(crate) fn complete(
229 &mut self,
230 result: Result<oxide_core::Value, oxide_core::Throw>,
231 ) -> JsResult<Value> {
232 match result {
233 Ok(value) => self.lift(value),
234 Err(thrown) => Err(self.thrown(thrown)),
235 }
236 }
237
238 pub(crate) fn complete_with<T>(&mut self, result: Result<T, oxide_core::Throw>) -> JsResult<T> {
239 result.map_err(|thrown| self.thrown(thrown))
240 }
241
242 fn lower_descriptor(
246 &mut self,
247 descriptor: &OrdinaryPropertyDescriptor,
248 ) -> JsResult<oxide_core::PropertyDescriptor> {
249 let accessor = |view: &mut Self, field: &DescriptorField<AccessorValue>| match field {
250 DescriptorField::Absent => Ok(None),
251 DescriptorField::Present(AccessorValue::Undefined) => {
252 Ok(Some(oxide_core::Value::UNDEFINED))
253 }
254 DescriptorField::Present(AccessorValue::Callable(function)) => {
255 view.own(&function.0.slot).map(Some)
256 }
257 };
258 Ok(oxide_core::PropertyDescriptor {
259 value: match &descriptor.value {
260 DescriptorField::Absent => None,
261 DescriptorField::Present(value) => Some(self.lower(value)?),
262 },
263 get: accessor(self, &descriptor.get)?,
264 set: accessor(self, &descriptor.set)?,
265 writable: descriptor.writable.into_option(),
266 enumerable: descriptor.enumerable.into_option(),
267 configurable: descriptor.configurable.into_option(),
268 })
269 }
270
271 fn lift_descriptor(
272 &mut self,
273 descriptor: oxide_core::PropertyDescriptor,
274 ) -> JsResult<CompleteOrdinaryPropertyDescriptor> {
275 if descriptor.is_accessor() {
276 let callable = |view: &mut Self, value: Option<oxide_core::Value>| {
277 Ok::<_, RuntimeError>(match value {
278 Some(value) if !value.is_undefined() => match view.lift(value)? {
279 Value::Object(object) => Some(CallableRef(object)),
280 _ => None,
281 },
282 _ => None,
283 })
284 };
285 Ok(CompleteOrdinaryPropertyDescriptor::Accessor {
286 get: callable(self, descriptor.get)?,
287 set: callable(self, descriptor.set)?,
288 enumerable: descriptor.enumerable.unwrap_or(false),
289 configurable: descriptor.configurable.unwrap_or(false),
290 })
291 } else {
292 let value = descriptor.value.unwrap_or(oxide_core::Value::UNDEFINED);
293 Ok(CompleteOrdinaryPropertyDescriptor::Data {
294 value: self.lift(value)?,
295 writable: descriptor.writable.unwrap_or(false),
296 enumerable: descriptor.enumerable.unwrap_or(false),
297 configurable: descriptor.configurable.unwrap_or(false),
298 })
299 }
300 }
301
302 fn modules_supported(&mut self) -> JsResult<()> {
305 if self.core.owns_code() {
306 Ok(())
307 } else {
308 Err(RuntimeError::Unsupported("modules inside a host function"))
309 }
310 }
311
312 pub(crate) fn eval(&mut self, source: &str) -> JsResult<Value> {
315 self.eval_bytes(source.as_bytes())
316 }
317
318 pub(crate) fn eval_bytes(&mut self, source: &[u8]) -> JsResult<Value> {
319 self.eval_bytes_with_filename(source, crate::engine::compiler::DEFAULT_EVAL_FILENAME)
320 }
321
322 pub(crate) fn eval_with_filename(&mut self, source: &str, filename: &str) -> JsResult<Value> {
323 self.eval_bytes_with_filename(source.as_bytes(), filename)
324 }
325
326 pub(crate) fn eval_with_options(
327 &mut self,
328 source: &str,
329 options: &EvalOptions,
330 ) -> JsResult<Value> {
331 self.eval_bytes_with_options(source.as_bytes(), options)
332 }
333
334 pub(crate) fn eval_bytes_with_options(
335 &mut self,
336 source: &[u8],
337 options: &EvalOptions,
338 ) -> JsResult<Value> {
339 let script = self.compile_script_bytes(source, &options.filename, options.transient)?;
340 self.execute(&script)
341 }
342
343 pub(crate) fn eval_bytes_with_filename(
344 &mut self,
345 source: &[u8],
346 filename: &str,
347 ) -> JsResult<Value> {
348 let script = self.compile_bytes_with_filename(source, filename)?;
349 self.execute(&script)
350 }
351
352 pub(crate) fn compile(&mut self, source: &str) -> JsResult<FunctionBytecodeRef> {
353 self.compile_bytes(source.as_bytes())
354 }
355
356 pub(crate) fn compile_bytes(&mut self, source: &[u8]) -> JsResult<FunctionBytecodeRef> {
357 self.compile_bytes_with_filename(source, crate::engine::compiler::DEFAULT_EVAL_FILENAME)
358 }
359
360 pub(crate) fn compile_with_filename(
361 &mut self,
362 source: &str,
363 filename: &str,
364 ) -> JsResult<FunctionBytecodeRef> {
365 self.compile_bytes_with_filename(source.as_bytes(), filename)
366 }
367
368 pub(crate) fn compile_with_options(
369 &mut self,
370 source: &str,
371 options: &CompileOptions,
372 ) -> JsResult<FunctionBytecodeRef> {
373 self.compile_bytes_with_options(source.as_bytes(), options)
374 }
375
376 pub(crate) fn compile_bytes_with_options(
377 &mut self,
378 source: &[u8],
379 options: &CompileOptions,
380 ) -> JsResult<FunctionBytecodeRef> {
381 self.compile_script_bytes(source, &options.filename, options.transient)
382 }
383
384 pub(crate) fn compile_bytes_with_filename(
385 &mut self,
386 source: &[u8],
387 filename: &str,
388 ) -> JsResult<FunctionBytecodeRef> {
389 self.compile_script_bytes(source, filename, false)
390 }
391
392 fn compile_script_bytes(
396 &mut self,
397 source: &[u8],
398 filename: &str,
399 transient: bool,
400 ) -> JsResult<FunctionBytecodeRef> {
401 let debug_info = self.shared.debug_info.get();
402 let lowered = {
403 let mut compiler = self.core.compiler(transient);
404 compile_script(&mut compiler, source, filename, debug_info)
405 };
406 match lowered {
407 Ok(lowered) => Ok(FunctionBytecodeRef::new(
408 self.lift_object(lowered.function),
409 #[cfg(test)]
410 source,
411 #[cfg(test)]
412 filename,
413 #[cfg(test)]
414 debug_info,
415 )),
416 Err(ScriptCompileError::Front(error)) => {
417 Err(self.throw_compile_error(&error, source, filename))
418 }
419 Err(ScriptCompileError::Lower(error)) => match error {
420 crate::engine::compiler::register::LowerError::Syntax(message) => {
421 let error = Error::new(crate::engine::api::error::ErrorKind::Syntax, message);
422 Err(self.throw_compile_error(&error, source, filename))
423 }
424 other => Err(RuntimeError::Internal(other.to_string())),
425 },
426 }
427 }
428
429 fn throw_compile_error(
432 &mut self,
433 error: &Error,
434 source: &[u8],
435 filename: &str,
436 ) -> RuntimeError {
437 use crate::engine::api::error::ErrorKind;
438 let kind = match error.kind() {
439 ErrorKind::Syntax => oxide_core::ErrorKind::Syntax,
440 ErrorKind::Type => oxide_core::ErrorKind::Type,
441 ErrorKind::Reference => oxide_core::ErrorKind::Reference,
442 ErrorKind::Range => oxide_core::ErrorKind::Range,
443 ErrorKind::JsInternal => oxide_core::ErrorKind::Internal,
444 ErrorKind::Unsupported => {
445 return RuntimeError::Unsupported("constructs of this source");
446 }
447 ErrorKind::Internal | ErrorKind::Io => return RuntimeError::Compile(error.clone()),
448 };
449 let created = match syntax_location(error, source) {
450 Some((line, column)) => {
451 self.core
452 .new_located_error(kind, error.message(), filename, line, column)
453 }
454 None => self.core.new_error(kind, error.message()),
455 };
456 match created {
457 Ok(thrown) => self.thrown(oxide_core::Throw(thrown)),
458 Err(error) => error.into(),
459 }
460 }
461
462 pub(crate) fn execute(&mut self, script: &FunctionBytecodeRef) -> JsResult<Value> {
463 let function = self.object(script.function())?;
464 let result = self.core.run_script(function);
465 self.complete(result)
466 }
467
468 pub(crate) fn compile_module(&mut self, source: &str) -> JsResult<ModuleBytecodeRef> {
471 self.compile_module_bytes(source.as_bytes())
472 }
473
474 pub(crate) fn compile_module_bytes(&mut self, source: &[u8]) -> JsResult<ModuleBytecodeRef> {
475 self.compile_module_bytes_with_filename(
476 source,
477 crate::engine::compiler::DEFAULT_EVAL_FILENAME,
478 )
479 }
480
481 pub(crate) fn compile_module_with_filename(
482 &mut self,
483 source: &str,
484 filename: &str,
485 ) -> JsResult<ModuleBytecodeRef> {
486 self.compile_module_bytes_with_filename(source.as_bytes(), filename)
487 }
488
489 pub(crate) fn compile_module_bytes_with_options(
490 &mut self,
491 source: &[u8],
492 options: &CompileOptions,
493 ) -> JsResult<ModuleBytecodeRef> {
494 self.compile_module_bytes_with_filename(source, &options.filename)
495 }
496
497 pub(crate) fn compile_module_bytes_with_filename(
498 &mut self,
499 source: &[u8],
500 filename: &str,
501 ) -> JsResult<ModuleBytecodeRef> {
502 self.compile_module_bytes_with_import_meta(source, filename, Vec::new())
503 }
504
505 pub(crate) fn compile_module_bytes_with_import_meta(
506 &mut self,
507 source: &[u8],
508 filename: &str,
509 import_meta: Vec<(String, Value)>,
510 ) -> JsResult<ModuleBytecodeRef> {
511 self.modules_supported()?;
512 let debug_info = self.shared.debug_info.get();
513 let compiled = {
514 let mut compiler = self.core.compiler(false);
515 super::compile::compile_module(&mut compiler, filename, source, debug_info)
516 };
517 match compiled {
518 Ok((
519 oxide_core::vm::module::ModuleSource::Compiled {
520 function, tables, ..
521 },
522 _,
523 )) => {
524 let function = self.lift_object(function);
525 self.core.forget_module(filename);
528 self.shared.modules.borrow_mut().insert(
529 filename.to_owned(),
530 Preloaded::Compiled {
531 function,
532 tables,
533 import_meta,
534 },
535 );
536 Ok(ModuleBytecodeRef::new(filename))
537 }
538 Ok(_) => Err(RuntimeError::Invariant("a compiled module")),
539 Err(super::compile::ModuleCompileError::Front(error)) => {
540 Err(self.throw_compile_error(&error, source, filename))
541 }
542 Err(super::compile::ModuleCompileError::Core(failure)) => {
543 let thrown = self.core.new_error(failure.kind, &failure.message)?;
544 Err(self.thrown(oxide_core::Throw(thrown)))
545 }
546 }
547 }
548
549 pub(crate) fn execute_module(&mut self, module: &ModuleBytecodeRef) -> JsResult<Value> {
550 self.modules_supported()?;
551 let result = self.core.run_module(module.name());
552 self.complete(result)
553 }
554
555 pub(crate) fn call(
558 &mut self,
559 callable: &CallableRef,
560 this_value: Value,
561 arguments: &[Value],
562 ) -> JsResult<Value> {
563 let function = self.function(callable)?;
564 let this = self.lower(&this_value)?;
565 let args = self.lower_all(arguments)?;
566 let result = self.core.call(function, this, &args);
567 self.complete(result)
568 }
569
570 pub(crate) fn construct(
571 &mut self,
572 constructor: &CallableRef,
573 arguments: &[Value],
574 ) -> JsResult<Value> {
575 self.construct_with_new_target(constructor, constructor, arguments)
576 }
577
578 pub(crate) fn construct_with_new_target(
579 &mut self,
580 constructor: &CallableRef,
581 new_target: &CallableRef,
582 arguments: &[Value],
583 ) -> JsResult<Value> {
584 let function = self.function(constructor)?;
585 let target = self.function(new_target)?;
586 let args = self.lower_all(arguments)?;
587 if !self.core.is_constructor(function) {
588 let error = self
589 .core
590 .new_error(oxide_core::ErrorKind::Type, "not a constructor")?;
591 return Err(self.thrown(oxide_core::Throw(error)));
592 }
593 let result = self.core.construct(function, &args, target);
594 self.complete(result)
595 }
596
597 pub(crate) fn new_object(&mut self) -> JsResult<ObjectRef> {
600 let object = self.core.new_object()?;
601 Ok(self.lift_object(object))
602 }
603
604 pub(crate) fn new_object_with_prototype(
605 &mut self,
606 prototype: Option<&ObjectRef>,
607 ) -> JsResult<ObjectRef> {
608 let prototype = prototype.map(|p| self.object(p)).transpose()?;
609 let object = self.core.new_object_with_prototype(prototype)?;
610 Ok(self.lift_object(object))
611 }
612
613 pub(crate) fn new_array(&mut self) -> JsResult<ObjectRef> {
614 self.new_array_from_values(Vec::new())
615 }
616
617 pub(crate) fn new_array_from_values(&mut self, values: Vec<Value>) -> JsResult<ObjectRef> {
618 let values = self.lower_all(&values)?;
619 let result = self.core.new_array_from(&values);
620 let array = self.complete_with(result)?;
621 Ok(self.lift_object(array))
622 }
623
624 pub(crate) fn get_own_property(
625 &mut self,
626 object: &ObjectRef,
627 key: &PropertyKey,
628 ) -> JsResult<Option<CompleteOrdinaryPropertyDescriptor>> {
629 let id = self.object(object)?;
630 let key = self.key(key)?;
631 let result = self.core.get_own_property(id, key);
632 match self.complete_with(result)? {
633 Some(descriptor) => self.lift_descriptor(descriptor).map(Some),
634 None => Ok(None),
635 }
636 }
637
638 pub(crate) fn define_own_property(
639 &mut self,
640 object: &ObjectRef,
641 key: &PropertyKey,
642 descriptor: &OrdinaryPropertyDescriptor,
643 ) -> JsResult<bool> {
644 let id = self.object(object)?;
645 let key = self.key(key)?;
646 let descriptor = self.lower_descriptor(descriptor)?;
647 let result = self.core.define_own_property(id, key, &descriptor);
648 self.complete_with(result)
649 }
650
651 pub(crate) fn get_property(
652 &mut self,
653 object: &ObjectRef,
654 key: &PropertyKey,
655 ) -> JsResult<Value> {
656 self.get_property_with_receiver(object, key, Value::Object(object.clone()))
657 }
658
659 pub(crate) fn get_property_with_receiver(
660 &mut self,
661 object: &ObjectRef,
662 key: &PropertyKey,
663 receiver: Value,
664 ) -> JsResult<Value> {
665 let id = self.object(object)?;
666 let key = self.key(key)?;
667 let receiver = self.lower(&receiver)?;
668 let result = self.core.get(id, key, receiver);
669 self.complete(result)
670 }
671
672 pub(crate) fn set_property(
673 &mut self,
674 object: &ObjectRef,
675 key: &PropertyKey,
676 value: Value,
677 ) -> JsResult<bool> {
678 self.set_property_with_receiver(object, key, value, Value::Object(object.clone()))
679 }
680
681 pub(crate) fn set_property_with_receiver(
682 &mut self,
683 object: &ObjectRef,
684 key: &PropertyKey,
685 value: Value,
686 receiver: Value,
687 ) -> JsResult<bool> {
688 let id = self.object(object)?;
689 let key = self.key(key)?;
690 let value = self.lower(&value)?;
691 let receiver = self.lower(&receiver)?;
692 let result = self.core.set(id, key, value, receiver);
693 self.complete_with(result)
694 }
695
696 pub(crate) fn delete_property(
697 &mut self,
698 object: &ObjectRef,
699 key: &PropertyKey,
700 ) -> JsResult<bool> {
701 let id = self.object(object)?;
702 let key = self.key(key)?;
703 let result = self.core.delete_property(id, key);
704 self.complete_with(result)
705 }
706
707 pub(crate) fn has_property(&mut self, object: &ObjectRef, key: &PropertyKey) -> JsResult<bool> {
708 let id = self.object(object)?;
709 let key = self.key(key)?;
710 let result = self.core.has_property(id, key);
711 self.complete_with(result)
712 }
713
714 pub(crate) fn has_own_property(
715 &mut self,
716 object: &ObjectRef,
717 key: &PropertyKey,
718 ) -> JsResult<bool> {
719 let id = self.object(object)?;
720 let key = self.key(key)?;
721 let result = self.core.has_own_property(id, key);
722 self.complete_with(result)
723 }
724
725 pub(crate) fn own_property_keys(&mut self, object: &ObjectRef) -> JsResult<Vec<PropertyKey>> {
726 let id = self.object(object)?;
727 let result = self.core.own_property_keys(id);
728 let keys = self.complete_with(result)?;
729 keys.into_iter().map(|key| self.lift_key(key)).collect()
730 }
731
732 pub(crate) fn get_prototype_of(&mut self, object: &ObjectRef) -> JsResult<Option<ObjectRef>> {
733 let id = self.object(object)?;
734 let result = self.core.get_prototype_of(id);
735 let prototype = self.complete_with(result)?;
736 Ok(prototype.map(|prototype| self.lift_object(prototype)))
737 }
738
739 pub(crate) fn set_prototype_of(
740 &mut self,
741 object: &ObjectRef,
742 prototype: Option<&ObjectRef>,
743 ) -> JsResult<bool> {
744 let id = self.object(object)?;
745 let prototype = prototype.map(|p| self.object(p)).transpose()?;
746 let result = self.core.set_prototype_of(id, prototype);
747 self.complete_with(result)
748 }
749
750 pub(crate) fn as_callable(&mut self, object: &ObjectRef) -> JsResult<Option<CallableRef>> {
751 let value = self.own(&object.slot)?;
752 Ok(self
753 .core
754 .is_callable(value)
755 .then(|| CallableRef(object.clone())))
756 }
757
758 pub(crate) fn is_constructor(&mut self, object: &ObjectRef) -> JsResult<bool> {
759 let value = self.own(&object.slot)?;
760 Ok(self.core.is_constructor(value))
761 }
762
763 pub(crate) fn is_array_object(&mut self, object: &ObjectRef) -> JsResult<bool> {
764 let value = self.own(&object.slot)?;
765 let result = self.core.is_array(value);
766 self.complete_with(result)
767 }
768
769 pub(crate) fn is_error_object(&mut self, object: &ObjectRef) -> JsResult<bool> {
770 let value = self.own(&object.slot)?;
771 Ok(self.core.is_error(value))
772 }
773
774 #[allow(clippy::wrong_self_convention)]
777 pub(crate) fn to_js_string(&mut self, value: &Value) -> JsResult<JsString> {
778 let value = self.lower(value)?;
779 let result = self.core.to_string(value);
780 match self.complete(result)? {
781 Value::String(text) => Ok(text),
782 _ => Err(RuntimeError::Invariant("ToString returned a string")),
783 }
784 }
785
786 #[allow(clippy::wrong_self_convention)]
787 pub(crate) fn to_number(&mut self, value: &Value) -> JsResult<f64> {
788 let value = self.lower(value)?;
789 let result = self.core.to_number(value);
790 self.complete_with(result)
791 }
792
793 pub(crate) fn detach_array_buffer(&mut self, value: &Value) -> JsResult<()> {
794 let value = self.lower(value)?;
795 let result = self.core.detach_array_buffer(value);
796 self.complete_with(result)
797 }
798
799 pub(crate) fn type_of(&mut self, value: &Value) -> JsResult<String> {
800 let value = self.lower(value)?;
801 Ok(self.core.type_of(value))
802 }
803
804 pub(crate) fn print_value(&mut self, value: &Value) -> JsResult<String> {
805 let value = self.lower(value)?;
806 Ok(self.core.print_value(value))
807 }
808
809 pub(crate) fn qjs_print_value_bytes(&mut self, value: &Value) -> JsResult<Vec<u8>> {
810 let value = self.lower(value)?;
811 Ok(self.core.print_value_bytes(value))
812 }
813
814 pub(crate) fn new_symbol(&mut self, description: Option<JsString>) -> JsResult<SymbolRef> {
817 let units: Option<Vec<u16>> = description.map(|text| text.utf16_units().collect());
818 let symbol = self.core.new_symbol(units.as_deref())?;
819 match self.lift(symbol)? {
820 Value::Symbol(symbol) => Ok(symbol),
821 _ => Err(RuntimeError::Invariant("a new symbol")),
822 }
823 }
824
825 pub(crate) fn symbol_description(&mut self, symbol: &SymbolRef) -> JsResult<Option<JsString>> {
826 let value = self.own(&symbol.slot)?;
827 self.core
828 .symbol_description(value)
829 .map(JsString::try_from_utf16)
830 .transpose()
831 .map_err(RuntimeError::from)
832 }
833
834 pub(crate) fn well_known_symbol(&mut self, symbol: WellKnownSymbol) -> JsResult<SymbolRef> {
835 let value = self
836 .core
837 .well_known_symbol(symbol.name())
838 .ok_or(RuntimeError::Invariant("a well-known symbol"))?;
839 match self.lift(value)? {
840 Value::Symbol(symbol) => Ok(symbol),
841 _ => Err(RuntimeError::Invariant("a well-known symbol")),
842 }
843 }
844
845 pub(crate) fn promise_snapshot(
848 &mut self,
849 promise: &ObjectRef,
850 ) -> JsResult<Option<PromiseSnapshot>> {
851 let value = oxide_core::Value::object(self.object(promise)?);
852 let Some((state, result)) = self.core.promise_state(value) else {
853 return Ok(None);
854 };
855 let state = match state {
856 1 => PromiseState::Fulfilled,
857 2 => PromiseState::Rejected,
858 _ => PromiseState::Pending,
859 };
860 let result = if state == PromiseState::Pending {
861 Value::Undefined
862 } else {
863 self.lift(result)?
864 };
865 Ok(Some(PromiseSnapshot::new(state, result)))
866 }
867
868 pub(crate) fn new_promise(&mut self) -> JsResult<PromiseCapability> {
869 let result = self.core.new_promise_capability();
870 let (promise, resolve, reject) = self.complete_with(result)?;
871 Ok(PromiseCapability {
872 promise: self.lift_object(promise),
873 resolve: CallableRef(self.lift_object(resolve)),
874 reject: CallableRef(self.lift_object(reject)),
875 })
876 }
877
878 pub(crate) fn promise_then(
879 &mut self,
880 promise: &ObjectRef,
881 on_fulfilled: impl HostFunction<Raw>,
882 on_rejected: impl HostFunction<Raw>,
883 ) -> JsResult<ObjectRef> {
884 let fulfilled = self.new_function(FunctionOptions::new("").length(1), on_fulfilled)?;
885 let rejected = self.new_function(FunctionOptions::new("").length(1), on_rejected)?;
886 let key = PropertyKey::from_js_string(JsString::from_static("then"));
887 let then = match self.get_property(promise, &key)? {
888 Value::Object(then) => self.as_callable(&then)?,
889 _ => None,
890 };
891 let Some(then) = then else {
892 return Err(self.throw_error(NativeErrorKind::Type, "not a function"));
893 };
894 let result = self.call(
895 &then,
896 Value::Object(promise.clone()),
897 &[Value::from(fulfilled), Value::from(rejected)],
898 )?;
899 match result {
900 Value::Object(promise) => Ok(promise),
901 _ => Err(RuntimeError::Invariant("then returned a promise")),
902 }
903 }
904
905 pub(crate) fn new_array_buffer(&mut self, bytes: &[u8]) -> JsResult<ObjectRef> {
908 let result = self.core.new_array_buffer(bytes.len());
909 let id = self.complete_with(result)?;
910 let buffer = self.lift_object(id);
911 let result = self.core.array_buffer_write(id, 0, bytes);
912 self.complete_with(result)?;
913 Ok(buffer)
914 }
915
916 pub(crate) fn array_buffer_len(&mut self, buffer: &ObjectRef) -> JsResult<Option<usize>> {
917 let id = self.object(buffer)?;
918 Ok(self.core.array_buffer_len(id))
919 }
920
921 pub(crate) fn array_buffer_to_vec(&mut self, buffer: &ObjectRef) -> JsResult<Vec<u8>> {
922 let id = self.object(buffer)?;
923 let mut bytes = vec![0; self.core.array_buffer_len(id).unwrap_or(0)];
924 let result = self.core.array_buffer_read(id, 0, &mut bytes);
925 self.complete_with(result)?;
926 Ok(bytes)
927 }
928
929 pub(crate) fn with_array_buffer_bytes<R>(
930 &mut self,
931 buffer: &ObjectRef,
932 f: impl FnOnce(&[u8]) -> R,
933 ) -> JsResult<R> {
934 let id = self.object(buffer)?;
935 if let Some(bytes) = self.core.array_buffer_bytes(id) {
936 return Ok(f(bytes));
937 }
938 let bytes = self.array_buffer_to_vec(buffer)?;
941 Ok(f(&bytes))
942 }
943
944 pub(crate) fn write_array_buffer(
945 &mut self,
946 buffer: &ObjectRef,
947 offset: usize,
948 data: &[u8],
949 ) -> JsResult<()> {
950 let id = self.object(buffer)?;
951 let result = self.core.array_buffer_write(id, offset, data);
952 self.complete_with(result)
953 }
954
955 pub(crate) fn typed_array_view(
956 &mut self,
957 array: &ObjectRef,
958 ) -> JsResult<Option<TypedArrayView>> {
959 let id = self.object(array)?;
960 let Some((kind, buffer, byte_offset, length)) = self.core.typed_array_view(id) else {
961 return Ok(None);
962 };
963 Ok(Some(TypedArrayView {
964 kind,
965 buffer: self.lift_object(buffer),
966 byte_offset,
967 length,
968 }))
969 }
970
971 pub(crate) fn new_typed_array(
972 &mut self,
973 kind: TypedArrayKind,
974 buffer: &ObjectRef,
975 byte_offset: usize,
976 length: Option<usize>,
977 ) -> JsResult<ObjectRef> {
978 let constructor = CallableRef(self.intrinsic(typed_array_constructor(kind))?);
979 let mut arguments = vec![
980 Value::Object(buffer.clone()),
981 Value::number(byte_offset as f64),
982 ];
983 if let Some(length) = length {
984 arguments.push(Value::number(length as f64));
985 }
986 match self.construct(&constructor, &arguments)? {
987 Value::Object(array) => Ok(array),
988 _ => Err(RuntimeError::Invariant("a typed array")),
989 }
990 }
991
992 fn intrinsic(&mut self, intrinsic: Intrinsic) -> JsResult<ObjectRef> {
995 let object = self.core.intrinsic(intrinsic);
996 Ok(self.lift_object(object))
997 }
998
999 pub(crate) fn global_object(&mut self) -> JsResult<ObjectRef> {
1000 let object = self.core.global_object();
1001 Ok(self.lift_object(object))
1002 }
1003
1004 pub(crate) fn object_prototype(&mut self) -> JsResult<ObjectRef> {
1005 self.intrinsic(Intrinsic::ObjectPrototype)
1006 }
1007
1008 pub(crate) fn array_prototype(&mut self) -> JsResult<ObjectRef> {
1009 self.intrinsic(Intrinsic::ArrayPrototype)
1010 }
1011
1012 pub(crate) fn function_prototype(&mut self) -> JsResult<ObjectRef> {
1013 self.intrinsic(Intrinsic::FunctionPrototype)
1014 }
1015
1016 pub(crate) fn iterator_prototype(&mut self) -> JsResult<ObjectRef> {
1017 self.intrinsic(Intrinsic::IteratorPrototype)
1018 }
1019
1020 pub(crate) fn string_iterator_prototype(&mut self) -> JsResult<ObjectRef> {
1021 self.intrinsic(Intrinsic::StringIteratorPrototype)
1022 }
1023
1024 pub(crate) fn number_prototype(&mut self) -> JsResult<ObjectRef> {
1025 self.intrinsic(Intrinsic::NumberPrototype)
1026 }
1027
1028 pub(crate) fn boolean_prototype(&mut self) -> JsResult<ObjectRef> {
1029 self.intrinsic(Intrinsic::BooleanPrototype)
1030 }
1031
1032 pub(crate) fn string_prototype(&mut self) -> JsResult<ObjectRef> {
1033 self.intrinsic(Intrinsic::StringPrototype)
1034 }
1035
1036 pub(crate) fn symbol_prototype(&mut self) -> JsResult<ObjectRef> {
1037 self.intrinsic(Intrinsic::SymbolPrototype)
1038 }
1039
1040 pub(crate) fn bigint_prototype(&mut self) -> JsResult<ObjectRef> {
1041 self.intrinsic(Intrinsic::BigIntPrototype)
1042 }
1043
1044 pub(crate) fn function_constructor(&mut self) -> JsResult<CallableRef> {
1045 self.intrinsic(Intrinsic::Function).map(CallableRef)
1046 }
1047
1048 pub(crate) fn new_native_error(
1051 &mut self,
1052 kind: NativeErrorKind,
1053 message: &str,
1054 ) -> JsResult<Value> {
1055 let error = self.core.new_error(native_kind(kind), message)?;
1056 self.lift(error)
1057 }
1058
1059 pub(crate) fn throw_error(&mut self, kind: NativeErrorKind, message: &str) -> RuntimeError {
1060 match self.new_native_error(kind, message) {
1061 Ok(error) => RuntimeError::Exception(error),
1062 Err(error) => error,
1063 }
1064 }
1065
1066 pub(crate) fn install_qjs_helpers(&mut self, helpers: &QjsHelpers) -> JsResult<()> {
1069 self.core
1070 .install_qjs_helpers(helpers.script_args.as_deref())?;
1071 if helpers.std {
1072 self.core.install_std()?;
1073 }
1074 Ok(())
1075 }
1076
1077 pub(crate) fn new_function<Args>(
1080 &mut self,
1081 options: FunctionOptions,
1082 function: impl HostFunction<Args>,
1083 ) -> JsResult<CallableRef> {
1084 let data = self.lower_all(&options.data)?;
1085 let body = host_body(self.shared, function);
1086 let object = self.core.new_host_function(
1087 &options.name,
1088 options.length,
1089 options.constructor,
1090 &data,
1091 body,
1092 )?;
1093 Ok(CallableRef(self.lift_object(object)))
1094 }
1095
1096 pub(crate) fn define_function<Args>(
1097 &mut self,
1098 target: &ObjectRef,
1099 name: &str,
1100 length: u32,
1101 function: impl HostFunction<Args>,
1102 ) -> JsResult<CallableRef> {
1103 let function = self.new_function(FunctionOptions::new(name).length(length), function)?;
1104 let key = PropertyKey::from_js_string(JsString::try_from_utf8(name)?);
1105 let descriptor = OrdinaryPropertyDescriptor::data(
1106 Value::Object(function.as_object().clone()),
1107 true,
1108 false,
1109 true,
1110 );
1111 if !self.define_own_property(target, &key, &descriptor)? {
1112 let error = self.throw_error(NativeErrorKind::Type, "property is not configurable");
1113 return Err(error);
1114 }
1115 Ok(function)
1116 }
1117
1118 pub(crate) fn new_host_object<T: 'static>(
1119 &mut self,
1120 value: T,
1121 prototype: Option<&ObjectRef>,
1122 ) -> JsResult<ObjectRef> {
1123 let prototype = prototype.map(|p| self.object(p)).transpose()?;
1124 let object = self.core.new_host_object(prototype, Rc::new(value))?;
1125 Ok(self.lift_object(object))
1126 }
1127
1128 pub(crate) fn host_data<T: 'static>(&mut self, object: &ObjectRef) -> JsResult<Option<Rc<T>>> {
1129 let id = self.object(object)?;
1130 Ok(self
1131 .core
1132 .host_data(id)
1133 .and_then(|data: Rc<dyn Any>| data.downcast::<T>().ok()))
1134 }
1135}
1136
1137fn typed_array_constructor(kind: TypedArrayKind) -> Intrinsic {
1138 match kind {
1139 TypedArrayKind::Int8 => Intrinsic::Int8Array,
1140 TypedArrayKind::Uint8 => Intrinsic::Uint8Array,
1141 TypedArrayKind::Uint8Clamped => Intrinsic::Uint8ClampedArray,
1142 TypedArrayKind::Int16 => Intrinsic::Int16Array,
1143 TypedArrayKind::Uint16 => Intrinsic::Uint16Array,
1144 TypedArrayKind::Int32 => Intrinsic::Int32Array,
1145 TypedArrayKind::Uint32 => Intrinsic::Uint32Array,
1146 TypedArrayKind::Float16 => Intrinsic::Float16Array,
1147 TypedArrayKind::Float32 => Intrinsic::Float32Array,
1148 TypedArrayKind::Float64 => Intrinsic::Float64Array,
1149 TypedArrayKind::BigInt64 => Intrinsic::BigInt64Array,
1150 TypedArrayKind::BigUint64 => Intrinsic::BigUint64Array,
1151 }
1152}
1153
1154pub(crate) fn native_kind(kind: NativeErrorKind) -> oxide_core::ErrorKind {
1155 match kind {
1156 NativeErrorKind::Eval => oxide_core::ErrorKind::Eval,
1157 NativeErrorKind::Range => oxide_core::ErrorKind::Range,
1158 NativeErrorKind::Reference => oxide_core::ErrorKind::Reference,
1159 NativeErrorKind::Syntax => oxide_core::ErrorKind::Syntax,
1160 NativeErrorKind::Type => oxide_core::ErrorKind::Type,
1161 NativeErrorKind::Uri => oxide_core::ErrorKind::Uri,
1162 NativeErrorKind::Internal => oxide_core::ErrorKind::Internal,
1163 NativeErrorKind::Aggregate => oxide_core::ErrorKind::Aggregate,
1164 }
1165}
1166
1167mod sealed {
1168 pub trait Sealed {}
1169 impl Sealed for super::Context {}
1170 impl Sealed for super::Scope<'_> {}
1171}
1172
1173macro_rules! js_ops {
1179 ($(
1180 $(#[$doc:meta])*
1181 fn $name:ident $([$($generic:tt)*])? (&mut self $(, $arg:ident: $ty:ty)* $(,)?) -> $ret:ty;
1182 )*) => {
1183 impl Context {
1184 $(
1185 $(#[$doc])*
1186 pub fn $name $(<$($generic)*>)? (&self $(, $arg: $ty)*) -> $ret {
1187 let mut entry = self.runtime.enter()?;
1188 entry.view().$name($($arg),*)
1189 }
1190 )*
1191 }
1192
1193 impl Scope<'_> {
1194 $(
1195 $(#[$doc])*
1196 pub fn $name $(<$($generic)*>)? (&mut self $(, $arg: $ty)*) -> $ret {
1197 self.view().$name($($arg),*)
1198 }
1199 )*
1200 }
1201
1202 pub trait Js: sealed::Sealed {
1207 $(
1208 $(#[$doc])*
1209 fn $name $(<$($generic)*>)? (&mut self $(, $arg: $ty)*) -> $ret;
1210 )*
1211
1212 fn throw_error(&mut self, kind: NativeErrorKind, message: &str) -> RuntimeError;
1216 }
1217
1218 impl Js for Context {
1219 $(
1220 fn $name $(<$($generic)*>)? (&mut self $(, $arg: $ty)*) -> $ret {
1221 Context::$name(self $(, $arg)*)
1222 }
1223 )*
1224
1225 fn throw_error(&mut self, kind: NativeErrorKind, message: &str) -> RuntimeError {
1226 Context::throw_error(self, kind, message)
1227 }
1228 }
1229
1230 impl Js for Scope<'_> {
1231 $(
1232 fn $name $(<$($generic)*>)? (&mut self $(, $arg: $ty)*) -> $ret {
1233 Scope::$name(self $(, $arg)*)
1234 }
1235 )*
1236
1237 fn throw_error(&mut self, kind: NativeErrorKind, message: &str) -> RuntimeError {
1238 Scope::throw_error(self, kind, message)
1239 }
1240 }
1241 };
1242}
1243
1244impl Context {
1245 pub fn throw_error(&self, kind: NativeErrorKind, message: &str) -> RuntimeError {
1247 match self.runtime.enter() {
1248 Ok(mut entry) => entry.view().throw_error(kind, message),
1249 Err(error) => error,
1250 }
1251 }
1252}
1253
1254impl Scope<'_> {
1255 pub fn throw_error(&mut self, kind: NativeErrorKind, message: &str) -> RuntimeError {
1257 self.view().throw_error(kind, message)
1258 }
1259}
1260
1261js_ops! {
1262 fn eval(&mut self, source: &str) -> JsResult<Value>;
1266 fn eval_bytes(&mut self, source: &[u8]) -> JsResult<Value>;
1267 fn eval_with_filename(&mut self, source: &str, filename: &str) -> JsResult<Value>;
1268 fn eval_with_options(&mut self, source: &str, options: &EvalOptions) -> JsResult<Value>;
1269 fn eval_bytes_with_options(&mut self, source: &[u8], options: &EvalOptions) -> JsResult<Value>;
1270 fn eval_bytes_with_filename(&mut self, source: &[u8], filename: &str) -> JsResult<Value>;
1274 fn compile(&mut self, source: &str) -> JsResult<FunctionBytecodeRef>;
1275 fn compile_bytes(&mut self, source: &[u8]) -> JsResult<FunctionBytecodeRef>;
1276 fn compile_with_filename(&mut self, source: &str, filename: &str) -> JsResult<FunctionBytecodeRef>;
1277 fn compile_with_options(&mut self, source: &str, options: &CompileOptions) -> JsResult<FunctionBytecodeRef>;
1278 fn compile_bytes_with_options(&mut self, source: &[u8], options: &CompileOptions) -> JsResult<FunctionBytecodeRef>;
1279 fn compile_bytes_with_filename(&mut self, source: &[u8], filename: &str) -> JsResult<FunctionBytecodeRef>;
1283 fn execute(&mut self, script: &FunctionBytecodeRef) -> JsResult<Value>;
1285
1286 fn compile_module(&mut self, source: &str) -> JsResult<ModuleBytecodeRef>;
1289 fn compile_module_bytes(&mut self, source: &[u8]) -> JsResult<ModuleBytecodeRef>;
1290 fn compile_module_with_filename(&mut self, source: &str, filename: &str) -> JsResult<ModuleBytecodeRef>;
1291 fn compile_module_bytes_with_options(&mut self, source: &[u8], options: &CompileOptions) -> JsResult<ModuleBytecodeRef>;
1292 fn compile_module_bytes_with_filename(&mut self, source: &[u8], filename: &str) -> JsResult<ModuleBytecodeRef>;
1293 fn compile_module_bytes_with_import_meta(&mut self, source: &[u8], filename: &str, import_meta: Vec<(String, Value)>) -> JsResult<ModuleBytecodeRef>;
1297 fn execute_module(&mut self, module: &ModuleBytecodeRef) -> JsResult<Value>;
1300
1301 fn call(&mut self, callable: &CallableRef, this_value: Value, arguments: &[Value]) -> JsResult<Value>;
1304 fn construct(&mut self, constructor: &CallableRef, arguments: &[Value]) -> JsResult<Value>;
1305 fn construct_with_new_target(&mut self, constructor: &CallableRef, new_target: &CallableRef, arguments: &[Value]) -> JsResult<Value>;
1306
1307 fn new_object(&mut self) -> JsResult<ObjectRef>;
1310 fn new_object_with_prototype(&mut self, prototype: Option<&ObjectRef>) -> JsResult<ObjectRef>;
1311 fn new_array(&mut self) -> JsResult<ObjectRef>;
1312 fn new_array_from_values(&mut self, values: Vec<Value>) -> JsResult<ObjectRef>;
1313 fn get_own_property(&mut self, object: &ObjectRef, key: &PropertyKey) -> JsResult<Option<CompleteOrdinaryPropertyDescriptor>>;
1314 fn define_own_property(&mut self, object: &ObjectRef, key: &PropertyKey, descriptor: &OrdinaryPropertyDescriptor) -> JsResult<bool>;
1315 fn get_property(&mut self, object: &ObjectRef, key: &PropertyKey) -> JsResult<Value>;
1316 fn get_property_with_receiver(&mut self, object: &ObjectRef, key: &PropertyKey, receiver: Value) -> JsResult<Value>;
1317 fn set_property(&mut self, object: &ObjectRef, key: &PropertyKey, value: Value) -> JsResult<bool>;
1318 fn set_property_with_receiver(&mut self, object: &ObjectRef, key: &PropertyKey, value: Value, receiver: Value) -> JsResult<bool>;
1319 fn delete_property(&mut self, object: &ObjectRef, key: &PropertyKey) -> JsResult<bool>;
1320 fn has_property(&mut self, object: &ObjectRef, key: &PropertyKey) -> JsResult<bool>;
1321 fn has_own_property(&mut self, object: &ObjectRef, key: &PropertyKey) -> JsResult<bool>;
1322 fn own_property_keys(&mut self, object: &ObjectRef) -> JsResult<Vec<PropertyKey>>;
1323 fn get_prototype_of(&mut self, object: &ObjectRef) -> JsResult<Option<ObjectRef>>;
1324 fn set_prototype_of(&mut self, object: &ObjectRef, prototype: Option<&ObjectRef>) -> JsResult<bool>;
1325 fn as_callable(&mut self, object: &ObjectRef) -> JsResult<Option<CallableRef>>;
1327 fn is_constructor(&mut self, object: &ObjectRef) -> JsResult<bool>;
1328 fn is_array_object(&mut self, object: &ObjectRef) -> JsResult<bool>;
1330 fn is_error_object(&mut self, object: &ObjectRef) -> JsResult<bool>;
1331
1332 fn to_js_string(&mut self, value: &Value) -> JsResult<JsString>;
1336 fn to_number(&mut self, value: &Value) -> JsResult<f64>;
1338 fn detach_array_buffer(&mut self, value: &Value) -> JsResult<()>;
1341 fn type_of(&mut self, value: &Value) -> JsResult<String>;
1343 fn print_value(&mut self, value: &Value) -> JsResult<String>;
1346 fn qjs_print_value_bytes(&mut self, value: &Value) -> JsResult<Vec<u8>>;
1350
1351 fn new_symbol(&mut self, description: Option<JsString>) -> JsResult<SymbolRef>;
1354 fn symbol_description(&mut self, symbol: &SymbolRef) -> JsResult<Option<JsString>>;
1355 fn well_known_symbol(&mut self, symbol: WellKnownSymbol) -> JsResult<SymbolRef>;
1356
1357 fn promise_snapshot(&mut self, promise: &ObjectRef) -> JsResult<Option<PromiseSnapshot>>;
1361 fn new_promise(&mut self) -> JsResult<PromiseCapability>;
1364 fn promise_then(&mut self, promise: &ObjectRef, on_fulfilled: impl HostFunction<Raw>, on_rejected: impl HostFunction<Raw>) -> JsResult<ObjectRef>;
1367
1368 fn new_array_buffer(&mut self, bytes: &[u8]) -> JsResult<ObjectRef>;
1372 fn array_buffer_len(&mut self, buffer: &ObjectRef) -> JsResult<Option<usize>>;
1375 fn array_buffer_to_vec(&mut self, buffer: &ObjectRef) -> JsResult<Vec<u8>>;
1378 fn with_array_buffer_bytes[R](&mut self, buffer: &ObjectRef, f: impl FnOnce(&[u8]) -> R) -> JsResult<R>;
1382 fn write_array_buffer(&mut self, buffer: &ObjectRef, offset: usize, data: &[u8]) -> JsResult<()>;
1385 fn typed_array_view(&mut self, array: &ObjectRef) -> JsResult<Option<TypedArrayView>>;
1388 fn new_typed_array(&mut self, kind: TypedArrayKind, buffer: &ObjectRef, byte_offset: usize, length: Option<usize>) -> JsResult<ObjectRef>;
1391
1392 fn global_object(&mut self) -> JsResult<ObjectRef>;
1395 fn object_prototype(&mut self) -> JsResult<ObjectRef>;
1396 fn array_prototype(&mut self) -> JsResult<ObjectRef>;
1397 fn function_prototype(&mut self) -> JsResult<ObjectRef>;
1398 fn iterator_prototype(&mut self) -> JsResult<ObjectRef>;
1399 fn string_iterator_prototype(&mut self) -> JsResult<ObjectRef>;
1400 fn number_prototype(&mut self) -> JsResult<ObjectRef>;
1401 fn boolean_prototype(&mut self) -> JsResult<ObjectRef>;
1402 fn string_prototype(&mut self) -> JsResult<ObjectRef>;
1403 fn symbol_prototype(&mut self) -> JsResult<ObjectRef>;
1404 fn bigint_prototype(&mut self) -> JsResult<ObjectRef>;
1405 fn function_constructor(&mut self) -> JsResult<CallableRef>;
1406
1407 fn new_native_error(&mut self, kind: NativeErrorKind, message: &str) -> JsResult<Value>;
1411
1412 fn install_qjs_helpers(&mut self, helpers: &QjsHelpers) -> JsResult<()>;
1417
1418 fn new_function[Args](&mut self, options: FunctionOptions, function: impl HostFunction<Args>) -> JsResult<CallableRef>;
1423 fn define_function[Args](&mut self, target: &ObjectRef, name: &str, length: u32, function: impl HostFunction<Args>) -> JsResult<CallableRef>;
1427 fn new_host_object[T: 'static](&mut self, value: T, prototype: Option<&ObjectRef>) -> JsResult<ObjectRef>;
1430 fn host_data[T: 'static](&mut self, object: &ObjectRef) -> JsResult<Option<Rc<T>>>;
1433}