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.
 
 

112 lines
3.5 KiB

use crate::{
builtins::Array,
string::common::StaticJsStrings,
vm::{opcode::Operation, CompletionType},
Context, JsResult, JsValue,
};
/// `PushNewArray` implements the Opcode Operation for `Opcode::PushNewArray`
///
/// Operation:
/// - Push an empty array value on the stack.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushNewArray;
impl Operation for PushNewArray {
const NAME: &'static str = "PushNewArray";
const INSTRUCTION: &'static str = "INST - PushNewArray";
const COST: u8 = 3;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let array = context
.intrinsics()
.templates()
.array()
.create(Array, vec![JsValue::new(0)]);
context.vm.push(array);
Ok(CompletionType::Normal)
}
}
/// `PushValueToArray` implements the Opcode Operation for `Opcode::PushValueToArray`
///
/// Operation:
/// - Push a value to an array.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushValueToArray;
impl Operation for PushValueToArray {
const NAME: &'static str = "PushValueToArray";
const INSTRUCTION: &'static str = "INST - PushValueToArray";
const COST: u8 = 3;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let value = context.vm.pop();
let array = context.vm.pop();
let o = array.as_object().expect("should be an object");
let len = o
.length_of_array_like(context)
.expect("should have 'length' property");
o.create_data_property_or_throw(len, value, context)
.expect("should be able to create new data property");
context.vm.push(array);
Ok(CompletionType::Normal)
}
}
/// `PushEllisionToArray` implements the Opcode Operation for `Opcode::PushEllisionToArray`
///
/// Operation:
/// - Push an empty element/hole to an array.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushElisionToArray;
impl Operation for PushElisionToArray {
const NAME: &'static str = "PushElisionToArray";
const INSTRUCTION: &'static str = "INST - PushElisionToArray";
const COST: u8 = 3;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let array = context.vm.pop();
let o = array.as_object().expect("should always be an object");
let len = o
.length_of_array_like(context)
.expect("arrays should always have a 'length' property");
o.set(StaticJsStrings::LENGTH, len + 1, true, context)?;
context.vm.push(array);
Ok(CompletionType::Normal)
}
}
/// `PushIteratorToArray` implements the Opcode Operation for `Opcode::PushIteratorToArray`
///
/// Operation:
/// - Push all iterator values to an array.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushIteratorToArray;
impl Operation for PushIteratorToArray {
const NAME: &'static str = "PushIteratorToArray";
const INSTRUCTION: &'static str = "INST - PushIteratorToArray";
const COST: u8 = 8;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let mut iterator = context
.vm
.frame_mut()
.iterators
.pop()
.expect("iterator stack should have at least an iterator");
let array = context.vm.pop();
while !iterator.step(context)? {
let next = iterator.value(context)?;
Array::push(&array, &[next], context)?;
}
context.vm.push(array);
Ok(CompletionType::Normal)
}
}