зеркало из https://github.com/microsoft/v8-jsi.git
Fix JSI implementation to pass unit tests. Include windbg extension (#28)
* Fix JSI implementation to pass unit tests. Include windbg extension * Add support for Symbol * Don't try to run ARM unit tests * Don't build debug extension in uwp * pipeline syntax * You can't use parameters in conditions * yaml syntax * timeout * Add a debug line * Try a separate boolean parameter
This commit is contained in:
Родитель
2ad32e83e8
Коммит
ca521942e8
|
@ -1,6 +1,11 @@
|
|||
parameters:
|
||||
outputPath:
|
||||
appPlatform:
|
||||
- name: runUnitTests
|
||||
default: true
|
||||
type: boolean
|
||||
- name: appPlatform
|
||||
type: string
|
||||
- name: outputPath
|
||||
type: string
|
||||
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
|
@ -34,6 +39,27 @@ steps:
|
|||
-Configuration:$(BuildConfiguration)
|
||||
-AppPlatform:${{parameters.appPlatform}}
|
||||
|
||||
- powershell: |
|
||||
Write-Host "##vso[task.setvariable variable=GoogleTestAdapterPath]$((Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\" -Recurse -Include GoogleTestAdapter.Core.dll).Directory.FullName)"
|
||||
Write-Host "Set environment variable to ($env:GoogleTestAdapterPath)"
|
||||
displayName: Set GoogleTestAdapterPath
|
||||
|
||||
- task: VSTest@2
|
||||
displayName: Run Unit Tests
|
||||
timeoutInMinutes: 2
|
||||
inputs:
|
||||
testSelector: testAssemblies
|
||||
testAssemblyVer2: jsitests.exe
|
||||
pathtoCustomTestAdapters: $(GoogleTestAdapterPath)
|
||||
searchFolder: $(Build.SourcesDirectory)/build/v8build/v8/out/${{parameters.appPlatform}}/$(BuildPlatform)/$(BuildConfiguration)
|
||||
runTestsInIsolation: true
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
publishRunAttachments: true
|
||||
collectDumpOn: onAbortOnly
|
||||
vsTestVersion: latest
|
||||
condition: and(succeeded(), not(startsWith(variables.BuildPlatform, 'arm')), eq('${{ parameters.runUnitTests }}', true))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: "Publish artifacts"
|
||||
inputs:
|
||||
|
|
|
@ -13,7 +13,7 @@ pool:
|
|||
|
||||
jobs:
|
||||
- job: V8JsiBuild
|
||||
timeoutInMinutes: 150
|
||||
timeoutInMinutes: 180
|
||||
displayName: Build the UWP v8jsi.dll binary for supported architectures and flavors
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -52,6 +52,7 @@ jobs:
|
|||
parameters:
|
||||
outputPath: $(Build.ArtifactStagingDirectory)
|
||||
appPlatform: $(AppPlatform)
|
||||
runUnitTests: false
|
||||
|
||||
- job: V8JsiPublishNuget
|
||||
dependsOn:
|
||||
|
|
|
@ -52,6 +52,7 @@ jobs:
|
|||
parameters:
|
||||
outputPath: $(Build.ArtifactStagingDirectory)
|
||||
appPlatform: $(AppPlatform)
|
||||
runUnitTests: true
|
||||
|
||||
- job: V8JsiPublishNuget
|
||||
dependsOn:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"version": "0.64.2",
|
||||
"version": "0.64.3",
|
||||
"v8ref": "refs/branch-heads/8.5"
|
||||
}
|
|
@ -69,7 +69,13 @@ if (!$?) {
|
|||
# We'll use 2x the number of cores for parallel execution
|
||||
$numberOfThreads = [int]((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors) * 2
|
||||
|
||||
& ninja -v -j $numberOfThreads -C $buildoutput v8jsi jsitests | Tee-Object -FilePath "$SourcesPath\build.log"
|
||||
$ninjaExtraTargets = ""
|
||||
|
||||
if ($AppPlatform -ne "uwp") {
|
||||
$ninjaExtraTargets += "v8windbg"
|
||||
}
|
||||
|
||||
& ninja -v -j $numberOfThreads -C $buildoutput v8jsi jsitests $ninjaExtraTargets | Tee-Object -FilePath "$SourcesPath\build.log"
|
||||
if (!$?) {
|
||||
Write-Host "Build failure, check logs for details"
|
||||
exit 1
|
||||
|
@ -107,6 +113,11 @@ if (!$PSVersionTable.Platform -or $IsWindows) {
|
|||
} else {
|
||||
Copy-Item "$buildoutput\v8jsi.dll.pdb" -Destination "$OutputPath\lib\$AppPlatform\$Configuration\$Platform"
|
||||
}
|
||||
|
||||
# Debugging extension
|
||||
if ($AppPlatform -ne "uwp") {
|
||||
Copy-Item "$buildoutput\v8windbg.dll" -Destination "$OutputPath\lib\$AppPlatform\$Configuration\$Platform"
|
||||
}
|
||||
}
|
||||
else {
|
||||
#TODO (#2): .so
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
diff --git a/BUILD.gn b/BUILD.gn
|
||||
index 167e63503c..6ea5beaa99 100644
|
||||
index 65d137cbed..56b1bd6779 100644
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -3902,11 +3902,18 @@ v8_component("v8_libbase") {
|
||||
@@ -3985,11 +3985,18 @@ v8_component("v8_libbase") {
|
||||
|
||||
defines += [ "_CRT_RAND_S" ] # for rand_s()
|
||||
|
||||
|
@ -26,7 +26,7 @@ index 167e63503c..6ea5beaa99 100644
|
|||
|
||||
data_deps += [ "//build/win:runtime_libs" ]
|
||||
}
|
||||
@@ -5068,3 +5075,9 @@ if (!build_with_chromium && v8_use_perfetto) {
|
||||
@@ -5208,3 +5215,9 @@ if (!build_with_chromium && v8_use_perfetto) {
|
||||
]
|
||||
}
|
||||
} # if (!build_with_chromium && v8_use_perfetto)
|
||||
|
@ -38,10 +38,10 @@ index 167e63503c..6ea5beaa99 100644
|
|||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/DEPS b/DEPS
|
||||
index 7b38c3dcd0..494a187ed9 100644
|
||||
index 4c02904d70..87ac0c20e0 100644
|
||||
--- a/DEPS
|
||||
+++ b/DEPS
|
||||
@@ -540,4 +540,15 @@ hooks = [
|
||||
@@ -549,4 +549,15 @@ hooks = [
|
||||
'v8/tools/generate-header-include-checks.py',
|
||||
],
|
||||
},
|
||||
|
@ -72,10 +72,10 @@ index b5fb1823b3..b5ddc1aba2 100644
|
|||
# This is a cross-compile from an x64 host to either a non-Intel target
|
||||
# cpu or a different target OS. Clang will always be used by default on the
|
||||
diff --git a/include/v8.h b/include/v8.h
|
||||
index 18d72f1630..fc47f43d1f 100644
|
||||
index 13b40db28e..65335f4047 100644
|
||||
--- a/include/v8.h
|
||||
+++ b/include/v8.h
|
||||
@@ -9068,6 +9068,11 @@ class V8_EXPORT Isolate {
|
||||
@@ -9089,6 +9089,11 @@ class V8_EXPORT Isolate {
|
||||
*/
|
||||
MicrotasksPolicy GetMicrotasksPolicy() const;
|
||||
|
||||
|
@ -87,7 +87,7 @@ index 18d72f1630..fc47f43d1f 100644
|
|||
/**
|
||||
* Adds a callback to notify the host application after
|
||||
* microtasks were run on the default MicrotaskQueue. The callback is
|
||||
@@ -9094,6 +9099,10 @@ class V8_EXPORT Isolate {
|
||||
@@ -9115,6 +9120,10 @@ class V8_EXPORT Isolate {
|
||||
void RemoveMicrotasksCompletedCallback(
|
||||
MicrotasksCompletedCallbackWithData callback, void* data = nullptr);
|
||||
|
||||
|
@ -227,3 +227,16 @@ index 12dfaf9572..b16b0b0020 100644
|
|||
}
|
||||
|
||||
v8::PageAllocator* SetPlatformPageAllocatorForTesting(
|
||||
diff --git a/tools/debug_helper/get-object-properties.cc b/tools/debug_helper/get-object-properties.cc
|
||||
index 0e8fbf02a6..9eaf2ab7d3 100644
|
||||
--- a/tools/debug_helper/get-object-properties.cc
|
||||
+++ b/tools/debug_helper/get-object-properties.cc
|
||||
@@ -331,7 +331,7 @@ class ReadStringVisitor : public TqObjectVisitor {
|
||||
Isolate::FromRoot(GetIsolateRoot(heap_addresses_.any_heap_pointer)),
|
||||
resource_data));
|
||||
#else
|
||||
- uintptr_t data_address = reinterpret_cast<uintptr_t>(resource_data);
|
||||
+ uintptr_t data_address = static_cast<uintptr_t>(resource_data);
|
||||
#endif // V8_COMPRESS_POINTERS
|
||||
if (done_) return;
|
||||
ReadStringCharacters<TChar>(object, data_address);
|
||||
|
|
|
@ -514,6 +514,10 @@ void V8Runtime::createHostObjectConstructorPerContext() {
|
|||
nullptr,
|
||||
nullptr,
|
||||
HostObjectProxy::Enumerator));
|
||||
|
||||
// V8 distinguishes between named properties (strings and symbols) and indexed properties (number)
|
||||
// Note that we're not passing an Enumerator here, otherwise we'd be double-counting since JSI doesn't make the distinction
|
||||
hostObjectTemplate->SetIndexedPropertyHandler(HostObjectProxy::GetIndexed, HostObjectProxy::SetIndexed);
|
||||
hostObjectTemplate->SetInternalFieldCount(1);
|
||||
host_object_constructor_.Reset(
|
||||
isolate_,
|
||||
|
@ -539,9 +543,6 @@ void V8Runtime::initializeV8() {
|
|||
|
||||
int argc = static_cast<int>(argv.size());
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, const_cast<char **>(&argv[0]), false);
|
||||
|
||||
// Assuming Initialize can be called multiple times in process.
|
||||
v8::V8::Initialize();
|
||||
}
|
||||
|
||||
V8Runtime::V8Runtime(V8RuntimeArgs &&args) : args_(std::move(args)) {
|
||||
|
@ -637,23 +638,6 @@ jsi::Value V8Runtime::evaluateJavaScript(
|
|||
return result;
|
||||
}
|
||||
|
||||
v8::Local<v8::Script> V8Runtime::GetCompiledScript(
|
||||
const v8::Local<v8::String> &source,
|
||||
const std::string &sourceURL) {
|
||||
v8::Isolate *isolate = GetIsolate();
|
||||
v8::TryCatch try_catch(isolate);
|
||||
v8::MaybeLocal<v8::String> name = v8::String::NewFromUtf8(
|
||||
isolate, reinterpret_cast<const char *>(sourceURL.c_str()));
|
||||
v8::ScriptOrigin origin(name.ToLocalChecked());
|
||||
v8::Local<v8::Context> context(isolate->GetCurrentContext());
|
||||
|
||||
v8::Local<v8::Script> script;
|
||||
if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) {
|
||||
ReportException(&try_catch);
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
// The callback that is invoked by v8 whenever the JavaScript 'print'
|
||||
// function is called. Prints its arguments on stdout separated by
|
||||
// spaces and ending with a newline.
|
||||
|
@ -713,8 +697,6 @@ class ByteArrayBuffer final : public jsi::Buffer {
|
|||
jsi::Value V8Runtime::ExecuteString(
|
||||
const v8::Local<v8::String> &source,
|
||||
const std::string &sourceURL) {
|
||||
// jsi::Value V8Runtime::ExecuteString(v8::Local<v8::String> source, const
|
||||
// jsi::Buffer* cache, v8::Local<v8::Value> name, bool report_exceptions) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
v8::TryCatch try_catch(isolate);
|
||||
|
||||
|
@ -789,35 +771,101 @@ jsi::Value V8Runtime::ExecuteString(
|
|||
}
|
||||
}
|
||||
|
||||
class V8PreparedJavaScript : public facebook::jsi::PreparedJavaScript {
|
||||
public:
|
||||
jsi::ScriptSignature scriptSignature;
|
||||
jsi::JSRuntimeSignature runtimeSignature;
|
||||
std::vector<uint8_t> buffer;
|
||||
|
||||
// What's the point of bytecode if we need to preserve the full source too?
|
||||
// TODO: Figure out if there's a way to use the bytecode only with V8
|
||||
std::shared_ptr<const facebook::jsi::Buffer> sourceBuffer;
|
||||
};
|
||||
|
||||
std::shared_ptr<const facebook::jsi::PreparedJavaScript>
|
||||
V8Runtime::prepareJavaScript(
|
||||
const std::shared_ptr<const facebook::jsi::Buffer> &,
|
||||
std::string) {
|
||||
throw jsi::JSINativeException(
|
||||
"V8Runtime::prepareJavaScript is not implemented!");
|
||||
V8Runtime::prepareJavaScript(const std::shared_ptr<const facebook::jsi::Buffer> &buffer, std::string sourceURL) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
v8::TryCatch try_catch(isolate);
|
||||
v8::Local<v8::String> source;
|
||||
if (!v8::String::NewFromUtf8(isolate, reinterpret_cast<const char *>(buffer->data()),
|
||||
v8::NewStringType::kNormal, static_cast<int>(buffer->size())).ToLocal(&source)) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
v8::Local<v8::String> urlV8String = v8::String::NewFromUtf8(isolate, reinterpret_cast<const char *>(sourceURL.c_str())).ToLocalChecked();
|
||||
v8::ScriptOrigin origin(urlV8String);
|
||||
v8::Local<v8::Context> context(isolate->GetCurrentContext());
|
||||
v8::Local<v8::Script> script;
|
||||
v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::CompileOptions::kNoCompileOptions;
|
||||
v8::ScriptCompiler::CachedData *cached_data = nullptr;
|
||||
|
||||
v8::ScriptCompiler::Source script_source(source, origin, cached_data);
|
||||
|
||||
if (!v8::ScriptCompiler::Compile(context, &script_source, options).ToLocal(&script)) {
|
||||
ReportException(&try_catch);
|
||||
return nullptr;
|
||||
} else {
|
||||
v8::ScriptCompiler::CachedData *codeCache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
|
||||
|
||||
auto prepared = std::make_shared<V8PreparedJavaScript>();
|
||||
prepared->scriptSignature = {sourceURL, 1};
|
||||
prepared->runtimeSignature = {"V8", 76};
|
||||
prepared->buffer.assign(codeCache->data, codeCache->data + codeCache->length);
|
||||
prepared->sourceBuffer = buffer;
|
||||
return prepared;
|
||||
}
|
||||
}
|
||||
|
||||
facebook::jsi::Value V8Runtime::evaluatePreparedJavaScript(
|
||||
const std::shared_ptr<const facebook::jsi::PreparedJavaScript> &) {
|
||||
throw jsi::JSINativeException(
|
||||
"V8Runtime::evaluatePreparedJavaScript is not implemented!");
|
||||
facebook::jsi::Value V8Runtime::evaluatePreparedJavaScript(const std::shared_ptr<const facebook::jsi::PreparedJavaScript> & js) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
|
||||
auto prepared = static_cast<const V8PreparedJavaScript*>(js.get());
|
||||
|
||||
v8::TryCatch try_catch(isolate);
|
||||
v8::Local<v8::String> source;
|
||||
if (!v8::String::NewFromUtf8(isolate, reinterpret_cast<const char *>(prepared->sourceBuffer->data()),
|
||||
v8::NewStringType::kNormal, static_cast<int>(prepared->sourceBuffer->size())).ToLocal(&source)) {
|
||||
std::abort();
|
||||
}
|
||||
v8::Local<v8::String> urlV8String = v8::String::NewFromUtf8(isolate, reinterpret_cast<const char *>(prepared->scriptSignature.url.c_str())).ToLocalChecked();
|
||||
v8::ScriptOrigin origin(urlV8String);
|
||||
v8::Local<v8::Context> context(isolate->GetCurrentContext());
|
||||
v8::Local<v8::Script> script;
|
||||
|
||||
v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::CompileOptions::kConsumeCodeCache;
|
||||
v8::ScriptCompiler::CachedData *cached_data = new v8::ScriptCompiler::CachedData(prepared->buffer.data(), static_cast<int>(prepared->buffer.size()));
|
||||
|
||||
v8::ScriptCompiler::Source script_source(source, origin, cached_data);
|
||||
|
||||
if (!v8::ScriptCompiler::Compile(context, &script_source, options).ToLocal(&script)) {
|
||||
ReportException(&try_catch);
|
||||
return createValue(v8::Undefined(GetIsolate()));
|
||||
} else {
|
||||
v8::Local<v8::Value> result;
|
||||
if (!script->Run(context).ToLocal(&result)) {
|
||||
assert(try_catch.HasCaught());
|
||||
ReportException(&try_catch);
|
||||
return createValue(v8::Undefined(GetIsolate()));
|
||||
} else {
|
||||
assert(!try_catch.HasCaught());
|
||||
return createValue(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V8Runtime::ReportException(v8::TryCatch *try_catch) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
v8::String::Utf8Value exception(isolate, try_catch->Exception());
|
||||
const char *exception_string = ToCString(exception);
|
||||
v8::Local<v8::Message> message = try_catch->Message();
|
||||
if (message.IsEmpty()) {
|
||||
// V8 didn't provide any extra information about this error; just
|
||||
// throw the exception.
|
||||
throw jsi::JSError(*this, "<Unknown exception>");
|
||||
v8::String::Utf8Value exception(isolate, try_catch->Exception());
|
||||
throw jsi::JSError(*this, ToCString(exception));
|
||||
} else {
|
||||
// Print (filename):(line number): (message).
|
||||
|
||||
std::stringstream sstr;
|
||||
|
||||
v8::String::Utf8Value filename(
|
||||
|
||||
// Print (filename):(line number): (message) - this would differ from what JSI expects (it wants the plain stacktrace)
|
||||
/*v8::String::Utf8Value filename(
|
||||
isolate, message->GetScriptOrigin().ResourceName());
|
||||
v8::Local<v8::Context> context(isolate->GetCurrentContext());
|
||||
const char *filename_string = ToCString(filename);
|
||||
|
@ -825,7 +873,7 @@ void V8Runtime::ReportException(v8::TryCatch *try_catch) {
|
|||
sstr << filename_string << ":" << linenum << ": " << exception_string
|
||||
<< std::endl;
|
||||
|
||||
// Print line of source code.
|
||||
// Print line of source code
|
||||
v8::String::Utf8Value sourceline(
|
||||
isolate, message->GetSourceLine(context).ToLocalChecked());
|
||||
const char *sourceline_string = ToCString(sourceline);
|
||||
|
@ -840,10 +888,10 @@ void V8Runtime::ReportException(v8::TryCatch *try_catch) {
|
|||
for (int i = start; i < end; i++) {
|
||||
sstr << "^";
|
||||
}
|
||||
sstr << std::endl;
|
||||
sstr << std::endl;*/
|
||||
|
||||
v8::Local<v8::Value> stack_trace_string;
|
||||
if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
|
||||
if (try_catch->StackTrace(context_.Get(isolate)).ToLocal(&stack_trace_string) &&
|
||||
stack_trace_string->IsString() &&
|
||||
v8::Local<v8::String>::Cast(stack_trace_string)->Length() > 0) {
|
||||
v8::String::Utf8Value stack_trace(isolate, stack_trace_string);
|
||||
|
@ -851,13 +899,30 @@ void V8Runtime::ReportException(v8::TryCatch *try_catch) {
|
|||
sstr << stack_trace_string2 << std::endl;
|
||||
}
|
||||
|
||||
throw jsi::JSError(*this, sstr.str());
|
||||
v8::String::Utf8Value ex_message(isolate, message->Get());
|
||||
std::string ex_messages = ToCString(ex_message);
|
||||
if (ex_messages.rfind("Uncaught Error:", 0) == 0) {
|
||||
// V8 adds an "Uncaught Error: " before any message string any time we read it, this strips it out.
|
||||
ex_messages.erase(0, 16);
|
||||
}
|
||||
|
||||
// V8 doesn't actually capture the current callstack (as we're outside of scope when this gets called)
|
||||
// See also https://v8.dev/docs/stack-trace-api
|
||||
if (ex_messages.find("Maximum call stack size exceeded") == std::string::npos) {
|
||||
auto err = jsi::JSError(*this, ex_messages);
|
||||
err.value().getObject(*this).setProperty(*this, "stack", facebook::jsi::String::createFromUtf8(*this, sstr.str()));
|
||||
err.setStack(sstr.str());
|
||||
throw err;
|
||||
} else {
|
||||
// If we're already in stack overflow, calling the Error constructor pushes it overboard
|
||||
throw jsi::JSError(*this, ex_messages, sstr.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsi::Object V8Runtime::global() {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return createObject(context_.Get(isolate)->Global());
|
||||
return make<jsi::Object>(V8ObjectValue::make(context_.Get(isolate)->Global()));
|
||||
}
|
||||
|
||||
std::string V8Runtime::description() {
|
||||
|
@ -871,28 +936,6 @@ bool V8Runtime::isInspectable() {
|
|||
return false;
|
||||
}
|
||||
|
||||
V8Runtime::V8StringValue::V8StringValue(v8::Local<v8::String> str)
|
||||
: v8String_(v8::Isolate::GetCurrent(), str) {}
|
||||
|
||||
void V8Runtime::V8StringValue::invalidate() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
V8Runtime::V8StringValue::~V8StringValue() {
|
||||
v8String_.Reset();
|
||||
}
|
||||
|
||||
V8Runtime::V8ObjectValue::V8ObjectValue(v8::Local<v8::Object> obj)
|
||||
: v8Object_(v8::Isolate::GetCurrent(), obj) {}
|
||||
|
||||
void V8Runtime::V8ObjectValue::invalidate() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
V8Runtime::V8ObjectValue::~V8ObjectValue() {
|
||||
v8Object_.Reset();
|
||||
}
|
||||
|
||||
// Shallow clone
|
||||
jsi::Runtime::PointerValue *V8Runtime::cloneString(
|
||||
const jsi::Runtime::PointerValue *pv) {
|
||||
|
@ -902,7 +945,7 @@ jsi::Runtime::PointerValue *V8Runtime::cloneString(
|
|||
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
const V8StringValue *string = static_cast<const V8StringValue *>(pv);
|
||||
return makeStringValue(string->v8String_.Get(GetIsolate()));
|
||||
return V8StringValue::make(string->get(GetIsolate()));
|
||||
}
|
||||
|
||||
jsi::Runtime::PointerValue *V8Runtime::cloneObject(
|
||||
|
@ -913,7 +956,7 @@ jsi::Runtime::PointerValue *V8Runtime::cloneObject(
|
|||
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
const V8ObjectValue *object = static_cast<const V8ObjectValue *>(pv);
|
||||
return makeObjectValue(object->v8Object_.Get(GetIsolate()));
|
||||
return V8ObjectValue::make(object->get(GetIsolate()));
|
||||
}
|
||||
|
||||
jsi::Runtime::PointerValue *V8Runtime::clonePropNameID(
|
||||
|
@ -924,17 +967,23 @@ jsi::Runtime::PointerValue *V8Runtime::clonePropNameID(
|
|||
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
const V8StringValue *string = static_cast<const V8StringValue *>(pv);
|
||||
return makeStringValue(string->v8String_.Get(GetIsolate()));
|
||||
return V8StringValue::make(string->get(GetIsolate()));
|
||||
}
|
||||
|
||||
jsi::Runtime::PointerValue *V8Runtime::cloneSymbol(
|
||||
const jsi::Runtime::PointerValue *) {
|
||||
throw jsi::JSINativeException("V8Runtime::cloneSymbol is not implemented!");
|
||||
const jsi::Runtime::PointerValue *pv) {
|
||||
if (!pv) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
const V8PointerValue<v8::Symbol>* symbol = static_cast<const V8PointerValue<v8::Symbol>*>(pv);
|
||||
return V8PointerValue<v8::Symbol>::make(symbol->get(GetIsolate()));
|
||||
}
|
||||
|
||||
std::string V8Runtime::symbolToString(const jsi::Symbol &) {
|
||||
throw jsi::JSINativeException(
|
||||
"V8Runtime::symbolToString is not implemented!");
|
||||
std::string V8Runtime::symbolToString(const jsi::Symbol &sym) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return "Symbol(" + JSStringToSTLString(GetIsolate(), v8::Local<v8::String>::Cast(symbolRef(sym)->Description())) + ")";
|
||||
}
|
||||
|
||||
jsi::PropNameID V8Runtime::createPropNameIDFromAscii(
|
||||
|
@ -953,7 +1002,8 @@ jsi::PropNameID V8Runtime::createPropNameIDFromAscii(
|
|||
throw jsi::JSError(*this, strstream.str());
|
||||
}
|
||||
|
||||
auto res = createPropNameID(v8String);
|
||||
auto res = make<jsi::PropNameID>(
|
||||
V8StringValue::make(v8::Local<v8::String>::Cast(v8String)));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -973,13 +1023,15 @@ jsi::PropNameID V8Runtime::createPropNameIDFromUtf8(
|
|||
throw jsi::JSError(*this, strstream.str());
|
||||
}
|
||||
|
||||
auto res = createPropNameID(v8String);
|
||||
auto res = make<jsi::PropNameID>(
|
||||
V8StringValue::make(v8::Local<v8::String>::Cast(v8String)));
|
||||
return res;
|
||||
}
|
||||
|
||||
jsi::PropNameID V8Runtime::createPropNameIDFromString(const jsi::String &str) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return createPropNameID(stringRef(str));
|
||||
return make<jsi::PropNameID>(
|
||||
V8StringValue::make(v8::Local<v8::String>::Cast(stringRef(str))));
|
||||
}
|
||||
|
||||
std::string V8Runtime::utf8(const jsi::PropNameID &sym) {
|
||||
|
@ -1012,7 +1064,7 @@ jsi::String V8Runtime::createStringFromUtf8(const uint8_t *str, size_t length) {
|
|||
throw jsi::JSError(*this, "V8 string creation failed.");
|
||||
}
|
||||
|
||||
jsi::String jsistr = createString(v8string);
|
||||
jsi::String jsistr = make<jsi::String>(V8StringValue::make(v8string));
|
||||
return jsistr;
|
||||
}
|
||||
|
||||
|
@ -1023,7 +1075,7 @@ std::string V8Runtime::utf8(const jsi::String &str) {
|
|||
|
||||
jsi::Object V8Runtime::createObject() {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return createObject(v8::Object::New(GetIsolate()));
|
||||
return make<jsi::Object>(V8ObjectValue::make(v8::Object::New(GetIsolate())));
|
||||
}
|
||||
|
||||
jsi::Object V8Runtime::createObject(
|
||||
|
@ -1045,7 +1097,7 @@ jsi::Object V8Runtime::createObject(
|
|||
AddHostObjectLifetimeTracker(std::make_shared<HostObjectLifetimeTracker>(
|
||||
*this, newObject, hostObjectProxy));
|
||||
|
||||
return createObject(newObject);
|
||||
return make<jsi::Object>(V8ObjectValue::make(newObject));
|
||||
}
|
||||
|
||||
std::shared_ptr<jsi::HostObject> V8Runtime::getHostObject(
|
||||
|
@ -1174,8 +1226,13 @@ bool V8Runtime::isHostObject(const jsi::Object &obj) const {
|
|||
jsi::Array V8Runtime::getPropertyNames(const jsi::Object &obj) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
v8::Local<v8::Array> propNames =
|
||||
objectRef(obj)->GetPropertyNames(context_.Get(isolate_)).ToLocalChecked();
|
||||
return createObject(propNames).getArray(*this);
|
||||
objectRef(obj)->GetPropertyNames(
|
||||
context_.Get(isolate_),
|
||||
v8::KeyCollectionMode::kIncludePrototypes,
|
||||
static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS),
|
||||
v8::IndexFilter::kIncludeIndices,
|
||||
v8::KeyConversionMode::kConvertToString).ToLocalChecked();
|
||||
return make<jsi::Object>(V8ObjectValue::make(propNames)).getArray(*this);
|
||||
}
|
||||
|
||||
jsi::WeakObject V8Runtime::createWeakObject(const jsi::Object &) {
|
||||
|
@ -1188,7 +1245,7 @@ jsi::Value V8Runtime::lockWeakObject(jsi::WeakObject &) {
|
|||
|
||||
jsi::Array V8Runtime::createArray(size_t length) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return createObject(v8::Array::New(GetIsolate(), static_cast<int>(length)))
|
||||
return make<jsi::Object>(V8ObjectValue::make(v8::Array::New(GetIsolate(), static_cast<int>(length))))
|
||||
.getArray(*this);
|
||||
}
|
||||
|
||||
|
@ -1228,15 +1285,17 @@ jsi::Function V8Runtime::createFunctionFromHostFunction(
|
|||
HostFunctionProxy::HostFunctionCallback,
|
||||
v8::Local<v8::External>::New(
|
||||
GetIsolate(),
|
||||
v8::External::New(GetIsolate(), hostFunctionProxy)))
|
||||
v8::External::New(GetIsolate(), hostFunctionProxy)), paramCount)
|
||||
.ToLocal(&newFunction)) {
|
||||
throw jsi::JSError(*this, "Creation of HostFunction failed.");
|
||||
}
|
||||
|
||||
newFunction->SetName(v8::Local<v8::String>::Cast(valueRef(name)));
|
||||
|
||||
AddHostObjectLifetimeTracker(std::make_shared<HostObjectLifetimeTracker>(
|
||||
*this, newFunction, hostFunctionProxy));
|
||||
|
||||
return createObject(newFunction).getFunction(*this);
|
||||
return make<jsi::Object>(V8ObjectValue::make(newFunction)).getFunction(*this);
|
||||
}
|
||||
|
||||
bool V8Runtime::isHostFunction(const jsi::Function &obj) const {
|
||||
|
@ -1319,8 +1378,9 @@ bool V8Runtime::strictEquals(const jsi::Object &a, const jsi::Object &b) const {
|
|||
return objectRef(a)->StrictEquals(objectRef(b));
|
||||
}
|
||||
|
||||
bool V8Runtime::strictEquals(const jsi::Symbol &, const jsi::Symbol &) const {
|
||||
throw jsi::JSINativeException("Not implemented!");
|
||||
bool V8Runtime::strictEquals(const jsi::Symbol &a, const jsi::Symbol &b) const {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return symbolRef(a)->StrictEquals(symbolRef(b));
|
||||
}
|
||||
|
||||
bool V8Runtime::instanceOf(const jsi::Object &o, const jsi::Function &f) {
|
||||
|
@ -1330,32 +1390,6 @@ bool V8Runtime::instanceOf(const jsi::Object &o, const jsi::Function &f) {
|
|||
.ToChecked();
|
||||
}
|
||||
|
||||
jsi::Runtime::PointerValue *V8Runtime::makeStringValue(
|
||||
v8::Local<v8::String> string) const {
|
||||
return new V8StringValue(string);
|
||||
}
|
||||
|
||||
jsi::String V8Runtime::createString(v8::Local<v8::String> str) const {
|
||||
return make<jsi::String>(makeStringValue(str));
|
||||
}
|
||||
|
||||
jsi::PropNameID V8Runtime::createPropNameID(v8::Local<v8::Value> str) {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return make<jsi::PropNameID>(
|
||||
makeStringValue(v8::Local<v8::String>::Cast(str)));
|
||||
}
|
||||
|
||||
jsi::Runtime::PointerValue *V8Runtime::makeObjectValue(
|
||||
v8::Local<v8::Object> objectRef) const {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return new V8ObjectValue(objectRef);
|
||||
}
|
||||
|
||||
jsi::Object V8Runtime::createObject(v8::Local<v8::Object> obj) const {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
return make<jsi::Object>(makeObjectValue(obj));
|
||||
}
|
||||
|
||||
jsi::Value V8Runtime::createValue(v8::Local<v8::Value> value) const {
|
||||
_ISOLATE_CONTEXT_ENTER
|
||||
if (value->IsInt32()) {
|
||||
|
@ -1371,13 +1405,13 @@ jsi::Value V8Runtime::createValue(v8::Local<v8::Value> value) const {
|
|||
return jsi::Value();
|
||||
} else if (value.IsEmpty() || value->IsNull()) {
|
||||
return jsi::Value(nullptr);
|
||||
}
|
||||
|
||||
else if (value->IsString()) {
|
||||
} else if (value->IsString()) {
|
||||
// Note :: Non copy create
|
||||
return createString(v8::Local<v8::String>::Cast(value));
|
||||
return make<jsi::String>(V8StringValue::make(v8::Local<v8::String>::Cast(value)));
|
||||
} else if (value->IsObject()) {
|
||||
return createObject(v8::Local<v8::Object>::Cast(value));
|
||||
return make<jsi::Object>(V8ObjectValue::make(v8::Local<v8::Object>::Cast(value)));
|
||||
} else if (value->IsSymbol()) {
|
||||
return make<jsi::Symbol>(V8PointerValue<v8::Symbol>::make(v8::Local<v8::Symbol>::Cast(value)));
|
||||
} else {
|
||||
// What are you?
|
||||
std::abort();
|
||||
|
@ -1400,36 +1434,14 @@ v8::Local<v8::Value> V8Runtime::valueRef(const jsi::Value &value) {
|
|||
return handle_scope.Escape(stringRef(value.asString(*this)));
|
||||
} else if (value.isObject()) {
|
||||
return handle_scope.Escape(objectRef(value.getObject(*this)));
|
||||
} else if (value.isSymbol()) {
|
||||
return handle_scope.Escape(symbolRef(value.getSymbol(*this)));
|
||||
} else {
|
||||
// What are you?
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::String> V8Runtime::stringRef(const jsi::String &str) {
|
||||
v8::EscapableHandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
const V8StringValue *v8StringValue =
|
||||
static_cast<const V8StringValue *>(getPointerValue(str));
|
||||
return handle_scope.Escape(
|
||||
v8StringValue->v8String_.Get(v8::Isolate::GetCurrent()));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> V8Runtime::valueRef(const jsi::PropNameID &sym) {
|
||||
v8::EscapableHandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
const V8StringValue *v8StringValue =
|
||||
static_cast<const V8StringValue *>(getPointerValue(sym));
|
||||
return handle_scope.Escape(
|
||||
v8StringValue->v8String_.Get(v8::Isolate::GetCurrent()));
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> V8Runtime::objectRef(const jsi::Object &obj) {
|
||||
v8::EscapableHandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
const V8ObjectValue *v8ObjectValue =
|
||||
static_cast<const V8ObjectValue *>(getPointerValue(obj));
|
||||
return handle_scope.Escape(
|
||||
v8ObjectValue->v8Object_.Get(v8::Isolate::GetCurrent()));
|
||||
}
|
||||
|
||||
std::unique_ptr<jsi::Runtime> makeV8Runtime(V8RuntimeArgs &&args) {
|
||||
return std::make_unique<V8Runtime>(std::move(args));
|
||||
}
|
||||
|
|
|
@ -103,6 +103,8 @@ class V8PlatformHolder {
|
|||
platform_s_ = std::make_unique<V8Platform>(true);
|
||||
#endif
|
||||
v8::V8::InitializePlatform(platform_s_.get());
|
||||
|
||||
v8::V8::Initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +115,7 @@ class V8PlatformHolder {
|
|||
if (--use_count_s_ == 0) {
|
||||
// We cannot shutdown the platform once created because V8 internally references bits of the platform from process-globals
|
||||
// This cannot be worked around, the design of V8 is not currently embedder-friendly
|
||||
// v8::V8::Dispose();
|
||||
v8::V8::ShutdownPlatform();
|
||||
platform_s_ = nullptr;
|
||||
}
|
||||
|
@ -205,9 +208,9 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
};
|
||||
|
||||
class HostObjectProxy : public IHostProxy {
|
||||
public:
|
||||
static void Get(
|
||||
v8::Local<v8::Name> v8PropName,
|
||||
private:
|
||||
static void GetInternal(
|
||||
std::string propName,
|
||||
const v8::PropertyCallbackInfo<v8::Value> &info) {
|
||||
v8::Local<v8::External> data =
|
||||
v8::Local<v8::External>::Cast(info.This()->GetInternalField(0));
|
||||
|
@ -221,31 +224,46 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
std::shared_ptr<facebook::jsi::HostObject> hostObject =
|
||||
hostObjectProxy->hostObject_;
|
||||
|
||||
v8::Local<v8::String> propNameStr =
|
||||
v8::Local<v8::String>::Cast(v8PropName);
|
||||
facebook::jsi::Value result;
|
||||
try {
|
||||
result = hostObject->get(runtime, runtime.createPropNameIDFromUtf8(
|
||||
reinterpret_cast<uint8_t *>(&propName[0]), propName.length()));
|
||||
} catch (const facebook::jsi::JSError& error) {
|
||||
info.GetReturnValue().Set(v8::Undefined(info.GetIsolate()));
|
||||
|
||||
char buffer[512];
|
||||
propNameStr->WriteUtf8(info.GetIsolate(), buffer);
|
||||
// Schedule to throw the exception back to JS.
|
||||
info.GetIsolate()->ThrowException(runtime.valueRef(error.value()));
|
||||
return;
|
||||
} catch (const std::exception& ex) {
|
||||
info.GetReturnValue().Set(v8::Undefined(info.GetIsolate()));
|
||||
|
||||
// std::string propName;
|
||||
// propName.resize(propNameStr->Utf8Length(info.GetIsolate()));
|
||||
// propNameStr->WriteUtf8(info.GetIsolate(), &propName[0]);
|
||||
// Schedule to throw the exception back to JS.
|
||||
v8::Local<v8::String> message =
|
||||
v8::String::NewFromUtf8(info.GetIsolate(), ex.what(),
|
||||
v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
info.GetIsolate()->ThrowException(v8::Exception::Error(message));
|
||||
return;
|
||||
} catch (...) {
|
||||
info.GetReturnValue().Set(v8::Undefined(info.GetIsolate()));
|
||||
|
||||
// facebook::jsi::PropNameID propNameId =
|
||||
// runtime.createPropNameIDFromUtf8(reinterpret_cast<uint8_t*>(&propName[0]),
|
||||
// propName.length());
|
||||
facebook::jsi::PropNameID propNameId = runtime.createPropNameIDFromUtf8(
|
||||
reinterpret_cast<uint8_t *>(buffer),
|
||||
propNameStr->Utf8Length(info.GetIsolate()));
|
||||
// Schedule to throw the exception back to JS.
|
||||
v8::Local<v8::String> message =
|
||||
v8::String::NewFromOneByte(
|
||||
info.GetIsolate(),
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
"<Unknown exception in host function callback>"),
|
||||
v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
info.GetIsolate()->ThrowException(v8::Exception::Error(message));
|
||||
return;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> retValue;
|
||||
{ retValue = runtime.valueRef(hostObject->get(runtime, propNameId)); }
|
||||
|
||||
info.GetReturnValue().Set(retValue);
|
||||
info.GetReturnValue().Set(runtime.valueRef(result));
|
||||
}
|
||||
|
||||
static void Set(
|
||||
v8::Local<v8::Name> v8PropName,
|
||||
static void SetInternal(
|
||||
std::string propName,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value> &info) {
|
||||
v8::Local<v8::External> data =
|
||||
|
@ -260,22 +278,76 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
std::shared_ptr<facebook::jsi::HostObject> hostObject =
|
||||
hostObjectProxy->hostObject_;
|
||||
|
||||
v8::Local<v8::String> propNameStr =
|
||||
v8::Local<v8::String>::Cast(v8PropName);
|
||||
try {
|
||||
hostObject->set(
|
||||
runtime,
|
||||
runtime.createPropNameIDFromUtf8(
|
||||
reinterpret_cast<uint8_t *>(&propName[0]), propName.length()),
|
||||
runtime.createValue(value));
|
||||
} catch (const facebook::jsi::JSError& error) {
|
||||
// Schedule to throw the exception back to JS.
|
||||
info.GetIsolate()->ThrowException(runtime.valueRef(error.value()));
|
||||
} catch (const std::exception& ex) {
|
||||
// Schedule to throw the exception back to JS.
|
||||
v8::Local<v8::String> message =
|
||||
v8::String::NewFromUtf8(info.GetIsolate(), ex.what(),
|
||||
v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
info.GetIsolate()->ThrowException(v8::Exception::Error(message));
|
||||
} catch (...) {
|
||||
// Schedule to throw the exception back to JS.
|
||||
v8::Local<v8::String> message =
|
||||
v8::String::NewFromOneByte(
|
||||
info.GetIsolate(),
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
"<Unknown exception in host function callback>"),
|
||||
v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
info.GetIsolate()->ThrowException(v8::Exception::Error(message));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static void Get(
|
||||
v8::Local<v8::Name> v8PropName,
|
||||
const v8::PropertyCallbackInfo<v8::Value> &info) {
|
||||
v8::Local<v8::String> propNameStr = v8::Local<v8::String>::Cast(v8PropName);
|
||||
|
||||
std::string propName;
|
||||
propName.resize(propNameStr->Utf8Length(info.GetIsolate()));
|
||||
propNameStr->WriteUtf8(info.GetIsolate(), &propName[0]);
|
||||
GetInternal(propName, info);
|
||||
}
|
||||
|
||||
hostObject->set(
|
||||
runtime,
|
||||
runtime.createPropNameIDFromUtf8(
|
||||
reinterpret_cast<uint8_t *>(&propName[0]), propName.length()),
|
||||
runtime.createValue(value));
|
||||
static void GetIndexed(
|
||||
uint32_t index,
|
||||
const v8::PropertyCallbackInfo<v8::Value> &info) {
|
||||
std::string propName = std::to_string(index);
|
||||
GetInternal(propName, info);
|
||||
}
|
||||
|
||||
static void Set(
|
||||
v8::Local<v8::Name> v8PropName,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value> &info) {
|
||||
v8::Local<v8::String> propNameStr = v8::Local<v8::String>::Cast(v8PropName);
|
||||
|
||||
std::string propName;
|
||||
propName.resize(propNameStr->Utf8Length(info.GetIsolate()));
|
||||
propNameStr->WriteUtf8(info.GetIsolate(), &propName[0]);
|
||||
SetInternal(propName, value, info);
|
||||
}
|
||||
|
||||
static void SetIndexed(
|
||||
uint32_t index,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value> &info) {
|
||||
std::string propName = std::to_string(index);
|
||||
SetInternal(propName, value, info);
|
||||
}
|
||||
|
||||
static void Enumerator(const v8::PropertyCallbackInfo<v8::Array> &info) {
|
||||
v8::Local<v8::External> data = v8::Local<v8::External>::Cast(info.Data());
|
||||
v8::Local<v8::External> data = v8::Local<v8::External>::Cast(info.This()->GetInternalField(0));
|
||||
HostObjectProxy *hostObjectProxy =
|
||||
reinterpret_cast<HostObjectProxy *>(data->Value());
|
||||
|
||||
|
@ -346,28 +418,28 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
} catch (const facebook::jsi::JSError &error) {
|
||||
callbackInfo.GetReturnValue().Set(v8::Undefined(isolate));
|
||||
|
||||
// Schedule to throw the exception back to JS.
|
||||
// Schedule to throw the exception back to JS
|
||||
isolate->ThrowException(runtime.valueRef(error.value()));
|
||||
return;
|
||||
} catch (const std::exception &ex) {
|
||||
callbackInfo.GetReturnValue().Set(v8::Undefined(isolate));
|
||||
|
||||
// Schedule to throw the exception back to JS.
|
||||
// Schedule to throw the exception back to JS
|
||||
std::string errMessage = std::string("Exception in HostFunction: ") + ex.what();
|
||||
v8::Local<v8::String> message =
|
||||
v8::String::NewFromUtf8(
|
||||
isolate, ex.what(), v8::NewStringType::kNormal)
|
||||
isolate, errMessage.c_str(), v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
isolate->ThrowException(v8::Exception::Error(message));
|
||||
return;
|
||||
} catch (...) {
|
||||
callbackInfo.GetReturnValue().Set(v8::Undefined(isolate));
|
||||
|
||||
// Schedule to throw the exception back to JS.
|
||||
// Schedule to throw the exception back to JS
|
||||
v8::Local<v8::String> message =
|
||||
v8::String::NewFromOneByte(
|
||||
isolate,
|
||||
reinterpret_cast<const uint8_t *>(
|
||||
"<Unknown exception in host function callback>"),
|
||||
reinterpret_cast<const uint8_t *>("Exception in HostFunction: <unknown>"),
|
||||
v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
isolate->ThrowException(v8::Exception::Error(message));
|
||||
|
@ -403,30 +475,37 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
V8Runtime &runtime_;
|
||||
};
|
||||
|
||||
class V8StringValue final : public PointerValue {
|
||||
V8StringValue(v8::Local<v8::String> str);
|
||||
~V8StringValue();
|
||||
template<typename T>
|
||||
class V8PointerValue final : public PointerValue {
|
||||
static V8PointerValue<T>* make(v8::Local<T> objectRef) {
|
||||
return new V8PointerValue<T>(objectRef);
|
||||
}
|
||||
|
||||
void invalidate() override;
|
||||
V8PointerValue(v8::Local<T> obj) :
|
||||
v8Object_(v8::Isolate::GetCurrent(), obj)
|
||||
{}
|
||||
|
||||
v8::Persistent<v8::String> v8String_;
|
||||
~V8PointerValue() {
|
||||
v8Object_.Reset();
|
||||
}
|
||||
|
||||
void invalidate() override {
|
||||
delete this;
|
||||
}
|
||||
|
||||
v8::Local<T> get(v8::Isolate* isolate) const {
|
||||
return v8Object_.Get(isolate);
|
||||
}
|
||||
|
||||
private:
|
||||
v8::Persistent<T> v8Object_;
|
||||
|
||||
protected:
|
||||
friend class V8Runtime;
|
||||
};
|
||||
|
||||
class V8ObjectValue final : public PointerValue {
|
||||
V8ObjectValue(v8::Local<v8::Object> obj);
|
||||
|
||||
~V8ObjectValue();
|
||||
|
||||
void invalidate() override;
|
||||
|
||||
v8::Persistent<v8::Object> v8Object_;
|
||||
|
||||
protected:
|
||||
friend class V8Runtime;
|
||||
};
|
||||
using V8StringValue = V8PointerValue<v8::String>;
|
||||
using V8ObjectValue = V8PointerValue<v8::Object>;
|
||||
|
||||
class ExternalOwningOneByteStringResource
|
||||
: public v8::String::ExternalOneByteStringResource {
|
||||
|
@ -454,10 +533,10 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
|
||||
std::string symbolToString(const facebook::jsi::Symbol &) override;
|
||||
|
||||
PointerValue *cloneString(const Runtime::PointerValue *pv) override;
|
||||
PointerValue *cloneObject(const Runtime::PointerValue *pv) override;
|
||||
PointerValue *clonePropNameID(const Runtime::PointerValue *pv) override;
|
||||
PointerValue *cloneSymbol(const PointerValue *) override;
|
||||
PointerValue *cloneString(const PointerValue *pv) override;
|
||||
PointerValue *cloneObject(const PointerValue *pv) override;
|
||||
PointerValue *clonePropNameID(const PointerValue *pv) override;
|
||||
PointerValue *cloneSymbol(const PointerValue *pv) override;
|
||||
|
||||
facebook::jsi::PropNameID createPropNameIDFromAscii(
|
||||
const char *str,
|
||||
|
@ -585,24 +664,7 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
private:
|
||||
v8::Local<v8::Context> CreateContext(v8::Isolate *isolate);
|
||||
|
||||
// Methods to compile and execute JS script.
|
||||
v8::ScriptCompiler::CachedData *TryLoadCachedData(const std::string &path);
|
||||
void PersistCachedData(
|
||||
std::unique_ptr<v8::ScriptCompiler::CachedData> cachedData,
|
||||
const std::string &path);
|
||||
|
||||
v8::Local<v8::Script> GetCompiledScriptFromCache(
|
||||
const v8::Local<v8::String> &source,
|
||||
const std::string &sourceURL);
|
||||
v8::Local<v8::Script> GetCompiledScript(
|
||||
const v8::Local<v8::String> &source,
|
||||
const std::string &sourceURL);
|
||||
|
||||
facebook::jsi::Value ExecuteString(
|
||||
v8::Local<v8::String> source,
|
||||
const facebook::jsi::Buffer *cache,
|
||||
v8::Local<v8::Value> name,
|
||||
bool report_exceptions);
|
||||
// Methods to compile and execute JS script
|
||||
facebook::jsi::Value ExecuteString(
|
||||
const v8::Local<v8::String> &source,
|
||||
const std::string &sourceURL);
|
||||
|
@ -619,24 +681,21 @@ class V8Runtime : public facebook::jsi::Runtime {
|
|||
void createHostObjectConstructorPerContext();
|
||||
|
||||
// Basically convenience casts
|
||||
static v8::Local<v8::String> stringRef(const facebook::jsi::String &str);
|
||||
static v8::Local<v8::Value> valueRef(const facebook::jsi::PropNameID &sym);
|
||||
static v8::Local<v8::Object> objectRef(const facebook::jsi::Object &obj);
|
||||
template<typename T>
|
||||
static v8::Local<T> pvRef(const PointerValue* pv) {
|
||||
v8::EscapableHandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
const V8PointerValue<T> *v8PValue = static_cast<const V8PointerValue<T>*>(pv);
|
||||
return handle_scope.Escape(v8PValue->get(v8::Isolate::GetCurrent()));
|
||||
}
|
||||
|
||||
static v8::Local<v8::String> stringRef(const facebook::jsi::String &str) { return pvRef<v8::String>(getPointerValue(str)); }
|
||||
static v8::Local<v8::Value> valueRef(const facebook::jsi::PropNameID &sym) { return pvRef<v8::Value>(getPointerValue(sym)); }
|
||||
static v8::Local<v8::Object> objectRef(const facebook::jsi::Object &obj) { return pvRef<v8::Object>(getPointerValue(obj)); }
|
||||
static v8::Local<v8::Symbol> symbolRef(const facebook::jsi::Symbol &sym) { return pvRef<v8::Symbol>(getPointerValue(sym)); }
|
||||
|
||||
v8::Local<v8::Value> valueRef(const facebook::jsi::Value &value);
|
||||
facebook::jsi::Value createValue(v8::Local<v8::Value> value) const;
|
||||
|
||||
// Factory methods for creating String/Object
|
||||
facebook::jsi::String createString(v8::Local<v8::String> stringRef) const;
|
||||
facebook::jsi::PropNameID createPropNameID(v8::Local<v8::Value> propValRef);
|
||||
facebook::jsi::Object createObject(v8::Local<v8::Object> objectRef) const;
|
||||
|
||||
// Used by factory methods and clone methods
|
||||
facebook::jsi::Runtime::PointerValue *makeStringValue(
|
||||
v8::Local<v8::String> str) const;
|
||||
facebook::jsi::Runtime::PointerValue *makeObjectValue(
|
||||
v8::Local<v8::Object> obj) const;
|
||||
|
||||
#ifdef _WIN32
|
||||
std::unique_ptr<inspector::Agent> inspector_agent_;
|
||||
#endif
|
||||
|
|
|
@ -1260,6 +1260,13 @@ class JSI_EXPORT JSError : public JSIException {
|
|||
return stack_;
|
||||
}
|
||||
|
||||
/// In V8's case, creating an Error object in JS doesn't record the callstack
|
||||
/// To preserve it, we need a way to manually add the stack here and on the JS side
|
||||
void setStack(std::string stack) {
|
||||
stack_ = std::move(stack);
|
||||
what_ = message_ + "\n\n" + stack_;
|
||||
}
|
||||
|
||||
const std::string& getMessage() const {
|
||||
return message_;
|
||||
}
|
||||
|
|
|
@ -721,8 +721,12 @@ TEST_P(JSITest, HostFunctionTest) {
|
|||
.getString(rt)
|
||||
.utf8(rt),
|
||||
"A cat was called with std::function::target");
|
||||
|
||||
// Disabling these tests for V8 because we'd incur unnecessary cost to implement the functionality
|
||||
#if 0
|
||||
EXPECT_TRUE(callable.isHostFunction(rt));
|
||||
EXPECT_NE(callable.getHostFunction(rt).target<Callable>(), nullptr);
|
||||
#endif
|
||||
|
||||
std::string strval = "strval1";
|
||||
auto getter = Object(rt);
|
||||
|
|
Загрузка…
Ссылка в новой задаче