mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-21 21:50:20 -05:00
Add 'Value::same_value_zero()' (#414)
This commit is contained in:
parent
1b84bc74f6
commit
d3f6e4d36c
3 changed files with 94 additions and 3 deletions
|
@ -1,6 +1,9 @@
|
|||
use crate::isolate::Isolate;
|
||||
use std::alloc::Layout;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::HandleScope;
|
||||
use crate::Integer;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::Number;
|
||||
|
||||
|
@ -57,4 +60,21 @@ impl Integer {
|
|||
pub fn value(&self) -> i64 {
|
||||
unsafe { v8__Integer__Value(self) }
|
||||
}
|
||||
|
||||
/// Internal helper function to produce a handle containing a SMI zero value,
|
||||
/// without the need for the caller to provide (or have entered) a
|
||||
/// `HandleScope`.
|
||||
pub(crate) fn zero<'s>() -> Local<'s, Integer> {
|
||||
// The SMI representation of zero is also zero. In debug builds, double
|
||||
// check this, so in the unlikely event that V8 changes its internal
|
||||
// representation of SMIs such that this invariant no longer holds, we'd
|
||||
// catch it.
|
||||
static ZERO_SMI: usize = 0;
|
||||
let zero_raw = &ZERO_SMI as *const _ as *mut Self;
|
||||
let zero_nn = unsafe { NonNull::new_unchecked(zero_raw) };
|
||||
let zero_local = unsafe { Local::from_non_null(zero_nn) };
|
||||
debug_assert_eq!(Layout::new::<usize>(), Layout::new::<Local<Self>>());
|
||||
debug_assert_eq!(zero_local.value(), 0);
|
||||
zero_local
|
||||
}
|
||||
}
|
||||
|
|
25
src/value.rs
25
src/value.rs
|
@ -419,14 +419,35 @@ impl Value {
|
|||
unsafe { v8__Value__IsModuleNamespaceObject(self) }
|
||||
}
|
||||
|
||||
pub fn strict_equals<'s>(&self, that: Local<'s, Value>) -> bool {
|
||||
pub fn strict_equals(&self, that: Local<Value>) -> bool {
|
||||
unsafe { v8__Value__StrictEquals(self, &*that) }
|
||||
}
|
||||
|
||||
pub fn same_value<'s>(&self, that: Local<'s, Value>) -> bool {
|
||||
pub fn same_value(&self, that: Local<Value>) -> bool {
|
||||
unsafe { v8__Value__SameValue(self, &*that) }
|
||||
}
|
||||
|
||||
/// Implements the the abstract operation `SameValueZero`, which is defined in
|
||||
/// ECMA-262 6th edition § 7.2.10
|
||||
/// (http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero).
|
||||
///
|
||||
/// This operation is used to compare values for the purpose of insertion into
|
||||
/// a `Set`, or determining whether `Map` keys are equivalent. Its semantics
|
||||
/// are almost the same as `strict_equals()` and `same_value()`, with the
|
||||
/// following important distinctions:
|
||||
/// - It considers `NaN` equal to `NaN` (unlike `strict_equals()`).
|
||||
/// - It considers `-0` equal to `0` (unlike `same_value()`).
|
||||
pub fn same_value_zero(&self, that: Local<Value>) -> bool {
|
||||
// The SMI representation of zero is also zero. In debug builds, double
|
||||
// check this, so in the unlikely event that V8 changes its internal
|
||||
// representation of SMIs such that this invariant no longer holds, we'd
|
||||
// catch it.
|
||||
self.same_value(that) || {
|
||||
let zero = Integer::zero().into();
|
||||
self.strict_equals(zero) && that.strict_equals(zero)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_big_int<'s>(
|
||||
&self,
|
||||
scope: &mut HandleScope<'s>,
|
||||
|
|
|
@ -1763,6 +1763,56 @@ fn equality() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::eq_op)]
|
||||
fn equality_edge_cases() {
|
||||
let _setup_guard = setup();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
let pos_zero = eval(scope, "0").unwrap();
|
||||
let neg_zero = eval(scope, "-0").unwrap();
|
||||
let nan = eval(scope, "NaN").unwrap();
|
||||
|
||||
assert!(pos_zero == pos_zero);
|
||||
assert!(pos_zero.same_value(pos_zero));
|
||||
assert!(pos_zero.same_value_zero(pos_zero));
|
||||
assert!(pos_zero.strict_equals(pos_zero));
|
||||
|
||||
assert!(neg_zero == neg_zero);
|
||||
assert!(neg_zero.same_value(neg_zero));
|
||||
assert!(neg_zero.same_value_zero(neg_zero));
|
||||
assert!(neg_zero.strict_equals(neg_zero));
|
||||
|
||||
assert!(pos_zero == neg_zero);
|
||||
assert!(!pos_zero.same_value(neg_zero));
|
||||
assert!(pos_zero.same_value_zero(neg_zero));
|
||||
assert!(pos_zero.strict_equals(neg_zero));
|
||||
|
||||
assert!(neg_zero == pos_zero);
|
||||
assert!(!neg_zero.same_value(pos_zero));
|
||||
assert!(neg_zero.same_value_zero(pos_zero));
|
||||
assert!(pos_zero.strict_equals(pos_zero));
|
||||
|
||||
assert!(nan != nan);
|
||||
assert!(nan.same_value(nan));
|
||||
assert!(nan.same_value_zero(nan));
|
||||
assert!(!nan.strict_equals(nan));
|
||||
|
||||
assert!(nan != pos_zero);
|
||||
assert!(!nan.same_value(pos_zero));
|
||||
assert!(!nan.same_value_zero(pos_zero));
|
||||
assert!(!nan.strict_equals(pos_zero));
|
||||
|
||||
assert!(neg_zero != nan);
|
||||
assert!(!neg_zero.same_value(nan));
|
||||
assert!(!neg_zero.same_value_zero(nan));
|
||||
assert!(!neg_zero.strict_equals(nan));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_buffer_view() {
|
||||
let _setup_guard = setup();
|
||||
|
|
Loading…
Add table
Reference in a new issue