vitest-pool-assemblyscript 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { stringifyValue } from './utils';
1
+ import { isNull, stringifyValue } from './utils';
2
2
 
3
3
  /**
4
4
  * Byte offset from an object pointer to the rtId field in the AS managed object header.
@@ -325,19 +325,15 @@ function arrayBufferEquals<T, U>(actual: T, expected: U): __vitest_assemblyscrip
325
325
  * (or same reference type) for provided values.
326
326
  */
327
327
  export function identical<T, U>(actual: T, expected: U): bool {
328
+ const actualIsNull = isNull(actual);
329
+ const expectedIsNull = isNull(expected);
330
+
328
331
  // both refs
329
332
  if (isReference<T>() && isReference<U>()) {
330
- const actualIsNullable = isNullable<T>();
331
- // Use changetype pointer check instead of `== null` to avoid invoking
332
- // user-defined @operator("==") overloads, which reject null arguments
333
- const actualIsNull = actualIsNullable && changetype<usize>(actual) == 0;
334
- const expectedIsNullable = isNullable<U>();
335
- const expectedIsNull = expectedIsNullable && changetype<usize>(expected) == 0;
336
-
337
333
  // null refs
338
334
  if (actualIsNull && expectedIsNull) {
339
335
  return true;
340
- } else if ( (actualIsNull && !expectedIsNull) || (!actualIsNull && expectedIsNull) ) {
336
+ } else if ( actualIsNull != expectedIsNull ) {
341
337
  return false;
342
338
  }
343
339
 
@@ -348,27 +344,26 @@ export function identical<T, U>(actual: T, expected: U): bool {
348
344
  // object refs
349
345
  return changetype<usize>(actual) == changetype<usize>(expected);
350
346
  }
351
- } else if (isReference<T>() && !isReference<U>()) {
352
- // Both null/zero: null reference matches bare null (usize(0))
353
- if (changetype<usize>(actual) == 0 && expected == usize(0)) {
347
+ } else if (
348
+ (isReference<T>() && !isReference<U>())
349
+ || (!isReference<T>() && isReference<U>())
350
+ ) {
351
+ if (actualIsNull && expectedIsNull) {
354
352
  return true;
353
+ } else if ( actualIsNull != expectedIsNull ) {
354
+ return false;
355
355
  }
356
+
356
357
  // Non-null reference vs value type: fundamentally incomparable
357
358
  throw new Error(
358
359
  "Cannot compare " + nameof<T>() + " with " + nameof<U>()
359
360
  + equalsPathAtSuffix() + ": reference and value types are not comparable."
360
361
  );
361
- } else if (!isReference<T>() && isReference<U>()) {
362
- // Both null/zero: bare null (usize(0)) matches null reference
363
- if (actual == usize(0) && changetype<usize>(expected) == 0) {
364
- return true;
365
- }
366
- // Value type vs non-null reference: fundamentally incomparable
367
- throw new Error(
368
- "Cannot compare " + nameof<T>() + " with " + nameof<U>()
369
- + equalsPathAtSuffix() + ": reference and value types are not comparable."
370
- );
371
362
  } else { // both primitives
363
+ if ( actualIsNull != expectedIsNull ) {
364
+ return false;
365
+ }
366
+
372
367
  if ( (isBoolean<T>() && !isBoolean<U>()) || (!isBoolean<T>() && isBoolean<U>())
373
368
  ) {
374
369
  // when one is boolean and the other is not, they are not identical
@@ -484,27 +479,39 @@ export function equals<T, U>(actual: T, expected: U): __vitest_assemblyscript_Eq
484
479
  exactMatch = identical(actual, expected);
485
480
  }
486
481
 
487
- if (!isReference<T>() || isString<T>() || isVector<T>()) {
488
- // non-bool primitives or strings: return result of comparing
482
+ const actualIsNull = isNull(actual);
483
+ const expectedIsNull = isNull(expected);
484
+
485
+ if (
486
+ (!isReference<T>() && !isReference<U>())
487
+ || (isString<T>() && isString<U>())
488
+ || (isVector<T>() && isVector<U>())
489
+ ) {
490
+ // non-bool primitives or strings or vectors: return result of identity compare
489
491
  return exactMatch ? __vitest_assemblyscript_EqualityResult.Equal : __vitest_assemblyscript_EqualityResult.NotEqual;
490
492
  } else if (exactMatch) {
491
493
  // primitive / reference comparison passed already
492
494
  return __vitest_assemblyscript_EqualityResult.Equal;
493
- }
494
-
495
- if (isNullable<T>()) {
496
- // Use changetype pointer checks instead of `== null` / `!= null` to avoid
497
- // invoking user-defined @operator("==") overloads, which reject null arguments
498
- const actualIsNull = changetype<usize>(actual) == 0;
499
- const expectedIsNull = changetype<usize>(expected) == 0;
500
-
501
- if (actualIsNull && expectedIsNull) {
502
- return __vitest_assemblyscript_EqualityResult.Equal;
495
+ } else if (
496
+ (isReference<T>() && !isReference<U>())
497
+ || (!isReference<T>() && isReference<U>())
498
+ ) {
499
+ if (actualIsNull || expectedIsNull) {
500
+ return exactMatch ? __vitest_assemblyscript_EqualityResult.Equal : __vitest_assemblyscript_EqualityResult.NotEqual;
503
501
  }
504
502
 
505
- if (actualIsNull != expectedIsNull) {
506
- return __vitest_assemblyscript_EqualityResult.NotEqual;
507
- }
503
+ // Non-null reference vs value type: fundamentally incomparable
504
+ throw new Error(
505
+ "Cannot compare " + nameof<T>() + " with " + nameof<U>()
506
+ + equalsPathAtSuffix() + ": reference and value types are not comparable."
507
+ );
508
+ }
509
+
510
+ if (actualIsNull && expectedIsNull) {
511
+ return __vitest_assemblyscript_EqualityResult.Equal;
512
+ }
513
+ if (actualIsNull != expectedIsNull) {
514
+ return __vitest_assemblyscript_EqualityResult.NotEqual;
508
515
  }
509
516
 
510
517
  // Cycle detection: if this reference pair is already being compared further up
@@ -784,4 +791,3 @@ export function compareInequality<T, U>(actual: T, compareTo: U, expectedOperati
784
791
  export function truthyOrFalsey<T>(actual: T, expected: bool): bool {
785
792
  return actual ? expected == true : expected == false;
786
793
  }
787
-
@@ -77,10 +77,15 @@ abstract class BaseExpectMatcher<T> {
77
77
  * involving a float and allows all numeric types because it can still produce accurate
78
78
  * results in precision-loss casting edge cases.
79
79
  *
80
+ * Null comparison: a null reference, the bare `null` literal, and `usize(0)` are all treated
81
+ * as null and compare as identical to one another. Zero-valued primitives (`0`, `false`, `0.0`) are
82
+ * **not** identical to null. Because the bare `null` literal is `usize(0)` in AssemblyScript,
83
+ * `usize(0)` will not compare as identical to a `0` of another numeric type.
84
+ *
80
85
  * @throws When comparing float/integer types where the float's mantissa cannot losslessly
81
86
  * represent the integer type's range (e.g. `f32` vs `i32`, `f64` vs `i64`).
82
87
  * @throws When comparing fundamentally incompatible types: reference vs value type
83
- * (e.g. `string` vs `i32`, unless one is null/zero), or `v128` vs non-vector type.
88
+ * (e.g. `string` vs `i32`, unless one side is null, or `v128` vs non-vector type).
84
89
  *
85
90
  * @example
86
91
  * expect(1 + 1).toBe(2);
@@ -278,12 +283,17 @@ abstract class BaseExpectMatcher<T> {
278
283
  * are not included, as deep equality injection is scoped to user source files only
279
284
  *
280
285
  * SIMD vectors use WASM's native `==` comparison, which compares at the bit level,
281
- * ignoring lane type.
286
+ * ignoring lane type.
287
+ *
288
+ * Null comparison: a null reference, the bare `null` literal, and `usize(0)` are all treated
289
+ * as null and compare equal to one another. Zero-valued primitives (`0`, `false`, `0.0`) are
290
+ * **not** equal to null. Because the bare `null` literal is `usize(0)` in AssemblyScript,
291
+ * `usize(0)` will not compare as identical to a `0` of another numeric type.
282
292
  *
283
293
  * @throws When comparing float/integer types where the float's mantissa cannot losslessly
284
294
  * represent the integer type's range (e.g. `f32` vs `i32`, `f64` vs `i64`).
285
295
  * @throws When comparing fundamentally incompatible types: reference vs value type
286
- * (e.g. `string` vs `i32`, unless one is null/zero), or `v128` vs non-vector type.
296
+ * (e.g. `string` vs `i32`, unless one side is null, or `v128` vs non-vector type).
287
297
  * @throws When comparing containers with incompatible element types (e.g. `Array<string>`
288
298
  * vs `Array<i32>`), or precision-loss numeric combinations (e.g. `Array<f32>` vs `Array<i32>`).
289
299
  *
package/assembly/utils.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export function isNull<T>(value: T): bool {
2
2
  if (isReference<T>()) {
3
3
  if (isNullable<T>()) {
4
- return value == null;
4
+ // Use changetype pointer checks instead of `== null` / `!= null` to avoid
5
+ // invoking user-defined @operator("==") overloads, which reject null arguments
6
+ return changetype<usize>(value) == 0;
5
7
  } else {
6
8
  return false;
7
9
  }
@@ -11,6 +13,7 @@ export function isNull<T>(value: T): bool {
11
13
  } else if (isVector<T>()) {
12
14
  return false;
13
15
  } else {
16
+ // handles bare nulls
14
17
  return nameof<T>(value) == 'usize' && value == 0;
15
18
  }
16
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-pool-assemblyscript",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "AssemblyScript testing with Vitest - Simple, fast, familiar, AS-native, with full coverage output",
5
5
  "author": "Matt Ritter <matthew.d.ritter@gmail.com>",
6
6
  "license": "MIT",