Remove FFI prototype.
Bug: v8:6867 TBR=ofrobots@google.com Change-Id: I0eaebe04863f4cc9152655fedbeb67225a4d8103 Reviewed-on: https://chromium-review.googlesource.com/691722 Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#48422}
This commit is contained in:
parent
6751db26ac
commit
343cbe955b
2
BUILD.gn
2
BUILD.gn
@ -1585,8 +1585,6 @@ v8_source_set("v8_base") {
|
|||||||
"src/feedback-vector-inl.h",
|
"src/feedback-vector-inl.h",
|
||||||
"src/feedback-vector.cc",
|
"src/feedback-vector.cc",
|
||||||
"src/feedback-vector.h",
|
"src/feedback-vector.h",
|
||||||
"src/ffi/ffi-compiler.cc",
|
|
||||||
"src/ffi/ffi-compiler.h",
|
|
||||||
"src/field-index-inl.h",
|
"src/field-index-inl.h",
|
||||||
"src/field-index.h",
|
"src/field-index.h",
|
||||||
"src/field-type.cc",
|
"src/field-type.cc",
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "src/extensions/ignition-statistics-extension.h"
|
#include "src/extensions/ignition-statistics-extension.h"
|
||||||
#include "src/extensions/statistics-extension.h"
|
#include "src/extensions/statistics-extension.h"
|
||||||
#include "src/extensions/trigger-failure-extension.h"
|
#include "src/extensions/trigger-failure-extension.h"
|
||||||
#include "src/ffi/ffi-compiler.h"
|
|
||||||
#include "src/heap/heap.h"
|
#include "src/heap/heap.h"
|
||||||
#include "src/isolate-inl.h"
|
#include "src/isolate-inl.h"
|
||||||
#include "src/snapshot/natives.h"
|
#include "src/snapshot/natives.h"
|
||||||
@ -4967,8 +4966,6 @@ bool Genesis::InstallSpecialObjects(Handle<Context> native_context) {
|
|||||||
WasmJs::Install(isolate, false);
|
WasmJs::Install(isolate, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallFFIMap(isolate);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
mattloring@google.com
|
|
||||||
ofrobots@google.com
|
|
||||||
|
|
||||||
# COMPONENT: Blink>JavaScript>Compiler
|
|
@ -1,125 +0,0 @@
|
|||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
#include "src/ffi/ffi-compiler.h"
|
|
||||||
#include "src/api.h"
|
|
||||||
#include "src/code-factory.h"
|
|
||||||
#include "src/objects-inl.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
void InstallFFIMap(Isolate* isolate) {
|
|
||||||
Handle<Context> context(isolate->context());
|
|
||||||
DCHECK(!context->get(Context::NATIVE_FUNCTION_MAP_INDEX)->IsMap());
|
|
||||||
Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate);
|
|
||||||
|
|
||||||
InstanceType instance_type = prev_map->instance_type();
|
|
||||||
int embedder_fields = JSObject::GetEmbedderFieldCount(*prev_map);
|
|
||||||
CHECK_EQ(0, embedder_fields);
|
|
||||||
int pre_allocated =
|
|
||||||
prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
|
|
||||||
int instance_size;
|
|
||||||
int in_object_properties;
|
|
||||||
JSFunction::CalculateInstanceSizeHelper(
|
|
||||||
instance_type, embedder_fields, 0, &instance_size, &in_object_properties);
|
|
||||||
int unused_property_fields = in_object_properties - pre_allocated;
|
|
||||||
Handle<Map> map = Map::CopyInitialMap(
|
|
||||||
prev_map, instance_size, in_object_properties, unused_property_fields);
|
|
||||||
context->set_native_function_map(*map);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ffi {
|
|
||||||
|
|
||||||
class FFIAssembler : public CodeStubAssembler {
|
|
||||||
public:
|
|
||||||
explicit FFIAssembler(CodeAssemblerState* state) : CodeStubAssembler(state) {}
|
|
||||||
|
|
||||||
Node* ToJS(Node* node, Node* context, FFIType type) {
|
|
||||||
switch (type) {
|
|
||||||
case FFIType::kInt32:
|
|
||||||
return ChangeInt32ToTagged(node);
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* FromJS(Node* node, Node* context, FFIType type) {
|
|
||||||
switch (type) {
|
|
||||||
case FFIType::kInt32:
|
|
||||||
return TruncateTaggedToWord32(context, node);
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
MachineType FFIToMachineType(FFIType type) {
|
|
||||||
switch (type) {
|
|
||||||
case FFIType::kInt32:
|
|
||||||
return MachineType::Int32();
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
Signature<MachineType>* FFIToMachineSignature(FFISignature* sig) {
|
|
||||||
Signature<MachineType>::Builder sig_builder(zone(), sig->return_count(),
|
|
||||||
sig->parameter_count());
|
|
||||||
for (size_t i = 0; i < sig->return_count(); i++) {
|
|
||||||
sig_builder.AddReturn(FFIToMachineType(sig->GetReturn(i)));
|
|
||||||
}
|
|
||||||
for (size_t j = 0; j < sig->parameter_count(); j++) {
|
|
||||||
sig_builder.AddParam(FFIToMachineType(sig->GetParam(j)));
|
|
||||||
}
|
|
||||||
return sig_builder.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateJSToNativeWrapper(NativeFunction* func) {
|
|
||||||
int params = static_cast<int>(func->sig->parameter_count());
|
|
||||||
int returns = static_cast<int>(func->sig->return_count());
|
|
||||||
ApiFunction api_func(func->start);
|
|
||||||
ExternalReference ref(&api_func, ExternalReference::BUILTIN_CALL,
|
|
||||||
isolate());
|
|
||||||
|
|
||||||
Node* context_param = GetJSContextParameter();
|
|
||||||
|
|
||||||
Node** inputs = zone()->NewArray<Node*>(params + 1);
|
|
||||||
int input_count = 0;
|
|
||||||
inputs[input_count++] = ExternalConstant(ref);
|
|
||||||
for (int i = 0; i < params; i++) {
|
|
||||||
inputs[input_count++] =
|
|
||||||
FromJS(Parameter(i), context_param, func->sig->GetParam(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* call =
|
|
||||||
CallCFunctionN(FFIToMachineSignature(func->sig), input_count, inputs);
|
|
||||||
Node* return_val = UndefinedConstant();
|
|
||||||
if (returns == 1) {
|
|
||||||
return_val = ToJS(call, context_param, func->sig->GetReturn());
|
|
||||||
}
|
|
||||||
Return(return_val);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Handle<JSFunction> CompileJSToNativeWrapper(Isolate* isolate,
|
|
||||||
Handle<String> name,
|
|
||||||
NativeFunction func) {
|
|
||||||
int params = static_cast<int>(func.sig->parameter_count());
|
|
||||||
Zone zone(isolate->allocator(), ZONE_NAME);
|
|
||||||
CodeAssemblerState state(isolate, &zone, params, Code::BUILTIN,
|
|
||||||
"js-to-native");
|
|
||||||
FFIAssembler assembler(&state);
|
|
||||||
assembler.GenerateJSToNativeWrapper(&func);
|
|
||||||
Handle<Code> code = assembler.GenerateCode(&state);
|
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> shared =
|
|
||||||
isolate->factory()->NewSharedFunctionInfo(name, code, false);
|
|
||||||
shared->set_length(params);
|
|
||||||
shared->set_internal_formal_parameter_count(params);
|
|
||||||
Handle<JSFunction> function = isolate->factory()->NewFunction(
|
|
||||||
isolate->native_function_map(), name, code);
|
|
||||||
function->set_shared(*shared);
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ffi
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace v8
|
|
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
#ifndef SRC_FFI_FFI_COMPILER_H_
|
|
||||||
#define SRC_FFI_FFI_COMPILER_H_
|
|
||||||
|
|
||||||
#include "src/code-stub-assembler.h"
|
|
||||||
#include "src/machine-type.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
typedef compiler::Node Node;
|
|
||||||
typedef compiler::CodeAssemblerState CodeAssemblerState;
|
|
||||||
|
|
||||||
void InstallFFIMap(Isolate* isolate);
|
|
||||||
|
|
||||||
namespace ffi {
|
|
||||||
|
|
||||||
enum class FFIType : uint8_t { kInt32 };
|
|
||||||
|
|
||||||
typedef Signature<FFIType> FFISignature;
|
|
||||||
|
|
||||||
struct NativeFunction {
|
|
||||||
FFISignature* sig;
|
|
||||||
uint8_t* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
Handle<JSFunction> CompileJSToNativeWrapper(Isolate* isolate,
|
|
||||||
Handle<String> name,
|
|
||||||
NativeFunction func);
|
|
||||||
} // namespace ffi
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace v8
|
|
||||||
|
|
||||||
#endif // SRC_FFI_FFI_COMPILER_H_
|
|
@ -968,8 +968,6 @@
|
|||||||
'feedback-vector-inl.h',
|
'feedback-vector-inl.h',
|
||||||
'feedback-vector.cc',
|
'feedback-vector.cc',
|
||||||
'feedback-vector.h',
|
'feedback-vector.h',
|
||||||
'ffi/ffi-compiler.cc',
|
|
||||||
'ffi/ffi-compiler.h',
|
|
||||||
'field-index.h',
|
'field-index.h',
|
||||||
'field-index-inl.h',
|
'field-index-inl.h',
|
||||||
'field-type.cc',
|
'field-type.cc',
|
||||||
|
@ -89,7 +89,6 @@ v8_source_set("cctest_sources") {
|
|||||||
"compiler/test-run-wasm-machops.cc",
|
"compiler/test-run-wasm-machops.cc",
|
||||||
"compiler/value-helper.h",
|
"compiler/value-helper.h",
|
||||||
"expression-type-collector-macros.h",
|
"expression-type-collector-macros.h",
|
||||||
"ffi/test-ffi.cc",
|
|
||||||
"gay-fixed.cc",
|
"gay-fixed.cc",
|
||||||
"gay-fixed.h",
|
"gay-fixed.h",
|
||||||
"gay-precision.cc",
|
"gay-precision.cc",
|
||||||
|
@ -79,7 +79,6 @@
|
|||||||
'cctest.cc',
|
'cctest.cc',
|
||||||
'cctest.h',
|
'cctest.h',
|
||||||
'expression-type-collector-macros.h',
|
'expression-type-collector-macros.h',
|
||||||
'ffi/test-ffi.cc',
|
|
||||||
'gay-fixed.cc',
|
'gay-fixed.cc',
|
||||||
'gay-fixed.h',
|
'gay-fixed.h',
|
||||||
'gay-precision.cc',
|
'gay-precision.cc',
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
mattloring@google.com
|
|
||||||
ofrobots@google.com
|
|
||||||
|
|
||||||
# COMPONENT: Blink>JavaScript>Compiler
|
|
@ -1,222 +0,0 @@
|
|||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
#include "src/api.h"
|
|
||||||
#include "src/codegen.h"
|
|
||||||
#include "src/ffi/ffi-compiler.h"
|
|
||||||
#include "src/objects-inl.h"
|
|
||||||
#include "test/cctest/cctest.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
namespace internal {
|
|
||||||
namespace ffi {
|
|
||||||
|
|
||||||
static void hello_world() { printf("hello world from native code\n"); }
|
|
||||||
|
|
||||||
TEST(Run_FFI_Hello) {
|
|
||||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
|
|
||||||
Handle<String> name =
|
|
||||||
isolate->factory()->InternalizeUtf8String("hello_world");
|
|
||||||
Handle<Object> undefined = isolate->factory()->undefined_value();
|
|
||||||
|
|
||||||
AccountingAllocator allocator;
|
|
||||||
Zone zone(&allocator, ZONE_NAME);
|
|
||||||
FFISignature::Builder sig_builder(&zone, 0, 0);
|
|
||||||
NativeFunction func = {sig_builder.Build(),
|
|
||||||
reinterpret_cast<uint8_t*>(hello_world)};
|
|
||||||
|
|
||||||
Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func);
|
|
||||||
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, 0, nullptr).ToHandleChecked();
|
|
||||||
|
|
||||||
CHECK(result->IsUndefined(isolate));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int add2(int x, int y) { return x + y; }
|
|
||||||
|
|
||||||
TEST(Run_FFI_add2) {
|
|
||||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
|
|
||||||
Handle<String> name = isolate->factory()->InternalizeUtf8String("add2");
|
|
||||||
Handle<Object> undefined = isolate->factory()->undefined_value();
|
|
||||||
|
|
||||||
AccountingAllocator allocator;
|
|
||||||
Zone zone(&allocator, ZONE_NAME);
|
|
||||||
FFISignature::Builder sig_builder(&zone, 1, 2);
|
|
||||||
sig_builder.AddReturn(FFIType::kInt32);
|
|
||||||
sig_builder.AddParam(FFIType::kInt32);
|
|
||||||
sig_builder.AddParam(FFIType::kInt32);
|
|
||||||
NativeFunction func = {sig_builder.Build(), reinterpret_cast<uint8_t*>(add2)};
|
|
||||||
|
|
||||||
Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func);
|
|
||||||
|
|
||||||
// Simple math should work.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->NewNumber(1.0),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(42.0, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate floating point to integer.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->NewNumber(1.9),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(42.0, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// INT_MAX + 1 should wrap.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->NewNumber(kMaxInt),
|
|
||||||
isolate->factory()->NewNumber(1)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(kMinInt, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// INT_MIN + -1 should wrap.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->NewNumber(kMinInt),
|
|
||||||
isolate->factory()->NewNumber(-1)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(kMaxInt, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Numbers get truncated to the 32 least significant bits.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->NewNumber(1ull << 40),
|
|
||||||
isolate->factory()->NewNumber(-1)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(-1, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// String '57' converts to 57.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {
|
|
||||||
isolate->factory()->NewStringFromAsciiChecked("57"),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(98.0, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// String 'foo' converts to 0.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {
|
|
||||||
isolate->factory()->NewStringFromAsciiChecked("foo"),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(41.0, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// String '58o' converts to 0.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {
|
|
||||||
isolate->factory()->NewStringFromAsciiChecked("58o"),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(41.0, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// NaN converts to 0.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->nan_value(),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(41.0, result->Number());
|
|
||||||
}
|
|
||||||
|
|
||||||
// null converts to 0.
|
|
||||||
{
|
|
||||||
Handle<Object> args[] = {isolate->factory()->null_value(),
|
|
||||||
isolate->factory()->NewNumber(41.0)};
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(41.0, result->Number());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int add6(int a, int b, int c, int d, int e, int f) {
|
|
||||||
return a + b + c + d + e + f;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Run_FFI_add6) {
|
|
||||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
|
|
||||||
Handle<String> name = isolate->factory()->InternalizeUtf8String("add6");
|
|
||||||
Handle<Object> undefined = isolate->factory()->undefined_value();
|
|
||||||
|
|
||||||
AccountingAllocator allocator;
|
|
||||||
Zone zone(&allocator, ZONE_NAME);
|
|
||||||
FFISignature::Builder sig_builder(&zone, 1, 7);
|
|
||||||
sig_builder.AddReturn(FFIType::kInt32);
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
sig_builder.AddParam(FFIType::kInt32);
|
|
||||||
}
|
|
||||||
NativeFunction func = {sig_builder.Build(), reinterpret_cast<uint8_t*>(add6)};
|
|
||||||
|
|
||||||
Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func);
|
|
||||||
Handle<Object> args[] = {
|
|
||||||
isolate->factory()->NewNumber(1), isolate->factory()->NewNumber(2),
|
|
||||||
isolate->factory()->NewNumber(3), isolate->factory()->NewNumber(4),
|
|
||||||
isolate->factory()->NewNumber(5), isolate->factory()->NewNumber(6)};
|
|
||||||
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
|
|
||||||
CHECK_EQ(21.0, result->Number());
|
|
||||||
|
|
||||||
{
|
|
||||||
// Ensure builtin frames are generated
|
|
||||||
FLAG_allow_natives_syntax = true;
|
|
||||||
v8::Local<v8::Value> res = CompileRun(
|
|
||||||
"var o = { valueOf: function() { %DebugTrace(); return 1; } }; o;");
|
|
||||||
Handle<JSReceiver> param(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
|
|
||||||
Handle<Object> args[] = {param,
|
|
||||||
isolate->factory()->NewNumber(2),
|
|
||||||
isolate->factory()->NewNumber(3),
|
|
||||||
isolate->factory()->NewNumber(4),
|
|
||||||
isolate->factory()->NewNumber(5),
|
|
||||||
isolate->factory()->NewNumber(6),
|
|
||||||
isolate->factory()->NewNumber(21)};
|
|
||||||
|
|
||||||
Handle<Object> result =
|
|
||||||
Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
|
||||||
.ToHandleChecked();
|
|
||||||
CHECK_EQ(21.0, result->Number());
|
|
||||||
CHECK_EQ(
|
|
||||||
1.0,
|
|
||||||
res->NumberValue(
|
|
||||||
reinterpret_cast<v8::Isolate*>(isolate)->GetCurrentContext())
|
|
||||||
.ToChecked());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ffi
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace v8
|
|
Loading…
Reference in New Issue
Block a user