Repository: denoland/deno_core
Pull request #396 (2023-12-24 17:47:51)

feat(core): add type functions
related: https://github.com/denoland/deno/pull/21669

mmastrac: These seem reasonable. Can you add unit tests to a new `testing/unit/type_test.ts`, please?

Patch:
diff --git a/core/01_core.js b/core/01_core.js
index 3f7b3ed..a8e1b7a 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -788,6 +788,37 @@
 
   const hostObjectBrand = SymbolFor("Deno.core.hostObject");
 
+  const {
+    op_is_any_array_buffer,
+    op_is_arguments_object,
+    op_is_array_buffer,
+    op_is_array_buffer_view,
+    op_is_async_function,
+    op_is_big_int_object,
+    op_is_boolean_object,
+    op_is_boxed_primitive,
+    op_is_data_view,
+    op_is_date,
+    op_is_generator_function,
+    op_is_generator_object,
+    op_is_map,
+    op_is_map_iterator,
+    op_is_module_namespace_object,
+    op_is_native_error,
+    op_is_number_object,
+    op_is_promise,
+    op_is_proxy,
+    op_is_reg_exp,
+    op_is_set,
+    op_is_set_iterator,
+    op_is_shared_array_buffer,
+    op_is_string_object,
+    op_is_symbol_object,
+    op_is_typed_array,
+    op_is_weak_map,
+    op_is_weak_set,
+  } = ensureFastOps();
+
   // Extra Deno.core.* exports
   const core = ObjectAssign(globalThis.Deno.core, {
     asyncStub,
@@ -843,7 +874,34 @@
     deserialize: (buffer, options) => ops.op_deserialize(buffer, options),
     getPromiseDetails: (promise) => ops.op_get_promise_details(promise),
     getProxyDetails: (proxy) => ops.op_get_proxy_details(proxy),
-    isProxy: (value) => ops.op_is_proxy(value),
+    isAnyArrayBuffer: (value) => op_is_any_array_buffer(value),
+    isArgumentsObject: (value) => op_is_arguments_object(value),
+    isArrayBuffer: (value) => op_is_array_buffer(value),
+    isArrayBufferView: (value) => op_is_array_buffer_view(value),
+    isAsyncFunction: (value) => op_is_async_function(value),
+    isBigIntObject: (value) => op_is_big_int_object(value),
+    isBooleanObject: (value) => op_is_boolean_object(value),
+    isBoxedPrimitive: (value) => op_is_boxed_primitive(value),
+    isDataView: (value) => op_is_data_view(value),
+    isDate: (value) => op_is_date(value),
+    isGeneratorFunction: (value) => op_is_generator_function(value),
+    isGeneratorObject: (value) => op_is_generator_object(value),
+    isMap: (value) => op_is_map(value),
+    isMapIterator: (value) => op_is_map_iterator(value),
+    isModuleNamespaceObject: (value) => op_is_module_namespace_object(value),
+    isNativeError: (value) => op_is_native_error(value),
+    isNumberObject: (value) => op_is_number_object(value),
+    isPromise: (value) => op_is_promise(value),
+    isProxy: (value) => op_is_proxy(value),
+    isRegExp: (value) => op_is_reg_exp(value),
+    isSet: (value) => op_is_set(value),
+    isSetIterator: (value) => op_is_set_iterator(value),
+    isSharedArrayBuffer: (value) => op_is_shared_array_buffer(value),
+    isStringObject: (value) => op_is_string_object(value),
+    isSymbolObject: (value) => op_is_symbol_object(value),
+    isTypedArray: (value) => op_is_typed_array(value),
+    isWeakMap: (value) => op_is_weak_map(value),
+    isWeakSet: (value) => op_is_weak_set(value),
     memoryUsage: () => ops.op_memory_usage(),
     setWasmStreamingCallback: (fn) => ops.op_set_wasm_streaming_callback(fn),
     abortWasmStreaming: (
diff --git a/core/lib.deno_core.d.ts b/core/lib.deno_core.d.ts
index 0c64fef..0ad62a5 100644
--- a/core/lib.deno_core.d.ts
+++ b/core/lib.deno_core.d.ts
@@ -1,6 +1,6 @@
 // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
 
-// deno-lint-ignore-file no-explicit-any
+// deno-lint-ignore-file ban-types no-explicit-any
 
 /// <reference no-default-lib="true" />
 /// <reference lib="esnext" />
@@ -252,6 +252,58 @@ declare namespace Deno {
       resolve_hook?: (promise: Promise<unknown>) => void,
     ): void;
 
+    function isAnyArrayBuffer(
+      value: unknown,
+    ): value is ArrayBuffer | SharedArrayBuffer;
+    function isArgumentsObject(value: unknown): value is IArguments;
+    function isArrayBuffer(value: unknown): value is ArrayBuffer;
+    function isArrayBufferView(value: unknown): value is ArrayBufferView;
+    function isAsyncFunction(
+      value: unknown,
+    ): value is (
+      ...args: unknown[]
+    ) => Promise<unknown> | AsyncGeneratorFunction;
+    function isBigIntObject(value: unknown): value is BigInt;
+    function isBooleanObject(value: unknown): value is Boolean;
+    function isBoxedPrimitive(
+      value: unknown,
+    ): value is BigInt | Boolean | Number | String | Symbol;
+    function isDataView(value: unknown): value is DataView;
+    function isDate(value: unknown): value is Date;
+    function isGeneratorFunction(
+      value: unknown,
+    ): value is GeneratorFunction | AsyncGeneratorFunction;
+    function isGeneratorObject(value: unknown): value is Generator;
+    function isMap(value: unknown): value is Map<unknown, unknown>;
+    function isMapIterator(value: unknown): value is IterableIterator<unknown>;
+    function isModuleNamespaceObject(value: unknown): value is object;
+    function isNativeError(value: unknown): value is Error;
+    function isNumberObject(value: unknown): value is Number;
+    function isPromise(value: unknown): value is Promise<unknown>;
+    function isProxy(value: unknown): value is object;
+    function isRegExp(value: unknown): value is RegExp;
+    function isSet(value: unknown): value is Set<unknown>;
+    function isSetIterator(value: unknown): value is IterableIterator<unknown>;
+    function isSharedArrayBuffer(value: unknown): value is SharedArrayBuffer;
+    function isStringObject(value: unknown): value is String;
+    function isSymbolObject(value: unknown): value is Symbol;
+    function isTypedArray(
+      value: unknown,
+    ): value is
+      | Uint8Array
+      | Uint8ClampedArray
+      | Uint16Array
+      | Uint32Array
+      | Int8Array
+      | Int16Array
+      | Int32Array
+      | Float32Array
+      | Float64Array
+      | BigUint64Array
+      | BigInt64Array;
+    function isWeakMap(value: unknown): value is WeakMap<WeakKey, unknown>;
+    function isWeakSet(value: unknown): value is WeakSet<WeakKey>;
+
     const build: {
       target: string;
       arch: string;
diff --git a/core/lib.rs b/core/lib.rs
index b60f78b..e8ffd8b 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -17,6 +17,7 @@ mod modules;
 mod normalize_path;
 mod ops;
 mod ops_builtin;
+mod ops_builtin_types;
 mod ops_builtin_v8;
 mod ops_metrics;
 mod path;
diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs
index 216d4af..3141fd6 100644
--- a/core/ops_builtin.rs
+++ b/core/ops_builtin.rs
@@ -5,6 +5,7 @@ use crate::error::type_error;
 use crate::io::BufMutView;
 use crate::io::BufView;
 use crate::op2;
+use crate::ops_builtin_types;
 use crate::ops_builtin_v8;
 use crate::resources::ResourceId;
 use crate::JsBuffer;
@@ -43,9 +44,36 @@ deno_core::extension!(
     op_write_type_error,
     op_shutdown,
     op_format_file_name,
-    op_is_proxy,
     op_str_byte_length,
     op_panic,
+    ops_builtin_types::op_is_any_array_buffer,
+    ops_builtin_types::op_is_arguments_object,
+    ops_builtin_types::op_is_array_buffer,
+    ops_builtin_types::op_is_array_buffer_view,
+    ops_builtin_types::op_is_async_function,
+    ops_builtin_types::op_is_big_int_object,
+    ops_builtin_types::op_is_boolean_object,
+    ops_builtin_types::op_is_boxed_primitive,
+    ops_builtin_types::op_is_data_view,
+    ops_builtin_types::op_is_date,
+    ops_builtin_types::op_is_generator_function,
+    ops_builtin_types::op_is_generator_object,
+    ops_builtin_types::op_is_map,
+    ops_builtin_types::op_is_map_iterator,
+    ops_builtin_types::op_is_module_namespace_object,
+    ops_builtin_types::op_is_native_error,
+    ops_builtin_types::op_is_number_object,
+    ops_builtin_types::op_is_promise,
+    ops_builtin_types::op_is_proxy,
+    ops_builtin_types::op_is_reg_exp,
+    ops_builtin_types::op_is_set,
+    ops_builtin_types::op_is_set_iterator,
+    ops_builtin_types::op_is_shared_array_buffer,
+    ops_builtin_types::op_is_string_object,
+    ops_builtin_types::op_is_symbol_object,
+    ops_builtin_types::op_is_typed_array,
+    ops_builtin_types::op_is_weak_map,
+    ops_builtin_types::op_is_weak_set,
     ops_builtin_v8::op_timer_queue,
     ops_builtin_v8::op_timer_cancel,
     ops_builtin_v8::op_timer_ref,
@@ -326,11 +354,6 @@ fn op_format_file_name(#[string] file_name: &str) -> String {
   format_file_name(file_name)
 }
 
-#[op2(fast)]
-fn op_is_proxy(value: v8::Local<v8::Value>) -> bool {
-  value.is_proxy()
-}
-
 #[op2]
 fn op_str_byte_length(
   scope: &mut v8::HandleScope,
diff --git a/core/ops_builtin_types.rs b/core/ops_builtin_types.rs
new file mode 100644
index 0000000..608ae88
--- /dev/null
+++ b/core/ops_builtin_types.rs
@@ -0,0 +1,146 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+use crate::op2;
+
+#[op2(fast)]
+pub fn op_is_any_array_buffer(value: &v8::Value) -> bool {
+  value.is_array_buffer() || value.is_shared_array_buffer()
+}
+
+#[op2(fast)]
+pub fn op_is_arguments_object(value: &v8::Value) -> bool {
+  value.is_arguments_object()
+}
+
+#[op2(fast)]
+pub fn op_is_array_buffer(value: &v8::Value) -> bool {
+  value.is_array_buffer()
+}
+
+#[op2(fast)]
+pub fn op_is_array_buffer_view(value: &v8::Value) -> bool {
+  value.is_array_buffer_view()
+}
+
+#[op2(fast)]
+pub fn op_is_async_function(value: &v8::Value) -> bool {
+  value.is_async_function()
+}
+
+#[op2(fast)]
+pub fn op_is_big_int_object(value: &v8::Value) -> bool {
+  value.is_big_int_object()
+}
+
+#[op2(fast)]
+pub fn op_is_boolean_object(value: &v8::Value) -> bool {
+  value.is_boolean_object()
+}
+
+#[op2(fast)]
+pub fn op_is_boxed_primitive(value: &v8::Value) -> bool {
+  value.is_boolean_object()
+    || value.is_string_object()
+    || value.is_number_object()
+    || value.is_symbol_object()
+    || value.is_big_int_object()
+}
+
+#[op2(fast)]
+pub fn op_is_data_view(value: &v8::Value) -> bool {
+  value.is_data_view()
+}
+
+#[op2(fast)]
+pub fn op_is_date(value: &v8::Value) -> bool {
+  value.is_date()
+}
+
+#[op2(fast)]
+pub fn op_is_generator_function(value: &v8::Value) -> bool {
+  value.is_generator_function()
+}
+
+#[op2(fast)]
+pub fn op_is_generator_object(value: &v8::Value) -> bool {
+  value.is_generator_object()
+}
+
+#[op2(fast)]
+pub fn op_is_map(value: &v8::Value) -> bool {
+  value.is_map()
+}
+
+#[op2(fast)]
+pub fn op_is_map_iterator(value: &v8::Value) -> bool {
+  value.is_map_iterator()
+}
+
+#[op2(fast)]
+pub fn op_is_module_namespace_object(value: &v8::Value) -> bool {
+  value.is_module_namespace_object()
+}
+
+#[op2(fast)]
+pub fn op_is_native_error(value: &v8::Value) -> bool {
+  value.is_native_error()
+}
+
+#[op2(fast)]
+pub fn op_is_number_object(value: &v8::Value) -> bool {
+  value.is_number_object()
+}
+
+#[op2(fast)]
+pub fn op_is_promise(value: &v8::Value) -> bool {
+  value.is_promise()
+}
+
+#[op2(fast)]
+pub fn op_is_proxy(value: &v8::Value) -> bool {
+  value.is_proxy()
+}
+
+#[op2(fast)]
+pub fn op_is_reg_exp(value: &v8::Value) -> bool {
+  value.is_reg_exp()
+}
+
+#[op2(fast)]
+pub fn op_is_set(value: &v8::Value) -> bool {
+  value.is_set()
+}
+
+#[op2(fast)]
+pub fn op_is_set_iterator(value: &v8::Value) -> bool {
+  value.is_set_iterator()
+}
+
+#[op2(fast)]
+pub fn op_is_shared_array_buffer(value: &v8::Value) -> bool {
+  value.is_shared_array_buffer()
+}
+
+#[op2(fast)]
+pub fn op_is_string_object(value: &v8::Value) -> bool {
+  value.is_string_object()
+}
+
+#[op2(fast)]
+pub fn op_is_symbol_object(value: &v8::Value) -> bool {
+  value.is_symbol_object()
+}
+
+#[op2(fast)]
+pub fn op_is_typed_array(value: &v8::Value) -> bool {
+  value.is_typed_array()
+}
+
+#[op2(fast)]
+pub fn op_is_weak_map(value: &v8::Value) -> bool {
+  value.is_weak_map()
+}
+
+#[op2(fast)]
+pub fn op_is_weak_set(value: &v8::Value) -> bool {
+  value.is_weak_set()
+}


Test patch:
diff --git a/testing/lib.rs b/testing/lib.rs
index 104e7c3..c15b3f0 100644
--- a/testing/lib.rs
+++ b/testing/lib.rs
@@ -38,6 +38,7 @@ unit_test!(
   serialize_deserialize_test,
   tc39_test,
   timer_test,
+  type_test,
 );
 
 // Test the load and run of an entire file within the `checkin` infrastructure.
diff --git a/testing/tsconfig.json b/testing/tsconfig.json
index c93cc57..db07612 100644
--- a/testing/tsconfig.json
+++ b/testing/tsconfig.json
@@ -1,5 +1,6 @@
 {
   "compilerOptions": {
+    "target": "ES2022",
     "baseUrl": ".",
     "paths": {
       "checkin:console": ["checkin/runtime/console.ts"],
diff --git a/testing/unit/type_test.ts b/testing/unit/type_test.ts
new file mode 100644
index 0000000..c30b056
--- /dev/null
+++ b/testing/unit/type_test.ts
@@ -0,0 +1,179 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+import * as module from "checkin:testing";
+import { assert, test } from "checkin:testing";
+
+test(function testIsAnyArrayBuffer() {
+  assert(Deno.core.isAnyArrayBuffer(new ArrayBuffer(4)));
+  assert(Deno.core.isAnyArrayBuffer(new SharedArrayBuffer(4)));
+  assert(!Deno.core.isAnyArrayBuffer(new Uint8Array(4)));
+});
+
+test(function testIsArgumentsObject() {
+  let args: IArguments;
+  (function () {
+    args = arguments;
+  })();
+  assert(Deno.core.isArgumentsObject(args));
+  assert(!Deno.core.isArgumentsObject({}));
+});
+
+test(function testIsArrayBuffer() {
+  assert(Deno.core.isArrayBuffer(new ArrayBuffer(4)));
+  assert(!Deno.core.isArrayBuffer(new SharedArrayBuffer(4)));
+  assert(!Deno.core.isArrayBuffer(new Uint8Array(4)));
+});
+
+test(function testIsArrayBufferView() {
+  assert(Deno.core.isArrayBufferView(new DataView(new ArrayBuffer(4))));
+  assert(Deno.core.isArrayBufferView(new Uint8Array(4)));
+  assert(!Deno.core.isArrayBufferView(new ArrayBuffer(4)));
+});
+
+test(function testIsAsyncFunction() {
+  assert(Deno.core.isAsyncFunction(async function () {}));
+  assert(Deno.core.isAsyncFunction(async function* () {}));
+  assert(!Deno.core.isAsyncFunction(function () {}));
+  assert(!Deno.core.isAsyncFunction(function* () {}));
+});
+
+test(function testIsBigIntObject() {
+  assert(Deno.core.isBigIntObject(Object(1n)));
+  assert(!Deno.core.isBigIntObject(1n));
+  assert(!Deno.core.isBigIntObject(1));
+});
+
+test(function testIsBooleanObject() {
+  assert(Deno.core.isBooleanObject(new Boolean(true)));
+  assert(!Deno.core.isBooleanObject(true));
+  assert(!Deno.core.isBooleanObject("true"));
+});
+
+test(function testIsBoxedPrimitive() {
+  assert(Deno.core.isBoxedPrimitive(Object(1n)));
+  assert(Deno.core.isBoxedPrimitive(new Boolean(true)));
+  assert(Deno.core.isBoxedPrimitive(new Number(1)));
+  assert(Deno.core.isBoxedPrimitive(Object(Symbol())));
+  assert(Deno.core.isBoxedPrimitive(new String("str")));
+  assert(!Deno.core.isBoxedPrimitive(1n));
+  assert(!Deno.core.isBoxedPrimitive(true));
+  assert(!Deno.core.isBoxedPrimitive(1));
+  assert(!Deno.core.isBoxedPrimitive(Symbol()));
+  assert(!Deno.core.isBoxedPrimitive("str"));
+});
+
+test(function testIsDataView() {
+  assert(Deno.core.isDataView(new DataView(new ArrayBuffer(4))));
+  assert(!Deno.core.isDataView(new Uint8Array(4)));
+  assert(!Deno.core.isDataView(new ArrayBuffer(4)));
+});
+
+test(function testIsDate() {
+  assert(Deno.core.isDate(new Date()));
+  assert(!Deno.core.isDate({}));
+});
+
+test(function testIsGeneratorFunction() {
+  assert(Deno.core.isGeneratorFunction(async function* () {}));
+  assert(Deno.core.isGeneratorFunction(function* () {}));
+  assert(!Deno.core.isGeneratorFunction(async function () {}));
+  assert(!Deno.core.isGeneratorFunction(function () {}));
+});
+
+test(function testIsGeneratorObject() {
+  const generator = (function* () {})();
+  assert(Deno.core.isGeneratorObject(generator));
+  assert(!Deno.core.isGeneratorObject({}));
+});
+
+test(function testIsMap() {
+  assert(Deno.core.isMap(new Map()));
+  assert(!Deno.core.isMap(new Set()));
+  assert(!Deno.core.isMap(new WeakMap()));
+  assert(!Deno.core.isMap(new WeakSet()));
+});
+
+test(function testIsMapIterator() {
+  const map = new Map();
+  assert(Deno.core.isMapIterator(map.values()));
+  assert(!Deno.core.isMapIterator(map));
+});
+
+test(function testIsModuleNamespaceObject() {
+  assert(Deno.core.isModuleNamespaceObject(module));
+  assert(!Deno.core.isModuleNamespaceObject({}));
+});
+
+test(function testIsNativeError() {
+  assert(Deno.core.isNativeError(new Error()));
+  assert(Deno.core.isNativeError(new TypeError()));
+  assert(!Deno.core.isNativeError({}));
+});
+
+test(function testIsNativeError() {
+  assert(Deno.core.isNumberObject(new Number(1)));
+  assert(!Deno.core.isNumberObject(1));
+});
+
+test(function testIsPromise() {
+  assert(Deno.core.isPromise(new Promise((resolve) => resolve(1))));
+  assert(!Deno.core.isPromise({}));
+});
+
+test(function testIsProxy() {
+  assert(Deno.core.isProxy(new Proxy({}, {})));
+  assert(!Deno.core.isProxy({}));
+});
+
+test(function testIsRegExp() {
+  assert(Deno.core.isRegExp(/foo/));
+  assert(!Deno.core.isRegExp({}));
+});
+
+test(function testIsSet() {
+  assert(Deno.core.isSet(new Set()));
+  assert(!Deno.core.isSet(new Map()));
+  assert(!Deno.core.isSet(new WeakSet()));
+  assert(!Deno.core.isSet(new WeakMap()));
+});
+
+test(function testIsSetIterator() {
+  const set = new Set();
+  assert(Deno.core.isSetIterator(set.values()));
+  assert(!Deno.core.isSetIterator(set));
+});
+
+test(function testIsSharedArrayBuffer() {
+  assert(Deno.core.isSharedArrayBuffer(new SharedArrayBuffer(4)));
+  assert(!Deno.core.isSharedArrayBuffer(new ArrayBuffer(4)));
+  assert(!Deno.core.isSharedArrayBuffer(new Uint8Array(4)));
+});
+
+test(function testIsStringObject() {
+  assert(Deno.core.isStringObject(new String("str")));
+  assert(!Deno.core.isStringObject("str"));
+});
+
+test(function testIsSymbolObject() {
+  assert(Deno.core.isSymbolObject(Object(Symbol())));
+  assert(!Deno.core.isSymbolObject(Symbol()));
+});
+
+test(function testIsTypedArray() {
+  assert(Deno.core.isTypedArray(new Uint8Array(4)));
+  assert(!Deno.core.isTypedArray(new DataView(new ArrayBuffer(4))));
+  assert(!Deno.core.isTypedArray(new ArrayBuffer(4)));
+});
+
+test(function testIsWeakMap() {
+  assert(Deno.core.isWeakMap(new WeakMap()));
+  assert(!Deno.core.isWeakMap(new WeakSet()));
+  assert(!Deno.core.isWeakMap(new Map()));
+  assert(!Deno.core.isWeakMap(new Set()));
+});
+
+test(function testIsWeakSet() {
+  assert(Deno.core.isWeakSet(new WeakSet()));
+  assert(!Deno.core.isWeakSet(new WeakMap()));
+  assert(!Deno.core.isWeakSet(new Set()));
+  assert(!Deno.core.isWeakSet(new Map()));
+});