Skip to content

Commit

Permalink
feat(ios): support v8 for ios
Browse files Browse the repository at this point in the history
  • Loading branch information
ozonelmy authored and hippy-actions[bot] committed Apr 7, 2023
1 parent dd231c8 commit 94eeaae
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ coverage
dist
node_modules
xcuserdata
v8forios

*.log
*.iml
Expand Down
1 change: 1 addition & 0 deletions framework/examples/ios-demo/podfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ENV["layout_engine"]="Taitank"
# ENV["js_engine"] = "v8"
install! 'cocoapods',
:deterministic_uuids => false,
:generate_multiple_pod_projects => true
Expand Down
34 changes: 20 additions & 14 deletions framework/ios/base/enginewrapper/v8/HippyV8ContextWrapper.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@
* limitations under the License.
*/

#import "HippyAssert.h"
#import "HPAsserts.h"
#import "HPLog.h"
#import "HPDriverStackFrame.h"
#import "HippyV8ContextWrapper.h"
#import "HippyJSStackFrame.h"
#import "NativeRenderLog.h"
#import "NSObject+CtxValue.h"
#import "NSObject+V8Value.h"

#include <memory.h>
#include "driver/napi/v8/js_native_api_v8.h"

#include "driver/napi/v8/v8_ctx_value.h"
#include "driver/napi/v8/v8_ctx.h"

static id StringJSONToObject(NSString *string) {
@autoreleasepool {
Expand All @@ -38,19 +40,19 @@ static id StringJSONToObject(NSString *string) {
}
}

static v8::Local<v8::Value> V8ValueFromCtxValue(const std::shared_ptr<hippy::napi::CtxValue> &value) {
static v8::Local<v8::Value> V8ValueFromCtxValue(const std::shared_ptr<hippy::napi::CtxValue> &value, v8::Local<v8::Context> context) {
auto ctxValue = std::static_pointer_cast<hippy::napi::V8CtxValue>(value);
v8::Local<v8::Value> v8Value = ctxValue->global_value_.Get(ctxValue->isolate_);
v8::Local<v8::Value> v8Value = ctxValue->global_value_.Get(context->GetIsolate());
return v8Value;
}

static v8::Local<v8::Object> V8ObjectFromCtxValue(const std::shared_ptr<hippy::napi::CtxValue> &value,
v8::Local<v8::Context> context) {
auto ctxValue = std::static_pointer_cast<hippy::napi::V8CtxValue>(value);
v8::Local<v8::Value> v8Value = ctxValue->global_value_.Get(ctxValue->isolate_);
HippyAssert(v8Value->IsObject(), @"value is not a object");
v8::Local<v8::Value> v8Value = ctxValue->global_value_.Get(context->GetIsolate());
HPAssert(v8Value->IsObject(), @"value is not a object");
v8::MaybeLocal<v8::Object> maybeObject = v8Value->ToObject(context);
HippyAssert(!maybeObject.IsEmpty(), @"maybe object is not a object");
HPAssert(!maybeObject.IsEmpty(), @"maybe object is not a object");
return maybeObject.ToLocalChecked();
}

Expand Down Expand Up @@ -104,7 +106,7 @@ static void HandleUncaughtJsError(v8::Local<v8::Message> message, v8::Local<v8::
v8::Isolate *isolate = message->GetIsolate();
NSString *errorMessage = v8StringToNSString(isolate, message->Get());
int frameCount = stack->GetFrameCount();
NSMutableArray<HippyJSStackFrame *> *stacks = [NSMutableArray arrayWithCapacity:frameCount];
NSMutableArray<HPDriverStackFrame *> *stacks = [NSMutableArray arrayWithCapacity:frameCount];
for (int i = 0; i < frameCount; i++) {
v8::Local<v8::StackFrame> frame = stack->GetFrame(isolate, i);
v8::Local<v8::String> functionName = frame->GetFunctionName();
Expand All @@ -114,7 +116,10 @@ static void HandleUncaughtJsError(v8::Local<v8::Message> message, v8::Local<v8::
}
v8::Local<v8::String> scrName = frame->GetScriptNameOrSourceURL();
NSString *scriptName = v8StringToNSString(isolate, scrName);
HippyJSStackFrame *stackFrame = [[HippyJSStackFrame alloc] initWithMethodName:funcName file:scriptName lineNumber:frame->GetLineNumber() column:frame->GetColumn()];
HPDriverStackFrame *stackFrame = [[HPDriverStackFrame alloc] initWithMethodName:funcName
file:scriptName
lineNumber:frame->GetLineNumber()
column:frame->GetColumn()];
[stacks addObject:stackFrame];
}
excpetionHandler(wrapper, errorMessage, [stacks copy]);
Expand Down Expand Up @@ -325,7 +330,8 @@ - (BOOL)setProperties:(NSDictionary *)properties toGlobalObject:(NSString *)obje
v8::Local<v8::String> keyString = [key toV8StringInIsolate:isolate];
v8::Local<v8::Value> localValue = [object toV8ValueInIsolate:isolate context:localContext];
if (!targetObject->Set(localContext, keyString, localValue).FromMaybe(false)) {
NativeRenderLogWarn(@"createGlobalObject withDictionary failed, key:%@, value:%@", key, object);
// NativeRenderLogWarn(@"createGlobalObject withDictionary failed, key:%@, value:%@", key, object);

}
if (tryCache.HasCaught()) {
_exception = TryToFetchStringFromV8Value(tryCache.Exception(), isolate);
Expand All @@ -352,7 +358,7 @@ - (BOOL)setProperty:(NSString *)propertyName
v8::Context::Scope contextScope(localContext);
v8::Local<v8::String> v8Name = [propertyName toV8StringInIsolate:isolate];
v8::Local<v8::Object> targetObject = V8ObjectFromCtxValue(object, localContext);
v8::Local<v8::Value> targetValue = V8ValueFromCtxValue(value);
v8::Local<v8::Value> targetValue = V8ValueFromCtxValue(value, localContext);
v8::TryCatch tryCache(isolate);
BOOL ret = targetObject->Set(localContext, v8Name, targetValue).FromMaybe(false);
if (tryCache.HasCaught()) {
Expand All @@ -379,7 +385,7 @@ - (BOOL)setProperty:(NSString *)propertyName
v8::Local<v8::String> v8Name = [propertyName toV8StringInIsolate:isolate];
v8::MaybeLocal<v8::Value> maybeValue = targetObject->Get(localContext, v8Name);
if (maybeValue.IsEmpty()) {
NativeRenderLogWarn(@"get property %@ for object failed", propertyName);
HPLog(@"get property %@ for object failed", propertyName);
return nullptr;
}
v8::Local<v8::Value> value = maybeValue.ToLocalChecked();
Expand Down
9 changes: 5 additions & 4 deletions framework/ios/utils/v8/NSObject+V8Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
*/

#import <Foundation/Foundation.h>
#include "driver/napi/v8/js_native_api_v8.h"
#import "HippyDefines.h"
#import "MacroDefines.h"

#include "v8/v8.h"

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -69,8 +70,8 @@ NS_ASSUME_NONNULL_BEGIN

@end

HIPPY_EXTERN id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local<v8::Context> context);
HP_EXTERN id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local<v8::Context> context);

HIPPY_EXTERN NSString *TryToFetchStringFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate);
HP_EXTERN NSString *TryToFetchStringFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate);

NS_ASSUME_NONNULL_END
25 changes: 13 additions & 12 deletions framework/ios/utils/v8/NSObject+V8Value.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@
*/

#import "NSObject+V8Value.h"
#import "HippyAssert.h"
#import "HPAsserts.h"

@implementation NSObject (V8Value)

- (v8::Local<v8::Value>)toV8ValueInIsolate:(v8::Isolate *)isolate context:(v8::Local<v8::Context>)context {
HippyAssert(isolate, @"ios must not be null for object convert");
HPAssert(isolate, @"ios must not be null for object convert");
#ifdef DEBUG
BOOL isRightType = [self isKindOfClass:[NSArray class]] ||
[self isKindOfClass:[NSDictionary class]] ||
[self isKindOfClass:[NSData class]] ||
[self isKindOfClass:[NSString class]] ||
[self isKindOfClass:[NSNumber class]];
HippyAssert(isRightType, @"toV8ValueInIsolate is not supported by %@ class", NSStringFromClass([self class]));
HPAssert(isRightType, @"toV8ValueInIsolate is not supported by %@ class", NSStringFromClass([self class]));
#endif
v8::Local<v8::Object> object = v8::Object::New(isolate);
return object;
Expand All @@ -44,7 +44,7 @@ @implementation NSObject (V8Value)
@implementation NSArray (V8Value)

- (v8::Local<v8::Value>)toV8ValueInIsolate:(v8::Isolate *)isolate context:(v8::Local<v8::Context>)context {
HippyAssert(isolate, @"ios must not be null for array convert");
HPAssert(isolate, @"ios must not be null for array convert");
size_t count = [self count];
v8::Local<v8::Value> elements[count];
for (size_t i = 0; i < count; i++) {
Expand All @@ -59,7 +59,7 @@ @implementation NSArray (V8Value)
@implementation NSDictionary (V8Value)

- (v8::Local<v8::Value>)toV8ValueInIsolate:(v8::Isolate *)isolate context:(v8::Local<v8::Context>)context {
HippyAssert(isolate, @"ios must not be null for dictionary convert");
HPAssert(isolate, @"ios must not be null for dictionary convert");
v8::Local<v8::Object> object = v8::Object::New(isolate);
for (id key in self) {
id value = [self objectForKey:key];
Expand All @@ -81,7 +81,7 @@ static void ArrayBufferDataDeleter(void* data, size_t length, void* deleter_data
#endif //V8_MAJOR_VERSION >= 9

- (v8::Local<v8::Value>)toV8ValueInIsolate:(v8::Isolate *)isolate context:(v8::Local<v8::Context>)context {
HippyAssert(isolate, @"ios must not be null for data convert");
HPAssert(isolate, @"ios must not be null for data convert");
size_t length = [self length];
void *buffer = malloc(length);
if (!buffer) {
Expand All @@ -106,7 +106,7 @@ @implementation NSString (V8Value)
}

- (v8::Local<v8::String>)toV8StringInIsolate:(v8::Isolate *)isolate {
HippyAssert(isolate, @"ios must not be null for string convert");
HPAssert(isolate, @"ios must not be null for string convert");
const char *p = [self UTF8String]?:"";
v8::MaybeLocal<v8::String> string = v8::String::NewFromUtf8(isolate, p);
return string.ToLocalChecked();
Expand All @@ -117,7 +117,7 @@ @implementation NSString (V8Value)
@implementation NSNumber (V8Value)

- (v8::Local<v8::Value>)toV8ValueInIsolate:(v8::Isolate *)isolate context:(v8::Local<v8::Context>)context {
HippyAssert(isolate, @"ios must not be null for number convert");
HPAssert(isolate, @"ios must not be null for number convert");
v8::Local<v8::Value> number = v8::Number::New(isolate, [self doubleValue]);
return number;
}
Expand All @@ -132,6 +132,7 @@ @implementation NSNull (V8Value)

@end

id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local<v8::Context> context);
static id ObjectFromV8MaybeValue(v8::MaybeLocal<v8::Value> maybeValue, v8::Isolate *isolate, v8::Local<v8::Context> context) {
if (maybeValue.IsEmpty()) {
return nil;
Expand All @@ -147,7 +148,7 @@ id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local
return nil;
}
else if (value->IsString()) {
HippyAssert(isolate, @"isolate must not be null for string value");
HPAssert(isolate, @"isolate must not be null for string value");
v8::Local<v8::String> string = value.As<v8::String>();
int len = string->Length();
if (string->IsOneByte()) {
Expand All @@ -164,7 +165,7 @@ id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local
}
}
else if (value->IsStringObject()) {
HippyAssert(isolate, @"isolate must not be null for string value");
HPAssert(isolate, @"isolate must not be null for string value");
v8::Local<v8::StringObject> stringObj = value.As<v8::StringObject>();
return ObjectFromV8Value(stringObj->ValueOf(), isolate, context);
}
Expand Down Expand Up @@ -237,7 +238,7 @@ id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local
NSMutableDictionary *keysValues = [NSMutableDictionary dictionaryWithCapacity:length];
for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> key = props->Get(context, i).ToLocalChecked();
HippyAssert(key->IsString(), @"ObjectFromV8Value only supports keys as string");
HPAssert(key->IsString(), @"ObjectFromV8Value only supports keys as string");
if (!key->IsString()) {
continue;
}
Expand All @@ -252,7 +253,7 @@ id ObjectFromV8Value(v8::Local<v8::Value> value, v8::Isolate *isolate, v8::Local

else {
#ifdef DEBUG
HippyAssert(NO, @"no implementation ObjectFromV8Value for type %@", ObjectFromV8Value(value->TypeOf(isolate), isolate, context));
HPAssert(NO, @"no implementation ObjectFromV8Value for type %@", ObjectFromV8Value(value->TypeOf(isolate), isolate, context));
#endif
return nil;
}
Expand Down
84 changes: 76 additions & 8 deletions hippy.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@
#

layout_engine = "Taitank"
js_engine = "jsc"
use_frameworks = false;

Pod::Spec.new do |s|
if ENV["layout_engine"]
layout_engine = ENV["layout_engine"]
end
if ENV["use_frameworks"]
use_frameworks = true
end
if ENV["js_engine"]
js_engine = ENV["js_engine"]
end
puts "layout engine is #{layout_engine}, js engine is #{js_engine}"
puts "use_frameworks trigger is #{use_frameworks}"
if use_frameworks
framework_header_path = '${PODS_CONFIGURATION_BUILD_DIR}/hippy/hippy.framework/Headers'
Expand Down Expand Up @@ -43,14 +49,20 @@ Pod::Spec.new do |s|

#prepare_command not working for subspecs,so we remove devtools script from devtools subspec to root
s.prepare_command = <<-CMD
./xcodeinitscript.sh "#{layout_engine}"
./xcodeinitscript.sh "#{layout_engine}" "#{js_engine}"
CMD

s.subspec 'Framework' do |framework|
puts 'hippy subspec \'framework\' read begin'
framework.source_files = 'framework/ios/**/*.{h,m,c,mm,s,cpp,cc}'
framework.public_header_files = 'framework/ios/**/*.h'
framework.exclude_files = ['framework/ios/base/enginewrapper/v8', 'framework/ios/utils/v8']
if js_engine == "jsc"
framework.exclude_files = ['framework/ios/base/enginewrapper/v8', 'framework/ios/utils/v8']
elsif js_engine == "v8"
framework.exclude_files = ['framework/ios/base/enginewrapper/jsc', 'framework/ios/utils/jsc']
else
framework.exclude_files = ['framework/ios/base/enginewrapper/jsc', 'framework/ios/utils/jsc', 'framework/ios/base/enginewrapper/v8', 'framework/ios/utils/v8']
end
framework.libraries = 'c++'
framework.pod_target_xcconfig = {
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
Expand Down Expand Up @@ -162,16 +174,50 @@ Pod::Spec.new do |s|
driver.frameworks = 'JavaScriptCore'
driver.source_files = ['driver/js/include/**/*.h', 'driver/js/src/**/*.cc']
driver.public_header_files = 'driver/js/include/**/*.h'
driver.exclude_files = ['driver/js/include/driver/napi/v8','driver/js/src/napi/v8','driver/js/include/driver/runtime','driver/js/src/runtime', 'driver/js/include/vm/v8', 'driver/js/src/vm/v8']
if js_engine == "jsc"
driver.exclude_files = [
'driver/js/include/driver/napi/v8',
'driver/js/src/napi/v8',
'driver/js/include/driver/runtime',
'driver/js/src/runtime',
'driver/js/include/driver/vm/v8',
'driver/js/src/vm/v8']
elsif js_engine == "v8"
driver.exclude_files = [
'driver/js/include/driver/napi/jsc',
'driver/js/src/napi/jsc',
'driver/js/include/driver/vm/jsc',
'driver/js/src/vm/jsc']
else
driver.exclude_files = [
'driver/js/include/driver/napi/v8',
'driver/js/src/napi/v8',
'driver/js/include/driver/runtime',
'driver/js/src/runtime',
'driver/js/include/vm/v8',
'driver/js/src/vm/v8',
'driver/js/include/driver/napi/jsc',
'driver/js/src/napi/jsc',
'driver/js/include/vm/jsc',
'driver/js/src/vm/jsc']
end

if use_frameworks
header_search_paths = framework_header_path
driver.header_mappings_dir = 'driver/js/include'
else
header_search_paths = '${PODS_ROOT}/hippy/driver/js/include/'
end
definition_engine = ''
if js_engine == "jsc"
definition_engine = 'JS_JSC=1'
elsif js_engine == "v8"
definition_engine = 'JS_V8=1'
else
end
driver.pod_target_xcconfig = {
'HEADER_SEARCH_PATHS' => header_search_paths,
'GCC_PREPROCESSOR_DEFINITIONS' => 'JS_JSC=1',
'GCC_PREPROCESSOR_DEFINITIONS' => definition_engine,
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
'GCC_ENABLE_CPP_EXCEPTIONS' => false,
'GCC_ENABLE_CPP_RTTI' => false,
Expand Down Expand Up @@ -294,10 +340,14 @@ Pod::Spec.new do |s|
s.subspec 'DevTools' do |devtools|
puts 'hippy subspec \'devtools\' read begin'
devtools.libraries = 'c++'
devtools_exclude_files = Array.new;
if js_engine == "jsc"
devtools_exclude_files += ['devtools/devtools-integration/native/include/devtools/v8', 'devtools/devtools-integration/native/src/v8']
elsif js_engine == "v8"
else
devtools_exclude_files += ['devtools/devtools-integration/native/include/devtools/v8', 'devtools/devtools-integration/native/src/v8']
end
devtools.exclude_files = [
#v8 files
'devtools/devtools-integration/native/include/devtools/v8',
'devtools/devtools-integration/native/src/v8',
#test files
'devtools/devtools-integration/ios/DevtoolsBackend/_deps/**/*test*/**/*',
'devtools/devtools-integration/ios/DevtoolsBackend/_deps/**/*test*',
Expand All @@ -314,7 +364,7 @@ Pod::Spec.new do |s|
'devtools/devtools-integration/ios/DevtoolsBackend/_deps/base64-src/lib/tables/table_generator.c',
'devtools/devtools-integration/ios/DevtoolsBackend/_deps/base64-src/lib/arch/**/{dec,enc}_*.c',
'devtools/devtools-integration/ios/DevtoolsBackend/_deps/base64-src/bin/base64.c',
]
] + devtools_exclude_files
devtools.public_header_files = [
'devtools/devtools-integration/native/include/devtools/devtools_data_source.h',
#devtools_integration/native
Expand Down Expand Up @@ -370,5 +420,23 @@ Pod::Spec.new do |s|
puts 'hippy subspec \'devtools\' read end'
end

if js_engine == "v8"
s.subspec 'v8' do |v8|
puts 'hippy subspec \'v8\' read begin'
v8.source_files = ['v8forios/v8/include']
v8.public_header_files = ['v8forios/v8/include']
v8.pod_target_xcconfig = {
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
'HEADER_SEARCH_PATHS' => '${PODS_ROOT}/hippy/v8forios/v8/include ${PODS_ROOT}/hippy/v8forios/v8/include/v8',
'GCC_ENABLE_CPP_EXCEPTIONS' => false,
'GCC_ENABLE_CPP_RTTI' => false,
}
v8.libraries = 'c++'
v8.vendored_library = 'v8forios/v8/libv8.a'
v8.preserve_path = 'v8forios/v8'
puts 'hippy subspec \'v8\' read end'
end
end

puts 'hippy.podspec read ends'
end
Loading

0 comments on commit 94eeaae

Please sign in to comment.