Rust编写的JavaScript引擎,该项目是一个试验性质的项目。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

116 lines
3.5 KiB

use crate::{
vm::{opcode::Operation, CompletionType},
Context, JsNativeError, JsResult,
};
/// `Return` implements the Opcode Operation for `Opcode::Return`
///
/// Operation:
/// - Return from a function.
#[derive(Debug, Clone, Copy)]
pub(crate) struct Return;
impl Operation for Return {
const NAME: &'static str = "Return";
const INSTRUCTION: &'static str = "INST - Return";
const COST: u8 = 4;
fn execute(_context: &mut Context) -> JsResult<CompletionType> {
Ok(CompletionType::Return)
}
}
/// `CheckReturn` implements the Opcode Operation for `Opcode::CheckReturn`
///
/// Operation:
/// - Check return from a function.
#[derive(Debug, Clone, Copy)]
pub(crate) struct CheckReturn;
impl Operation for CheckReturn {
const NAME: &'static str = "CheckReturn";
const INSTRUCTION: &'static str = "INST - CheckReturn";
const COST: u8 = 3;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
if !context.vm.frame().construct() {
return Ok(CompletionType::Normal);
}
let frame = context.vm.frame();
let this = frame.this(&context.vm);
let result = context.vm.take_return_value();
let result = if result.is_object() {
result
} else if !this.is_undefined() {
this
} else if !result.is_undefined() {
let realm = context.vm.frame().realm.clone();
context.vm.pending_exception = Some(
JsNativeError::typ()
.with_message("derived constructor can only return an Object or undefined")
.with_realm(realm)
.into(),
);
return Ok(CompletionType::Throw);
} else {
let frame = context.vm.frame();
if frame.has_this_value_cached() {
this
} else {
let realm = frame.realm.clone();
let this = context.vm.environments.get_this_binding();
match this {
Err(err) => {
let err = err.inject_realm(realm);
context.vm.pending_exception = Some(err);
return Ok(CompletionType::Throw);
}
Ok(this) => this,
}
}
};
context.vm.set_return_value(result);
Ok(CompletionType::Normal)
}
}
/// `GetReturnValue` implements the Opcode Operation for `Opcode::GetReturnValue`
///
/// Operation:
/// - Gets the return value of a function.
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetReturnValue;
impl Operation for GetReturnValue {
const NAME: &'static str = "GetReturnValue";
const INSTRUCTION: &'static str = "INST - GetReturnValue";
const COST: u8 = 2;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let value = context.vm.get_return_value();
context.vm.push(value);
Ok(CompletionType::Normal)
}
}
/// `SetReturnValue` implements the Opcode Operation for `Opcode::SetReturnValue`
///
/// Operation:
/// - Sets the return value of a function.
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetReturnValue;
impl Operation for SetReturnValue {
const NAME: &'static str = "SetReturnValue";
const INSTRUCTION: &'static str = "INST - SetReturnValue";
const COST: u8 = 2;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let value = context.vm.pop();
context.vm.set_return_value(value);
Ok(CompletionType::Normal)
}
}