| 161 | } |
| 162 | |
| 163 | fn evaluate( |
| 164 | &mut self, |
| 165 | function_name: &str, |
| 166 | arguments: &[DiffValue], |
| 167 | result_tys: &[DiffValueType], |
| 168 | ) -> Result<Option<Vec<DiffValue>>> { |
| 169 | let mut isolate = self.isolate.borrow_mut(); |
| 170 | let isolate = &mut **isolate; |
| 171 | let mut scope = v8::HandleScope::new(isolate); |
| 172 | let context = v8::Local::new(&mut scope, &self.context); |
| 173 | let global = context.global(&mut scope); |
| 174 | let mut scope = v8::ContextScope::new(&mut scope, context); |
| 175 | |
| 176 | // See https://webassembly.github.io/spec/js-api/index.html#tojsvalue |
| 177 | // for how the Wasm-to-JS conversions are done. |
| 178 | let mut params = Vec::new(); |
| 179 | for arg in arguments { |
| 180 | params.push(match *arg { |
| 181 | DiffValue::I32(n) => v8::Number::new(&mut scope, n.into()).into(), |
| 182 | DiffValue::F32(n) => v8::Number::new(&mut scope, f32::from_bits(n).into()).into(), |
| 183 | DiffValue::F64(n) => v8::Number::new(&mut scope, f64::from_bits(n)).into(), |
| 184 | DiffValue::I64(n) => v8::BigInt::new_from_i64(&mut scope, n).into(), |
| 185 | DiffValue::FuncRef { null } | DiffValue::ExternRef { null } => { |
| 186 | assert!(null); |
| 187 | v8::null(&mut scope).into() |
| 188 | } |
| 189 | // JS doesn't support v128 parameters |
| 190 | DiffValue::V128(_) => return Ok(None), |
| 191 | DiffValue::AnyRef { .. } => unimplemented!(), |
| 192 | DiffValue::ExnRef { .. } => unimplemented!(), |
| 193 | DiffValue::ContRef { .. } => unimplemented!(), |
| 194 | }); |
| 195 | } |
| 196 | // JS doesn't support v128 return values |
| 197 | for ty in result_tys { |
| 198 | if let DiffValueType::V128 = ty { |
| 199 | return Ok(None); |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | let name = v8::String::new(&mut scope, "WASM_INSTANCE").unwrap(); |
| 204 | let instance = v8::Local::new(&mut scope, &self.instance); |
| 205 | global.set(&mut scope, name.into(), instance); |
| 206 | let name = v8::String::new(&mut scope, "EXPORT_NAME").unwrap(); |
| 207 | let func_name = v8::String::new(&mut scope, function_name).unwrap(); |
| 208 | global.set(&mut scope, name.into(), func_name.into()); |
| 209 | let name = v8::String::new(&mut scope, "ARGS").unwrap(); |
| 210 | let params = v8::Array::new_with_elements(&mut scope, ¶ms); |
| 211 | global.set(&mut scope, name.into(), params.into()); |
| 212 | let v8_vals = eval(&mut scope, "WASM_INSTANCE.exports[EXPORT_NAME](...ARGS)")?; |
| 213 | |
| 214 | let mut results = Vec::new(); |
| 215 | match result_tys.len() { |
| 216 | 0 => assert!(v8_vals.is_undefined()), |
| 217 | 1 => results.push(get_diff_value(&v8_vals, result_tys[0], &mut scope)), |
| 218 | _ => { |
| 219 | let array = v8::Local::<'_, v8::Array>::try_from(v8_vals).unwrap(); |
| 220 | for (i, ty) in result_tys.iter().enumerate() { |