diff --git a/LICENSE b/LICENSE index ce70ac9357..6781a5d179 100644 --- a/LICENSE +++ b/LICENSE @@ -272,11 +272,6 @@ The text of each license is also included in licenses/LICENSE-[project].txt. java/fury-core/src/main/java/org/apache/fury/type/Generics.java java/fury-core/src/test/java/org/apache/fury/type/GenericsTest.java -* v8 (https://chromium.googlesource.com/v8/v8.git) - Files: - javascript/packages/hps/src/v8-fast-api-calls.h - - ================================================================ MIT licenses ================================================================ diff --git a/ci/release.py b/ci/release.py index 0f110461fc..f38d893dc9 100644 --- a/ci/release.py +++ b/ci/release.py @@ -148,12 +148,6 @@ def bump_version(**kwargs): new_version, _update_js_version, ) - _bump_version( - "javascript/packages/hps", - "package.json", - new_version, - _update_js_version, - ) else: raise NotImplementedError(f"Unsupported {lang}") diff --git a/docs/guide/xlang_serialization_guide.md b/docs/guide/xlang_serialization_guide.md index 60fb72906f..f3355042e2 100644 --- a/docs/guide/xlang_serialization_guide.md +++ b/docs/guide/xlang_serialization_guide.md @@ -98,14 +98,7 @@ func main() { ```javascript import Fury from '@furyjs/fury'; -/** - * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from '@furyjs/hps'; - -const fury = new Fury({ hps }); +const fury = new Fury({}); const input = fury.serialize('hello fury'); const result = fury.deserialize(input); console.log(result); @@ -317,18 +310,11 @@ func main() { ```javascript import Fury, { Type, InternalSerializerType } from '@furyjs/fury'; -/** - * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from '@furyjs/hps'; - // Now we describe data structures using JSON, but in the future, we will use more ways. const description = Type.object('example.foo', { foo: Type.string(), }); -const fury = new Fury({ hps }); +const fury = new Fury({}); const { serialize, deserialize } = fury.registerSerializer(description); const input = serialize({ foo: 'hello fury' }); const result = deserialize(input); @@ -490,19 +476,13 @@ func main() { ```javascript import Fury, { Type } from '@furyjs/fury'; -/** - * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from '@furyjs/hps'; const description = Type.object('example.foo', { foo: Type.string(), bar: Type.object('example.foo'), }); -const fury = new Fury({ hps }); +const fury = new Fury({}); const { serialize, deserialize } = fury.registerSerializer(description); const data: any = { foo: 'hello fury', diff --git a/javascript/README.md b/javascript/README.md index 377da0ea0f..8ec358d2a8 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -8,7 +8,6 @@ The Cross-Language part of the protocol is not stable, so the output of this lib ```shell npm install @furyjs/fury -npm install @furyjs/hps ``` ## Usage @@ -16,18 +15,11 @@ npm install @furyjs/hps ```Javascript import Fury, { Type, InternalSerializerType } from '@furyjs/fury'; -/** - * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from '@furyjs/hps'; - // Now we describe data structures using JSON, but in the future, we will use more ways. const description = Type.object('example.foo', { foo: Type.string(), }); -const fury = new Fury({ hps }); +const fury = new Fury({}); const { serialize, deserialize } = fury.registerSerializer(description); const input = serialize({ foo: 'hello fury' }); const result = deserialize(input); @@ -39,11 +31,3 @@ console.log(result); ### fury Fury protocol implementation. It generates JavaScript code at runtime to make sure that all the code could be optimized by v8 JIT efficiently. - -### hps - -Node.js high-performance suite, ensuring that your Node.js version is 20 or later. - -`hps` is use for detect the string type in v8. Fury support latin1 and utf8 string both, we should get the certain type of string before write it -in buffer. It is slow to detect the string is latin1 or utf8, but hps can detect it by a hack way, which is called FASTCALL in v8. -so it is not stable now. diff --git a/javascript/benchmark/index.js b/javascript/benchmark/index.js index 52d0b267be..11eb0044d2 100644 --- a/javascript/benchmark/index.js +++ b/javascript/benchmark/index.js @@ -19,8 +19,7 @@ const Fury = require("@furyjs/fury"); const utils = require("@furyjs/fury/dist/lib/util"); -const hps = require('@furyjs/hps'); -const fury = new Fury.default({ hps, refTracking: false, useSliceString: true }); +const fury = new Fury.default({ refTracking: false, useSliceString: true }); const Benchmark = require("benchmark"); const protobuf = require("protobufjs"); const path = require('path'); diff --git a/javascript/benchmark/map.js b/javascript/benchmark/map.js index 121c02baf0..1bd3d98980 100644 --- a/javascript/benchmark/map.js +++ b/javascript/benchmark/map.js @@ -19,9 +19,8 @@ const Fury = require("@furyjs/fury"); const beautify = require("js-beautify"); -const hps = require('@furyjs/hps'); const fury = new Fury.default({ - hps, refTracking: false, useSliceString: true, hooks: { + refTracking: false, useSliceString: true, hooks: { afterCodeGenerated: (code) => { return beautify.js(code, { indent_size: 2, space_in_empty_paren: true, indent_empty_lines: true }); } diff --git a/javascript/jest.config.js b/javascript/jest.config.js index ce81426919..eb89174041 100644 --- a/javascript/jest.config.js +++ b/javascript/jest.config.js @@ -19,10 +19,9 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ const semver = require("semver"); -const hpsEnable = semver.gt(process.versions.node, '20.0.0') && process.platform !== 'win32'; module.exports = { - collectCoverage: hpsEnable, + collectCoverage: true, preset: 'ts-jest', testEnvironment: 'node', collectCoverageFrom: [ @@ -31,9 +30,6 @@ module.exports = { "!**/build/**", "!packages/fury/lib/murmurHash3.ts" ], - "testPathIgnorePatterns" : [ - hpsEnable ? null : "(.*)/hps.test.ts$", - ].filter(Boolean), transform: { '\\.ts$': ['ts-jest', { tsconfig: { diff --git a/javascript/package.json b/javascript/package.json index 8b257e6a14..78797ab549 100644 --- a/javascript/package.json +++ b/javascript/package.json @@ -1,14 +1,13 @@ { "scripts": { "test": "npm run build && jest", - "clear": "rm -rf ./packages/fury/dist && rm -rf ./packages/hps/dist", - "build": "npm run clear && npm run build -w packages/fury -w packages/hps", + "clear": "rm -rf ./packages/fury/dist", + "build": "npm run clear && npm run build -w packages/fury", "lint": "eslint .", "lint-fix": "eslint . --fix" }, "repository": "git@github.com:apache/fury.git", "workspaces": [ - "packages/hps", "packages/fury" ], "devDependencies": { diff --git a/javascript/packages/fury/lib/type.ts b/javascript/packages/fury/lib/type.ts index 23956da896..fa584450fd 100644 --- a/javascript/packages/fury/lib/type.ts +++ b/javascript/packages/fury/lib/type.ts @@ -95,18 +95,12 @@ export const HalfMinInt32 = MinInt32 / 2; export const LATIN1 = 0; export const UTF8 = 1; -export interface Hps { - isLatin1: (str: string) => boolean; - stringCopy: (str: string, dist: Uint8Array, offset: number) => void; -} - export enum Mode { SchemaConsistent, Compatible, } export interface Config { - hps?: Hps; refTracking?: boolean; useSliceString?: boolean; hooks?: { diff --git a/javascript/packages/fury/lib/writer/index.ts b/javascript/packages/fury/lib/writer/index.ts index 69ef309026..cf168c5540 100644 --- a/javascript/packages/fury/lib/writer/index.ts +++ b/javascript/packages/fury/lib/writer/index.ts @@ -22,6 +22,11 @@ import { PlatformBuffer, alloc, strByteLength } from "../platformBuffer"; import { OwnershipError } from "../error"; import { toFloat16 } from "./number"; +declare global { + // eslint-disable-next-line + var isOneByteString: ((input: string) => boolean) | undefined; +} + const MAX_POOL_SIZE = 1024 * 1024 * 3; // 3MB export class BinaryWriter { @@ -32,12 +37,10 @@ export class BinaryWriter { private reserved = 0; private locked = false; private config: Config; - private hpsEnable = false; constructor(config: Config) { this.initPoll(); this.config = config; - this.hpsEnable = Boolean(config?.hps); } private initPoll() { @@ -188,14 +191,13 @@ export class BinaryWriter { } stringOfVarUInt32Fast(v: string) { - const { isLatin1: detectIsLatin1, stringCopy } = this.config.hps!; - const isLatin1 = detectIsLatin1(v); + const isLatin1 = globalThis.isOneByteString!(v); const len = isLatin1 ? v.length : strByteLength(v); this.dataView.setUint8(this.cursor++, isLatin1 ? LATIN1 : UTF8); this.varUInt32(len); this.reserve(len); if (isLatin1) { - stringCopy(v, this.platformBuffer, this.cursor); + this.platformBuffer.write(v, this.cursor, "latin1"); } else { if (len < 40) { this.fastWriteStringUtf8(v, this.platformBuffer, this.cursor); @@ -335,7 +337,7 @@ export class BinaryWriter { } stringOfVarUInt32(v: string) { - return this.hpsEnable + return globalThis.isOneByteString ? this.stringOfVarUInt32Fast(v) : this.stringOfVarUInt32Slow(v); } diff --git a/javascript/packages/fury/package.json b/javascript/packages/fury/package.json index 810709ad09..f33aec3fff 100644 --- a/javascript/packages/fury/package.json +++ b/javascript/packages/fury/package.json @@ -25,6 +25,5 @@ }, "repository": "git@github.com:apache/fury.git", "workspaces": [ - "packages/hps" ] } diff --git a/javascript/packages/hps/README.md b/javascript/packages/hps/README.md deleted file mode 100644 index e776db0155..0000000000 --- a/javascript/packages/hps/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Apache Fury™ JavaScript - -Node.js high-performance suite, ensuring that your Node.js version is 20 or later. - -`hps` is use for detect the string type in v8. Fury support latin1 and utf8 string both, we should get the certain type of string before write it -in buffer. It is slow to detect the string is latin1 or utf8, but hps can detect it by a hack way, which is called FASTCALL in v8. -so it is not stable now. - -Apache Fury(incubating) is an effort undergoing incubation at the Apache -Software Foundation (ASF), sponsored by the Apache Incubator PMC. - -Incubation is required of all newly accepted projects until a further review -indicates that the infrastructure, communications, and decision making process -have stabilized in a manner consistent with other successful ASF projects. - -While incubation status is not necessarily a reflection of the completeness -or stability of the code, it does indicate that the project has yet to be -fully endorsed by the ASF. diff --git a/javascript/packages/hps/binding.gyp b/javascript/packages/hps/binding.gyp deleted file mode 100644 index 73b11b41e7..0000000000 --- a/javascript/packages/hps/binding.gyp +++ /dev/null @@ -1,32 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -{ - "targets": [ - { - "target_name": "hps", - "sources": [ - "src/fastcall.cc", - "src/v8-fast-api-calls.h" - ], - "include_dirs" : [ - " boolean; - stringCopy: (str: string, dist: Uint8Array, offset: number) => void; -} - -const { isLatin1, stringCopy } = hps; - -export { - isLatin1, - stringCopy, -}; diff --git a/javascript/packages/hps/package.json b/javascript/packages/hps/package.json deleted file mode 100644 index ffd529d4ad..0000000000 --- a/javascript/packages/hps/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@furyjs/hps", - "version": "0.10.0.dev", - "description": "Apache Fury™(incubating) nodejs high-performance suite", - "main": "dist/index.js", - "files": [ - "dist", - "src", - "binding.gyp" - ], - "gypfile": false, - "scripts": { - "postinstall": "node -e \"if (process.version.match(/v(\\d+)/)[1] >= 20 && process.platform !== 'win32') { require('child_process').execSync('npx node-gyp rebuild') } \"", - "build": "node -e \"if (process.version.match(/v(\\d+)/)[1] >= 20 && process.platform !== 'win32') { require('child_process').execSync('npx node-gyp rebuild && tsc') } \"", - "prepublishOnly": "npm run build" - }, - "license": "Apache-2.0", - "dependencies": { - "bindings": "~1.2.1", - "nan": "^2.17.0", - "node-gyp": "^9.4.0" - }, - "engines": { - "node": "^20.0.0" - } -} diff --git a/javascript/packages/hps/src/fastcall.cc b/javascript/packages/hps/src/fastcall.cc deleted file mode 100644 index 38f1cda6f7..0000000000 --- a/javascript/packages/hps/src/fastcall.cc +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "v8-fast-api-calls.h" -#include - -void IsLatin1Slow(const v8::FunctionCallbackInfo &info) { - v8::Local input = info[0].As(); - info.GetReturnValue().Set(Nan::New(input->IsOneByte())); -} - -bool IsLatin1Fast(v8::Local receiver, - const v8::FastOneByteString &source) { - return true; -} - -static v8::CFunction fast_is_latin1(v8::CFunction::Make(IsLatin1Fast)); - -void StringCopySlow(const v8::FunctionCallbackInfo &info) { - v8::Isolate *isolate = info.GetIsolate(); - v8::Local source = info[0].As(); - char *type_array = - (char *)info[1].As()->Buffer()->GetBackingStore()->Data(); - int32_t offset = - info[2]->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust(); - - v8::String::Utf8Value source_value(isolate, source); - - for (size_t i = 0; i < source_value.length(); i++) { - *(type_array + (offset++)) = *((*source_value) + i); - } - info.GetReturnValue().Set(Nan::New(100)); -} - -void StringCopyFast(v8::Local receiver, - const v8::FastOneByteString &source, - const v8::FastApiTypedArray &ab, - u_int32_t offset) { - uint8_t *ptr; - ab.getStorageIfAligned(&ptr); - int32_t i = 0; - memcpy(ptr + offset, source.data, source.length); -} - -static v8::CFunction string_copy_fast(v8::CFunction::Make(StringCopyFast)); - -v8::Local FastFunction(v8::Isolate *isolate, - v8::FunctionCallback callback, - const v8::CFunction *c_function) { - return v8::FunctionTemplate::New( - isolate, callback, v8::Local(), v8::Local(), 0, - v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect, - c_function); -} - -void Init(v8::Local exports) { - v8::Local context = exports->GetCreationContextChecked(); - v8::Isolate *isolate = context->GetIsolate(); - exports->Set(context, Nan::New("isLatin1").ToLocalChecked(), - FastFunction(isolate, IsLatin1Slow, &fast_is_latin1) - ->GetFunction(context) - .ToLocalChecked()); - exports->Set(context, Nan::New("stringCopy").ToLocalChecked(), - FastFunction(isolate, StringCopySlow, &string_copy_fast) - ->GetFunction(context) - .ToLocalChecked()); -} - -NODE_MODULE(fury_util, Init) \ No newline at end of file diff --git a/javascript/packages/hps/src/v8-fast-api-calls.h b/javascript/packages/hps/src/v8-fast-api-calls.h deleted file mode 100644 index 0fe7cd2489..0000000000 --- a/javascript/packages/hps/src/v8-fast-api-calls.h +++ /dev/null @@ -1,957 +0,0 @@ -// Copyright 2020 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * This file provides additional API on top of the default one for making - * API calls, which come from embedder C++ functions. The functions are being - * called directly from optimized code, doing all the necessary typechecks - * in the compiler itself, instead of on the embedder side. Hence the "fast" - * in the name. Example usage might look like: - * - * \code - * void FastMethod(int param, bool another_param); - * - * v8::FunctionTemplate::New(isolate, SlowCallback, data, - * signature, length, constructor_behavior - * side_effect_type, - * &v8::CFunction::Make(FastMethod)); - * \endcode - * - * By design, fast calls are limited by the following requirements, which - * the embedder should enforce themselves: - * - they should not allocate on the JS heap; - * - they should not trigger JS execution. - * To enforce them, the embedder could use the existing - * v8::Isolate::DisallowJavascriptExecutionScope and a utility similar to - * Blink's NoAllocationScope: - * https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/heap/thread_state_scopes.h;l=16 - * - * Due to these limitations, it's not directly possible to report errors by - * throwing a JS exception or to otherwise do an allocation. There is an - * alternative way of creating fast calls that supports falling back to the - * slow call and then performing the necessary allocation. When one creates - * the fast method by using CFunction::MakeWithFallbackSupport instead of - * CFunction::Make, the fast callback gets as last parameter an output variable, - * through which it can request falling back to the slow call. So one might - * declare their method like: - * - * \code - * void FastMethodWithFallback(int param, FastApiCallbackOptions& options); - * \endcode - * - * If the callback wants to signal an error condition or to perform an - * allocation, it must set options.fallback to true and do an early return from - * the fast method. Then V8 checks the value of options.fallback and if it's - * true, falls back to executing the SlowCallback, which is capable of reporting - * the error (either by throwing a JS exception or logging to the console) or - * doing the allocation. It's the embedder's responsibility to ensure that the - * fast callback is idempotent up to the point where error and fallback - * conditions are checked, because otherwise executing the slow callback might - * produce visible side-effects twice. - * - * An example for custom embedder type support might employ a way to wrap/ - * unwrap various C++ types in JSObject instances, e.g: - * - * \code - * - * // Helper method with a check for field count. - * template - * inline T* GetInternalField(v8::Local wrapper) { - * assert(offset < wrapper->InternalFieldCount()); - * return reinterpret_cast( - * wrapper->GetAlignedPointerFromInternalField(offset)); - * } - * - * class CustomEmbedderType { - * public: - * // Returns the raw C object from a wrapper JS object. - * static CustomEmbedderType* Unwrap(v8::Local wrapper) { - * return GetInternalField(wrapper); - * } - * static void FastMethod(v8::Local receiver_obj, int param) { - * CustomEmbedderType* receiver = static_cast( - * receiver_obj->GetAlignedPointerFromInternalField( - * kV8EmbedderWrapperObjectIndex)); - * - * // Type checks are already done by the optimized code. - * // Then call some performance-critical method like: - * // receiver->Method(param); - * } - * - * static void SlowMethod( - * const v8::FunctionCallbackInfo& info) { - * v8::Local instance = - * v8::Local::Cast(info.Holder()); - * CustomEmbedderType* receiver = Unwrap(instance); - * // TODO: Do type checks and extract {param}. - * receiver->Method(param); - * } - * }; - * - * // TODO(mslekova): Clean-up these constants - * // The constants kV8EmbedderWrapperTypeIndex and - * // kV8EmbedderWrapperObjectIndex describe the offsets for the type info - * // struct and the native object, when expressed as internal field indices - * // within a JSObject. The existance of this helper function assumes that - * // all embedder objects have their JSObject-side type info at the same - * // offset, but this is not a limitation of the API itself. For a detailed - * // use case, see the third example. - * static constexpr int kV8EmbedderWrapperTypeIndex = 0; - * static constexpr int kV8EmbedderWrapperObjectIndex = 1; - * - * // The following setup function can be templatized based on - * // the {embedder_object} argument. - * void SetupCustomEmbedderObject(v8::Isolate* isolate, - * v8::Local context, - * CustomEmbedderType* embedder_object) { - * isolate->set_embedder_wrapper_type_index( - * kV8EmbedderWrapperTypeIndex); - * isolate->set_embedder_wrapper_object_index( - * kV8EmbedderWrapperObjectIndex); - * - * v8::CFunction c_func = - * MakeV8CFunction(CustomEmbedderType::FastMethod); - * - * Local method_template = - * v8::FunctionTemplate::New( - * isolate, CustomEmbedderType::SlowMethod, v8::Local(), - * v8::Local(), 1, v8::ConstructorBehavior::kAllow, - * v8::SideEffectType::kHasSideEffect, &c_func); - * - * v8::Local object_template = - * v8::ObjectTemplate::New(isolate); - * object_template->SetInternalFieldCount( - * kV8EmbedderWrapperObjectIndex + 1); - * object_template->Set(isolate, "method", method_template); - * - * // Instantiate the wrapper JS object. - * v8::Local object = - * object_template->NewInstance(context).ToLocalChecked(); - * object->SetAlignedPointerInInternalField( - * kV8EmbedderWrapperObjectIndex, - * reinterpret_cast(embedder_object)); - * - * // TODO: Expose {object} where it's necessary. - * } - * \endcode - * - * For instance if {object} is exposed via a global "obj" variable, - * one could write in JS: - * function hot_func() { - * obj.method(42); - * } - * and once {hot_func} gets optimized, CustomEmbedderType::FastMethod - * will be called instead of the slow version, with the following arguments: - * receiver := the {embedder_object} from above - * param := 42 - * - * Currently supported return types: - * - void - * - bool - * - int32_t - * - uint32_t - * - float32_t - * - float64_t - * Currently supported argument types: - * - pointer to an embedder type - * - JavaScript array of primitive types - * - bool - * - int32_t - * - uint32_t - * - int64_t - * - uint64_t - * - float32_t - * - float64_t - * - * The 64-bit integer types currently have the IDL (unsigned) long long - * semantics: https://heycam.github.io/webidl/#abstract-opdef-converttoint - * In the future we'll extend the API to also provide conversions from/to - * BigInt to preserve full precision. - * The floating point types currently have the IDL (unrestricted) semantics, - * which is the only one used by WebGL. We plan to add support also for - * restricted floats/doubles, similarly to the BigInt conversion policies. - * We also differ from the specific NaN bit pattern that WebIDL prescribes - * (https://heycam.github.io/webidl/#es-unrestricted-float) in that Blink - * passes NaN values as-is, i.e. doesn't normalize them. - * - * To be supported types: - * - TypedArrays and ArrayBuffers - * - arrays of embedder types - * - * - * The API offers a limited support for function overloads: - * - * \code - * void FastMethod_2Args(int param, bool another_param); - * void FastMethod_3Args(int param, bool another_param, int third_param); - * - * v8::CFunction fast_method_2args_c_func = - * MakeV8CFunction(FastMethod_2Args); - * v8::CFunction fast_method_3args_c_func = - * MakeV8CFunction(FastMethod_3Args); - * const v8::CFunction fast_method_overloads[] = {fast_method_2args_c_func, - * fast_method_3args_c_func}; - * Local method_template = - * v8::FunctionTemplate::NewWithCFunctionOverloads( - * isolate, SlowCallback, data, signature, length, - * constructor_behavior, side_effect_type, - * {fast_method_overloads, 2}); - * \endcode - * - * In this example a single FunctionTemplate is associated to multiple C++ - * functions. The overload resolution is currently only based on the number of - * arguments passed in a call. For example, if this method_template is - * registered with a wrapper JS object as described above, a call with two - * arguments: - * obj.method(42, true); - * will result in a fast call to FastMethod_2Args, while a call with three or - * more arguments: - * obj.method(42, true, 11); - * will result in a fast call to FastMethod_3Args. Instead a call with less than - * two arguments, like: - * obj.method(42); - * would not result in a fast call but would fall back to executing the - * associated SlowCallback. - */ - -#ifndef INCLUDE_V8_FAST_API_CALLS_H_ -#define INCLUDE_V8_FAST_API_CALLS_H_ - -#include -#include - -#include -#include - -#include "v8-internal.h" // NOLINT(build/include_directory) -#include "v8-local-handle.h" // NOLINT(build/include_directory) -#include "v8-typed-array.h" // NOLINT(build/include_directory) -#include "v8-value.h" // NOLINT(build/include_directory) -#include "v8config.h" // NOLINT(build/include_directory) - -namespace v8 { - -class Isolate; - -class CTypeInfo { - public: - enum class Type : uint8_t { - kVoid, - kBool, - kUint8, - kInt32, - kUint32, - kInt64, - kUint64, - kFloat32, - kFloat64, - kPointer, - kV8Value, - kSeqOneByteString, - kApiObject, // This will be deprecated once all users have - // migrated from v8::ApiObject to v8::Local. - kAny, // This is added to enable untyped representation of fast - // call arguments for test purposes. It can represent any of - // the other types stored in the same memory as a union (see - // the AnyCType struct declared below). This allows for - // uniform passing of arguments w.r.t. their location - // (in a register or on the stack), independent of their - // actual type. It's currently used by the arm64 simulator - // and can be added to the other simulators as well when fast - // calls having both GP and FP params need to be supported. - }; - - // kCallbackOptionsType is not part of the Type enum - // because it is only used internally. Use value 255 that is larger - // than any valid Type enum. - static constexpr Type kCallbackOptionsType = Type(255); - - enum class SequenceType : uint8_t { - kScalar, - kIsSequence, // sequence - kIsTypedArray, // TypedArray of T or any ArrayBufferView if T - // is void - kIsArrayBuffer // ArrayBuffer - }; - - enum class Flags : uint8_t { - kNone = 0, - kAllowSharedBit = 1 << 0, // Must be an ArrayBuffer or TypedArray - kEnforceRangeBit = 1 << 1, // T must be integral - kClampBit = 1 << 2, // T must be integral - kIsRestrictedBit = 1 << 3, // T must be float or double - }; - - explicit constexpr CTypeInfo( - Type type, SequenceType sequence_type = SequenceType::kScalar, - Flags flags = Flags::kNone) - : type_(type), sequence_type_(sequence_type), flags_(flags) {} - - typedef uint32_t Identifier; - explicit constexpr CTypeInfo(Identifier identifier) - : CTypeInfo(static_cast(identifier >> 16), - static_cast((identifier >> 8) & 255), - static_cast(identifier & 255)) {} - constexpr Identifier GetId() const { - return static_cast(type_) << 16 | - static_cast(sequence_type_) << 8 | - static_cast(flags_); - } - - constexpr Type GetType() const { return type_; } - constexpr SequenceType GetSequenceType() const { return sequence_type_; } - constexpr Flags GetFlags() const { return flags_; } - - static constexpr bool IsIntegralType(Type type) { - return type == Type::kUint8 || type == Type::kInt32 || - type == Type::kUint32 || type == Type::kInt64 || - type == Type::kUint64; - } - - static constexpr bool IsFloatingPointType(Type type) { - return type == Type::kFloat32 || type == Type::kFloat64; - } - - static constexpr bool IsPrimitive(Type type) { - return IsIntegralType(type) || IsFloatingPointType(type) || - type == Type::kBool; - } - - private: - Type type_; - SequenceType sequence_type_; - Flags flags_; -}; - -struct FastApiTypedArrayBase { - public: - // Returns the length in number of elements. - size_t V8_EXPORT length() const { return length_; } - // Checks whether the given index is within the bounds of the collection. - void V8_EXPORT ValidateIndex(size_t index) const; - - protected: - size_t length_ = 0; -}; - -template -struct FastApiTypedArray : public FastApiTypedArrayBase { - public: - V8_INLINE T get(size_t index) const { -#ifdef DEBUG - ValidateIndex(index); -#endif // DEBUG - T tmp; - memcpy(&tmp, reinterpret_cast(data_) + index, sizeof(T)); - return tmp; - } - - bool getStorageIfAligned(T** elements) const { - if (reinterpret_cast(data_) % alignof(T) != 0) { - return false; - } - *elements = reinterpret_cast(data_); - return true; - } - - private: - // This pointer should include the typed array offset applied. - // It's not guaranteed that it's aligned to sizeof(T), it's only - // guaranteed that it's 4-byte aligned, so for 8-byte types we need to - // provide a special implementation for reading from it, which hides - // the possibly unaligned read in the `get` method. - void* data_; -}; - -// Any TypedArray. It uses kTypedArrayBit with base type void -// Overloaded args of ArrayBufferView and TypedArray are not supported -// (for now) because the generic “any” ArrayBufferView doesn’t have its -// own instance type. It could be supported if we specify that -// TypedArray always has precedence over the generic ArrayBufferView, -// but this complicates overload resolution. -struct FastApiArrayBufferView { - void* data; - size_t byte_length; -}; - -struct FastApiArrayBuffer { - void* data; - size_t byte_length; -}; - -struct FastOneByteString { - const char* data; - uint32_t length; -}; - -class V8_EXPORT CFunctionInfo { - public: - // Construct a struct to hold a CFunction's type information. - // |return_info| describes the function's return type. - // |arg_info| is an array of |arg_count| CTypeInfos describing the - // arguments. Only the last argument may be of the special type - // CTypeInfo::kCallbackOptionsType. - CFunctionInfo(const CTypeInfo& return_info, unsigned int arg_count, - const CTypeInfo* arg_info); - - const CTypeInfo& ReturnInfo() const { return return_info_; } - - // The argument count, not including the v8::FastApiCallbackOptions - // if present. - unsigned int ArgumentCount() const { - return HasOptions() ? arg_count_ - 1 : arg_count_; - } - - // |index| must be less than ArgumentCount(). - // Note: if the last argument passed on construction of CFunctionInfo - // has type CTypeInfo::kCallbackOptionsType, it is not included in - // ArgumentCount(). - const CTypeInfo& ArgumentInfo(unsigned int index) const; - - bool HasOptions() const { - // The options arg is always the last one. - return arg_count_ > 0 && arg_info_[arg_count_ - 1].GetType() == - CTypeInfo::kCallbackOptionsType; - } - - private: - const CTypeInfo return_info_; - const unsigned int arg_count_; - const CTypeInfo* arg_info_; -}; - -struct FastApiCallbackOptions; - -// Provided for testing. -struct AnyCType { - AnyCType() : int64_value(0) {} - - union { - bool bool_value; - int32_t int32_value; - uint32_t uint32_value; - int64_t int64_value; - uint64_t uint64_value; - float float_value; - double double_value; - void* pointer_value; - Local object_value; - Local sequence_value; - const FastApiTypedArray* uint8_ta_value; - const FastApiTypedArray* int32_ta_value; - const FastApiTypedArray* uint32_ta_value; - const FastApiTypedArray* int64_ta_value; - const FastApiTypedArray* uint64_ta_value; - const FastApiTypedArray* float_ta_value; - const FastApiTypedArray* double_ta_value; - const FastOneByteString* string_value; - FastApiCallbackOptions* options_value; - }; -}; - -static_assert( - sizeof(AnyCType) == 8, - "The AnyCType struct should have size == 64 bits, as this is assumed " - "by EffectControlLinearizer."); - -class V8_EXPORT CFunction { - public: - constexpr CFunction() : address_(nullptr), type_info_(nullptr) {} - - const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); } - - const CTypeInfo& ArgumentInfo(unsigned int index) const { - return type_info_->ArgumentInfo(index); - } - - unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); } - - const void* GetAddress() const { return address_; } - const CFunctionInfo* GetTypeInfo() const { return type_info_; } - - enum class OverloadResolution { kImpossible, kAtRuntime, kAtCompileTime }; - - // Returns whether an overload between this and the given CFunction can - // be resolved at runtime by the RTTI available for the arguments or at - // compile time for functions with different number of arguments. - OverloadResolution GetOverloadResolution(const CFunction* other) { - // Runtime overload resolution can only deal with functions with the - // same number of arguments. Functions with different arity are handled - // by compile time overload resolution though. - if (ArgumentCount() != other->ArgumentCount()) { - return OverloadResolution::kAtCompileTime; - } - - // The functions can only differ by a single argument position. - int diff_index = -1; - for (unsigned int i = 0; i < ArgumentCount(); ++i) { - if (ArgumentInfo(i).GetSequenceType() != - other->ArgumentInfo(i).GetSequenceType()) { - if (diff_index >= 0) { - return OverloadResolution::kImpossible; - } - diff_index = i; - - // We only support overload resolution between sequence types. - if (ArgumentInfo(i).GetSequenceType() == - CTypeInfo::SequenceType::kScalar || - other->ArgumentInfo(i).GetSequenceType() == - CTypeInfo::SequenceType::kScalar) { - return OverloadResolution::kImpossible; - } - } - } - - return OverloadResolution::kAtRuntime; - } - - template - static CFunction Make(F* func) { - return ArgUnwrap::Make(func); - } - - // Provided for testing purposes. - template - static CFunction Make(R (*func)(Args...), - R_Patch (*patching_func)(Args_Patch...)) { - CFunction c_func = ArgUnwrap::Make(func); - static_assert( - sizeof...(Args_Patch) == sizeof...(Args), - "The patching function must have the same number of arguments."); - c_func.address_ = reinterpret_cast(patching_func); - return c_func; - } - - CFunction(const void* address, const CFunctionInfo* type_info); - - private: - const void* address_; - const CFunctionInfo* type_info_; - - template - class ArgUnwrap { - static_assert(sizeof(F) != sizeof(F), - "CFunction must be created from a function pointer."); - }; - - template - class ArgUnwrap { - public: - static CFunction Make(R (*func)(Args...)); - }; -}; - -/** - * A struct which may be passed to a fast call callback, like so: - * \code - * void FastMethodWithOptions(int param, FastApiCallbackOptions& options); - * \endcode - */ -struct FastApiCallbackOptions { - /** - * Creates a new instance of FastApiCallbackOptions for testing purpose. The - * returned instance may be filled with mock data. - */ - static FastApiCallbackOptions CreateForTesting(Isolate* isolate) { - return {false, {0}, nullptr}; - } - - /** - * If the callback wants to signal an error condition or to perform an - * allocation, it must set options.fallback to true and do an early return - * from the fast method. Then V8 checks the value of options.fallback and if - * it's true, falls back to executing the SlowCallback, which is capable of - * reporting the error (either by throwing a JS exception or logging to the - * console) or doing the allocation. It's the embedder's responsibility to - * ensure that the fast callback is idempotent up to the point where error and - * fallback conditions are checked, because otherwise executing the slow - * callback might produce visible side-effects twice. - */ - bool fallback; - - /** - * The `data` passed to the FunctionTemplate constructor, or `undefined`. - * `data_ptr` allows for default constructing FastApiCallbackOptions. - */ - union { - uintptr_t data_ptr; - v8::Local data; - }; - - /** - * When called from WebAssembly, a view of the calling module's memory. - */ - FastApiTypedArray* const wasm_memory; -}; - -namespace internal { - -// Helper to count the number of occurances of `T` in `List` -template -struct count : std::integral_constant {}; -template -struct count - : std::integral_constant::value> {}; -template -struct count : count {}; - -template -class CFunctionInfoImpl : public CFunctionInfo { - static constexpr int kOptionsArgCount = - count(); - static constexpr int kReceiverCount = 1; - - static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1, - "Only one options parameter is supported."); - - static_assert(sizeof...(ArgBuilders) >= kOptionsArgCount + kReceiverCount, - "The receiver or the options argument is missing."); - - public: - constexpr CFunctionInfoImpl() - : CFunctionInfo(RetBuilder::Build(), sizeof...(ArgBuilders), - arg_info_storage_), - arg_info_storage_{ArgBuilders::Build()...} { - constexpr CTypeInfo::Type kReturnType = RetBuilder::Build().GetType(); - static_assert(kReturnType == CTypeInfo::Type::kVoid || - kReturnType == CTypeInfo::Type::kBool || - kReturnType == CTypeInfo::Type::kInt32 || - kReturnType == CTypeInfo::Type::kUint32 || - kReturnType == CTypeInfo::Type::kFloat32 || - kReturnType == CTypeInfo::Type::kFloat64 || - kReturnType == CTypeInfo::Type::kPointer || - kReturnType == CTypeInfo::Type::kAny, - "64-bit int, string and api object values are not currently " - "supported return types."); - } - - private: - const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)]; -}; - -template -struct TypeInfoHelper { - static_assert(sizeof(T) != sizeof(T), "This type is not supported"); -}; - -#define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR(T, Enum) \ - template <> \ - struct TypeInfoHelper { \ - static constexpr CTypeInfo::Flags Flags() { \ - return CTypeInfo::Flags::kNone; \ - } \ - \ - static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \ - static constexpr CTypeInfo::SequenceType SequenceType() { \ - return CTypeInfo::SequenceType::kScalar; \ - } \ - }; - -template -struct CTypeInfoTraits {}; - -#define DEFINE_TYPE_INFO_TRAITS(CType, Enum) \ - template <> \ - struct CTypeInfoTraits { \ - using ctype = CType; \ - }; - -#define PRIMITIVE_C_TYPES(V) \ - V(bool, kBool) \ - V(uint8_t, kUint8) \ - V(int32_t, kInt32) \ - V(uint32_t, kUint32) \ - V(int64_t, kInt64) \ - V(uint64_t, kUint64) \ - V(float, kFloat32) \ - V(double, kFloat64) \ - V(void*, kPointer) - -// Same as above, but includes deprecated types for compatibility. -#define ALL_C_TYPES(V) \ - PRIMITIVE_C_TYPES(V) \ - V(void, kVoid) \ - V(v8::Local, kV8Value) \ - V(v8::Local, kV8Value) \ - V(AnyCType, kAny) - -// ApiObject was a temporary solution to wrap the pointer to the v8::Value. -// Please use v8::Local in new code for the arguments and -// v8::Local for the receiver, as ApiObject will be deprecated. - -ALL_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR) -PRIMITIVE_C_TYPES(DEFINE_TYPE_INFO_TRAITS) - -#undef PRIMITIVE_C_TYPES -#undef ALL_C_TYPES - -#define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA(T, Enum) \ - template <> \ - struct TypeInfoHelper&> { \ - static constexpr CTypeInfo::Flags Flags() { \ - return CTypeInfo::Flags::kNone; \ - } \ - \ - static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \ - static constexpr CTypeInfo::SequenceType SequenceType() { \ - return CTypeInfo::SequenceType::kIsTypedArray; \ - } \ - }; - -#define TYPED_ARRAY_C_TYPES(V) \ - V(uint8_t, kUint8) \ - V(int32_t, kInt32) \ - V(uint32_t, kUint32) \ - V(int64_t, kInt64) \ - V(uint64_t, kUint64) \ - V(float, kFloat32) \ - V(double, kFloat64) - -TYPED_ARRAY_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA) - -#undef TYPED_ARRAY_C_TYPES - -template <> -struct TypeInfoHelper> { - static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } - - static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kVoid; } - static constexpr CTypeInfo::SequenceType SequenceType() { - return CTypeInfo::SequenceType::kIsSequence; - } -}; - -template <> -struct TypeInfoHelper> { - static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } - - static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kUint32; } - static constexpr CTypeInfo::SequenceType SequenceType() { - return CTypeInfo::SequenceType::kIsTypedArray; - } -}; - -template <> -struct TypeInfoHelper { - static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } - - static constexpr CTypeInfo::Type Type() { - return CTypeInfo::kCallbackOptionsType; - } - static constexpr CTypeInfo::SequenceType SequenceType() { - return CTypeInfo::SequenceType::kScalar; - } -}; - -template <> -struct TypeInfoHelper { - static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } - - static constexpr CTypeInfo::Type Type() { - return CTypeInfo::Type::kSeqOneByteString; - } - static constexpr CTypeInfo::SequenceType SequenceType() { - return CTypeInfo::SequenceType::kScalar; - } -}; - -#define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \ - static_assert(((COND) == 0) || (ASSERTION), MSG) - -} // namespace internal - -template -class V8_EXPORT CTypeInfoBuilder { - public: - using BaseType = T; - - static constexpr CTypeInfo Build() { - constexpr CTypeInfo::Flags kFlags = - MergeFlags(internal::TypeInfoHelper::Flags(), Flags...); - constexpr CTypeInfo::Type kType = internal::TypeInfoHelper::Type(); - constexpr CTypeInfo::SequenceType kSequenceType = - internal::TypeInfoHelper::SequenceType(); - - STATIC_ASSERT_IMPLIES( - uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kAllowSharedBit), - (kSequenceType == CTypeInfo::SequenceType::kIsTypedArray || - kSequenceType == CTypeInfo::SequenceType::kIsArrayBuffer), - "kAllowSharedBit is only allowed for TypedArrays and ArrayBuffers."); - STATIC_ASSERT_IMPLIES( - uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kEnforceRangeBit), - CTypeInfo::IsIntegralType(kType), - "kEnforceRangeBit is only allowed for integral types."); - STATIC_ASSERT_IMPLIES( - uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kClampBit), - CTypeInfo::IsIntegralType(kType), - "kClampBit is only allowed for integral types."); - STATIC_ASSERT_IMPLIES( - uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kIsRestrictedBit), - CTypeInfo::IsFloatingPointType(kType), - "kIsRestrictedBit is only allowed for floating point types."); - STATIC_ASSERT_IMPLIES(kSequenceType == CTypeInfo::SequenceType::kIsSequence, - kType == CTypeInfo::Type::kVoid, - "Sequences are only supported from void type."); - STATIC_ASSERT_IMPLIES( - kSequenceType == CTypeInfo::SequenceType::kIsTypedArray, - CTypeInfo::IsPrimitive(kType) || kType == CTypeInfo::Type::kVoid, - "TypedArrays are only supported from primitive types or void."); - - // Return the same type with the merged flags. - return CTypeInfo(internal::TypeInfoHelper::Type(), - internal::TypeInfoHelper::SequenceType(), kFlags); - } - - private: - template - static constexpr CTypeInfo::Flags MergeFlags(CTypeInfo::Flags flags, - Rest... rest) { - return CTypeInfo::Flags(uint8_t(flags) | uint8_t(MergeFlags(rest...))); - } - static constexpr CTypeInfo::Flags MergeFlags() { return CTypeInfo::Flags(0); } -}; - -namespace internal { -template -class CFunctionBuilderWithFunction { - public: - explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {} - - template - constexpr auto Ret() { - return CFunctionBuilderWithFunction< - CTypeInfoBuilder, - ArgBuilders...>(fn_); - } - - template - constexpr auto Arg() { - // Return a copy of the builder with the Nth arg builder merged with - // template parameter pack Flags. - return ArgImpl( - std::make_index_sequence()); - } - - // Provided for testing purposes. - template - auto Patch(Ret (*patching_func)(Args...)) { - static_assert( - sizeof...(Args) == sizeof...(ArgBuilders), - "The patching function must have the same number of arguments."); - fn_ = reinterpret_cast(patching_func); - return *this; - } - - auto Build() { - static CFunctionInfoImpl instance; - return CFunction(fn_, &instance); - } - - private: - template - struct GetArgBuilder; - - // Returns the same ArgBuilder as the one at index N, including its flags. - // Flags in the template parameter pack are ignored. - template - struct GetArgBuilder { - using type = - typename std::tuple_element>::type; - }; - - // Returns an ArgBuilder with the same base type as the one at index N, - // but merges the flags with the flags in the template parameter pack. - template - struct GetArgBuilder { - using type = CTypeInfoBuilder< - typename std::tuple_element>::type::BaseType, - std::tuple_element>::type::Build() - .GetFlags(), - Flags...>; - }; - - // Return a copy of the CFunctionBuilder, but merges the Flags on - // ArgBuilder index N with the new Flags passed in the template parameter - // pack. - template - constexpr auto ArgImpl(std::index_sequence) { - return CFunctionBuilderWithFunction< - RetBuilder, typename GetArgBuilder::type...>(fn_); - } - - const void* fn_; -}; - -class CFunctionBuilder { - public: - constexpr CFunctionBuilder() {} - - template - constexpr auto Fn(R (*fn)(Args...)) { - return CFunctionBuilderWithFunction, - CTypeInfoBuilder...>( - reinterpret_cast(fn)); - } -}; - -} // namespace internal - -// static -template -CFunction CFunction::ArgUnwrap::Make(R (*func)(Args...)) { - return internal::CFunctionBuilder().Fn(func).Build(); -} - -using CFunctionBuilder = internal::CFunctionBuilder; - -static constexpr CTypeInfo kTypeInfoInt32 = CTypeInfo(CTypeInfo::Type::kInt32); -static constexpr CTypeInfo kTypeInfoFloat64 = - CTypeInfo(CTypeInfo::Type::kFloat64); - -/** - * Copies the contents of this JavaScript array to a C++ buffer with - * a given max_length. A CTypeInfo is passed as an argument, - * instructing different rules for conversion (e.g. restricted float/double). - * The element type T of the destination array must match the C type - * corresponding to the CTypeInfo (specified by CTypeInfoTraits). - * If the array length is larger than max_length or the array is of - * unsupported type, the operation will fail, returning false. Generally, an - * array which contains objects, undefined, null or anything not convertible - * to the requested destination type, is considered unsupported. The operation - * returns true on success. `type_info` will be used for conversions. - */ -template -bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer( - Local src, T* dst, uint32_t max_length); - -template <> -bool V8_EXPORT V8_WARN_UNUSED_RESULT -TryToCopyAndConvertArrayToCppBuffer::Build().GetId(), - int32_t>(Local src, int32_t* dst, - uint32_t max_length); - -template <> -bool V8_EXPORT V8_WARN_UNUSED_RESULT -TryToCopyAndConvertArrayToCppBuffer::Build().GetId(), - uint32_t>(Local src, uint32_t* dst, - uint32_t max_length); - -template <> -bool V8_EXPORT V8_WARN_UNUSED_RESULT -TryToCopyAndConvertArrayToCppBuffer::Build().GetId(), - float>(Local src, float* dst, - uint32_t max_length); - -template <> -bool V8_EXPORT V8_WARN_UNUSED_RESULT -TryToCopyAndConvertArrayToCppBuffer::Build().GetId(), - double>(Local src, double* dst, - uint32_t max_length); - -} // namespace v8 - -#endif // INCLUDE_V8_FAST_API_CALLS_H_ diff --git a/javascript/packages/hps/tsconfig.json b/javascript/packages/hps/tsconfig.json deleted file mode 100644 index 176ef55b31..0000000000 --- a/javascript/packages/hps/tsconfig.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "CommonJS", /* Specify what module code is generated. */ - "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - - /* Emit */ - "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, - "include": ["lib/**/*", "index.ts"] -} diff --git a/javascript/test/hps.test.ts b/javascript/test/hps.test.ts deleted file mode 100644 index 8d8bc1bce6..0000000000 --- a/javascript/test/hps.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { isLatin1, stringCopy } from '../packages/hps/index'; -import { describe, expect, test } from '@jest/globals'; - -describe('hps', () => { - test('should isLatin1 work', () => { - for (let index = 0; index < 10000; index++) { - var is = isLatin1("hello"); - expect(is).toBe(true) - - var is = isLatin1("😁"); - expect(is).toBe(false) - } - - }); - - test('should stringCopy work', () => { - for (let index = 0; index < 10000; index++) { - const dist = new Uint8Array(5); - stringCopy("hello", dist, 0); - expect([...dist]).toEqual([104, 101, 108, 108, 111]) - } - }); -}); - - diff --git a/javascript/test/object.test.ts b/javascript/test/object.test.ts index 79e1f7dc9b..d06d43a530 100644 --- a/javascript/test/object.test.ts +++ b/javascript/test/object.test.ts @@ -219,13 +219,12 @@ describe('object', () => { }); test("should partial record work", () => { - const hps = undefined; const description = Type.object('ws-channel-protocol', { kind: Type.string(), path: Type.string(), }); - const fury = new Fury({ hps }); + const fury = new Fury({}); const { serialize, deserialize } = fury.registerSerializer(description); const bin = serialize({ kind: "123", diff --git a/licenserc.toml b/licenserc.toml index 39821976f7..534f81a254 100644 --- a/licenserc.toml +++ b/licenserc.toml @@ -54,7 +54,6 @@ excludes = [ "java/fury-core/src/main/java/org/apache/fury/util/Preconditions.java", "java/fury-core/src/test/java/org/apache/fury/type/GenericsTest.java", "java/fury-format/src/main/java/org/apache/fury/format/vectorized/ArrowWriter.java", - "javascript/packages/hps/src/v8-fast-api-calls.h", "javascript/packages/fury/lib/murmurHash3.ts", "cpp/fury/thirdparty/MurmurHash3.*", ] diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..4f2d2250b9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "fury", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}