diff --git a/Common/cpp/NativeModules/NativeReanimatedModule.cpp b/Common/cpp/NativeModules/NativeReanimatedModule.cpp index a9bb968b846..69a8760a46f 100644 --- a/Common/cpp/NativeModules/NativeReanimatedModule.cpp +++ b/Common/cpp/NativeModules/NativeReanimatedModule.cpp @@ -10,6 +10,7 @@ #include "FrozenObject.h" #include #include +#include #include #include "JSIStoreValueUser.h" @@ -61,7 +62,8 @@ NativeReanimatedModule::NativeReanimatedModule(std::shared_ptr jsIn std::unique_ptr rt, std::shared_ptr errorHandler, std::function propObtainer, - PlatformDepMethodsHolder platformDepMethodsHolder) : NativeReanimatedModuleSpec(jsInvoker), + PlatformDepMethodsHolder platformDepMethodsHolder, + std::function()> runtimeObtainer) : NativeReanimatedModuleSpec(jsInvoker), runtime(std::move(rt)), mapperRegistry(new MapperRegistry()), eventHandlerRegistry(new EventHandlerRegistry()), @@ -69,14 +71,15 @@ NativeReanimatedModule::NativeReanimatedModule(std::shared_ptr jsIn propObtainer(propObtainer), errorHandler(errorHandler), workletsCache(new WorkletsCache()), - scheduler(scheduler) + scheduler(scheduler), + runtimeObtainer(runtimeObtainer) { auto requestAnimationFrame = [=](FrameCallback callback) { frameCallbacks.push_back(callback); maybeRequestRender(); }; - RuntimeDecorator::addNativeObjects(*runtime, + RuntimeDecorator::decorateUI(*runtime, platformDepMethodsHolder.updaterFunction, requestAnimationFrame, platformDepMethodsHolder.scrollToFunction, @@ -190,6 +193,46 @@ jsi::Value NativeReanimatedModule::getViewProp(jsi::Runtime &rt, const jsi::Valu return jsi::Value::undefined(); } +jsi::Value NativeReanimatedModule::spawnThread(jsi::Runtime &rt, const jsi::Value &operations) { + jsi::Object object = operations.asObject(rt); + + if (!object.isFunction(rt) || object.getProperty(rt, "__worklet").isUndefined()) { + errorHandler->setError("Function passed to spawnThread doesn't seem to be a worklet"); + errorHandler->raise(); + return jsi::Value::undefined(); + } + + const int threadId = ++this->currentThreadId; + + std::shared_ptr workletShareable = ShareableValue::adapt(rt, operations, this, ValueType::UndefinedType, threadId); + + std::shared_ptr th = std::make_shared(); + this->threads.insert(std::make_pair(threadId, th)); + + auto job = [=]() { + std::unique_ptr customRuntime = runtimeObtainer(); + std::shared_ptr th = this->threads.at(threadId); + th->rt = std::move(customRuntime); + RuntimeDecorator::decorateCustomThread(*th->rt); + jsi::Value result = jsi::Value::undefined(); + + jsi::Function func = workletShareable->getValue(*th->rt, threadId).asObject(*th->rt).asFunction(*th->rt); + std::shared_ptr funcPtr = std::make_shared(std::move(func)); + try { + result = funcPtr->callWithThis(*th->rt, *funcPtr); + } + catch (std::exception &e) { + std::string str = e.what(); + errorHandler->setError(str); + errorHandler->raise(); + } + return result; + }; + + threads.at(threadId)->thread = std::make_shared(job); + return jsi::Value::undefined(); +} + void NativeReanimatedModule::onEvent(std::string eventName, std::string eventAsString) { try diff --git a/Common/cpp/NativeModules/NativeReanimatedModuleSpec.cpp b/Common/cpp/NativeModules/NativeReanimatedModuleSpec.cpp index 22927a73074..34adb2a96df 100644 --- a/Common/cpp/NativeModules/NativeReanimatedModuleSpec.cpp +++ b/Common/cpp/NativeModules/NativeReanimatedModuleSpec.cpp @@ -89,6 +89,16 @@ static jsi::Value __hostFunction_NativeReanimatedModuleSpec_getViewProp( return jsi::Value::undefined(); } +static jsi::Value __hostFunction_NativeReanimatedModuleSpec_spawnThread( + jsi::Runtime &rt, + TurboModule &turboModule, + const jsi::Value *args, + size_t count) { + static_cast(&turboModule) + ->spawnThread(rt, std::move(args[0])); + return jsi::Value::undefined(); +} + NativeReanimatedModuleSpec::NativeReanimatedModuleSpec(std::shared_ptr jsInvoker) : TurboModule("NativeReanimated", jsInvoker) { methodMap_["installCoreFunctions"] = MethodMetadata{ @@ -115,6 +125,9 @@ NativeReanimatedModuleSpec::NativeReanimatedModuleSpec(std::shared_ptr WorkletsCache::obtainFunction(jsi::Runtime &rt, const std::string &code) { + jsi::Function fun = functionFromString(rt, code); + std::shared_ptr funPtr(new jsi::Function(std::move(fun))); + return std::move(funPtr); } -std::shared_ptr WorkletsCache::getFunction(jsi::Runtime &rt, std::shared_ptr frozenObj) { +std::shared_ptr WorkletsCache::getFunction(jsi::Runtime &rt, std::shared_ptr frozenObj, const int customThreadId) { + if (customThreadId != -1) { + // worklets cache wouldn't work for custom threads as every time we have a different RT + return obtainFunction(rt, frozenObj->map["asString"]->stringValue); + } long long workletHash = frozenObj->map["__workletHash"]->numberValue; if (worklets.count(workletHash) == 0) { - jsi::Function fun = function(rt, frozenObj->map["asString"]->stringValue); - std::shared_ptr funPtr(new jsi::Function(std::move(fun))); - worklets[workletHash] = funPtr; + worklets[workletHash] = obtainFunction(rt, frozenObj->map["asString"]->stringValue); } return worklets[workletHash]; } diff --git a/Common/cpp/SharedItems/FrozenObject.cpp b/Common/cpp/SharedItems/FrozenObject.cpp index 9c2c2c3a5be..029ef9f534b 100644 --- a/Common/cpp/SharedItems/FrozenObject.cpp +++ b/Common/cpp/SharedItems/FrozenObject.cpp @@ -4,18 +4,19 @@ namespace reanimated { -FrozenObject::FrozenObject(jsi::Runtime &rt, const jsi::Object &object, NativeReanimatedModule *module) { +FrozenObject::FrozenObject(jsi::Runtime &rt, const jsi::Object &object, NativeReanimatedModule *module, const int customThreadId) : customThreadId(customThreadId) { auto propertyNames = object.getPropertyNames(rt); for (size_t i = 0, count = propertyNames.size(rt); i < count; i++) { auto propertyName = propertyNames.getValueAtIndex(rt, i).asString(rt); - map[propertyName.utf8(rt)] = ShareableValue::adapt(rt, object.getProperty(rt, propertyName), module); + map[propertyName.utf8(rt)] = ShareableValue::adapt(rt, object.getProperty(rt, propertyName), module, ValueType::UndefinedType, customThreadId); } } -jsi::Object FrozenObject::shallowClone(jsi::Runtime &rt) { +jsi::Object FrozenObject::shallowClone(jsi::Runtime &rt, const int customThreadId) { + this->customThreadId = (this->customThreadId == -1 && this->customThreadId != customThreadId) ? customThreadId : this->customThreadId; jsi::Object object(rt); for (auto prop : map) { - object.setProperty(rt, jsi::String::createFromUtf8(rt, prop.first), prop.second->getValue(rt)); + object.setProperty(rt, jsi::String::createFromUtf8(rt, prop.first), prop.second->getValue(rt, customThreadId)); } return object; } diff --git a/Common/cpp/SharedItems/ShareableValue.cpp b/Common/cpp/SharedItems/ShareableValue.cpp index 92401e37c24..3fda1a488ea 100644 --- a/Common/cpp/SharedItems/ShareableValue.cpp +++ b/Common/cpp/SharedItems/ShareableValue.cpp @@ -52,7 +52,7 @@ void ShareableValue::adaptCache(jsi::Runtime &rt, const jsi::Value &value) { } void ShareableValue::adapt(jsi::Runtime &rt, const jsi::Value &value, ValueType objectType) { - bool isRNRuntime = !(module->isUIRuntime(rt)); + bool isNotUIRuntime = !(module->isUIRuntime(rt)); if (value.isObject()) { jsi::Object object = value.asObject(rt); jsi::Value hiddenValue = object.getProperty(rt, HIDDEN_HOST_OBJECT_PROP); @@ -99,8 +99,8 @@ void ShareableValue::adapt(jsi::Runtime &rt, const jsi::Value &value, ValueType } else { // a worklet type = ValueType::WorkletFunctionType; - frozenObject = std::make_shared(rt, object, module); - if (isRNRuntime) { + frozenObject = std::make_shared(rt, object, module, customThreadId); + if (isNotUIRuntime) { addHiddenProperty(rt, createHost(rt, frozenObject), object, HIDDEN_HOST_OBJECT_PROP); } } @@ -124,8 +124,8 @@ void ShareableValue::adapt(jsi::Runtime &rt, const jsi::Value &value, ValueType } else { // create frozen object based on a copy of a given object type = ValueType::ObjectType; - frozenObject = std::make_shared(rt, object, module); - if (isRNRuntime) { + frozenObject = std::make_shared(rt, object, module, customThreadId); + if (isNotUIRuntime) { addHiddenProperty(rt, createHost(rt, frozenObject), object, HIDDEN_HOST_OBJECT_PROP); freeze(rt, object); } @@ -138,13 +138,13 @@ void ShareableValue::adapt(jsi::Runtime &rt, const jsi::Value &value, ValueType } } -std::shared_ptr ShareableValue::adapt(jsi::Runtime &rt, const jsi::Value &value, NativeReanimatedModule *module, ValueType valueType) { - auto sv = std::shared_ptr(new ShareableValue(module, module->scheduler)); +std::shared_ptr ShareableValue::adapt(jsi::Runtime &rt, const jsi::Value &value, NativeReanimatedModule *module, ValueType valueType, const int customThreadId) { + auto sv = std::shared_ptr(new ShareableValue(module, module->scheduler, customThreadId)); sv->adapt(rt, value, valueType); return sv; } -jsi::Value ShareableValue::getValue(jsi::Runtime &rt) { +jsi::Value ShareableValue::getValue(jsi::Runtime &rt, const int customThreadId) { // TODO: maybe we can cache toJSValue results on a per-runtime basis, need to avoid ref loops if (module->isUIRuntime(rt)) { if (remoteValue.expired()) { @@ -157,7 +157,11 @@ jsi::Value ShareableValue::getValue(jsi::Runtime &rt) { } return jsi::Value(rt, *remoteValue.lock()); } else { - if (hostValue.get() == nullptr) { + std::string s = hostValue.get() == nullptr ? "true" : "false"; + if (hostValue.get() == nullptr || customThreadId != -1) { + // recreate objects for custom threads, because for every one of them + // there is a separate RT - we have to avoid errors caused by + // accessing the value created with a different RT hostValue = std::make_unique(rt, toJSValue(rt)); } return jsi::Value(rt, *hostValue); @@ -168,9 +172,9 @@ jsi::Object ShareableValue::createHost(jsi::Runtime &rt, std::shared_ptr frozenObject) { +jsi::Value createFrozenWrapper(jsi::Runtime &rt, std::shared_ptr frozenObject, const int customThreadId) { jsi::Object __reanimatedHiddenHost = jsi::Object::createFromHostObject(rt, frozenObject); - jsi::Object obj = frozenObject->shallowClone(rt); + jsi::Object obj = frozenObject->shallowClone(rt, customThreadId); jsi::Object globalObject = rt.global().getPropertyAsObject(rt, "Object"); jsi::Function freeze = globalObject.getPropertyAsFunction(rt, "freeze"); addHiddenProperty(rt, std::move(__reanimatedHiddenHost), obj, HIDDEN_HOST_OBJECT_PROP); @@ -191,7 +195,7 @@ jsi::Value ShareableValue::toJSValue(jsi::Runtime &rt) { case ValueType::StringType: return jsi::Value(rt, jsi::String::createFromAscii(rt, stringValue)); case ValueType::ObjectType: - return createFrozenWrapper(rt, frozenObject); + return createFrozenWrapper(rt, frozenObject, customThreadId); case ValueType::ArrayType: { jsi::Array array(rt, frozenArray.size()); for (size_t i = 0; i < frozenArray.size(); i++) { @@ -200,7 +204,7 @@ jsi::Value ShareableValue::toJSValue(jsi::Runtime &rt) { return array; } case ValueType::RemoteObjectType: - if (module->isUIRuntime(rt)) { + if (module->isUIRuntime(rt) || customThreadId != -1) { // todo check this(custom threads) remoteObject->maybeInitializeOnUIRuntime(rt); } return createHost(rt, remoteObject); @@ -270,11 +274,13 @@ jsi::Value ShareableValue::toJSValue(jsi::Runtime &rt) { case ValueType::WorkletFunctionType: auto module = this->module; auto frozenObject = this->frozenObject; - if (module->isUIRuntime(rt)) { + if (module->isUIRuntime(rt) || customThreadId != -1) { // when running on UI thread we prep a function + // for the custom threads we also just want to prepare - auto jsThis = std::make_shared(frozenObject->shallowClone(*module->runtime)); - std::shared_ptr funPtr(module->workletsCache->getFunction(rt, frozenObject)); + auto jsThis = std::make_shared(frozenObject->shallowClone(rt, customThreadId)); + // cache will not work for custom threads because for every thread we have a different RT + std::shared_ptr funPtr(module->workletsCache->getFunction(rt, frozenObject, customThreadId)); auto name = funPtr->getProperty(rt, "name").asString(rt).utf8(rt); auto clb = [=]( @@ -332,7 +338,7 @@ jsi::Value ShareableValue::toJSValue(jsi::Runtime &rt) { retain_this->module->scheduler->scheduleOnUI([retain_this, params] { NativeReanimatedModule *module = retain_this->module; jsi::Runtime &rt = *module->runtime.get(); - auto jsThis = createFrozenWrapper(rt, retain_this->frozenObject).getObject(rt); + auto jsThis = createFrozenWrapper(rt, retain_this->frozenObject, retain_this->customThreadId).getObject(rt); auto code = jsThis.getProperty(rt, "asString").asString(rt).utf8(rt); std::shared_ptr funPtr(retain_this->module->workletsCache->getFunction(rt, retain_this->frozenObject)); diff --git a/Common/cpp/Tools/RuntimeDecorator.cpp b/Common/cpp/Tools/RuntimeDecorator.cpp index d5b43540a86..8007b8f40ac 100644 --- a/Common/cpp/Tools/RuntimeDecorator.cpp +++ b/Common/cpp/Tools/RuntimeDecorator.cpp @@ -5,7 +5,61 @@ namespace reanimated { -void RuntimeDecorator::addNativeObjects(jsi::Runtime &rt, +void RuntimeDecorator::decorateCustomThread(jsi::Runtime &rt) { + rt.global().setProperty(rt, "_WORKLET", jsi::Value(true)); + + jsi::Object dummyGlobal(rt); + auto dummyFunction = []( + jsi::Runtime &rt, + const jsi::Value &thisValue, + const jsi::Value *args, + size_t count + ) -> jsi::Value { + return jsi::Value::undefined(); + }; + jsi::Function __reanimatedWorkletInit = jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forAscii(rt, "__reanimatedWorkletInit"), 1, dummyFunction); + + dummyGlobal.setProperty(rt, "__reanimatedWorkletInit", __reanimatedWorkletInit); + rt.global().setProperty(rt, "global", dummyGlobal); + + rt.global().setProperty(rt, "jsThis", jsi::Value::undefined()); + + auto callback = []( + jsi::Runtime &rt, + const jsi::Value &thisValue, + const jsi::Value *args, + size_t count + ) -> jsi::Value { + const jsi::Value *value = &args[0]; + if (value->isString()) { + Logger::log(value->getString(rt).utf8(rt).c_str()); + } else if (value->isNumber()) { + Logger::log(value->getNumber()); + } else if (value->isUndefined()) { + Logger::log("undefined"); + } else { + Logger::log("unsupported value type"); + } + return jsi::Value::undefined(); + }; + jsi::Value log = jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forAscii(rt, "_log"), 1, callback); + rt.global().setProperty(rt, "_log", log); + + auto clb5 = []( + jsi::Runtime &rt, + const jsi::Value &thisValue, + const jsi::Value *args, + size_t count + ) -> jsi::Value { + rt.global().setProperty(rt, "console", args[0]); + return jsi::Value::undefined(); + }; + jsi::Value setGlobalConsole = jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forAscii(rt, "_setGlobalConsole"), 1, clb5); + rt.global().setProperty(rt, "_setGlobalConsole", setGlobalConsole); +} + + +void RuntimeDecorator::decorateUI(jsi::Runtime &rt, UpdaterFunction updater, RequestFrameFunction requestFrame, ScrollToFunction scrollTo, @@ -14,7 +68,7 @@ void RuntimeDecorator::addNativeObjects(jsi::Runtime &rt, rt.global().setProperty(rt, "_WORKLET", jsi::Value(true)); jsi::Object dummyGlobal(rt); - auto dummyFunction = [requestFrame]( + auto dummyFunction = []( jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, diff --git a/Common/cpp/headers/NativeModules/NativeReanimatedModule.h b/Common/cpp/headers/NativeModules/NativeReanimatedModule.h index 258903a397c..a64352baf6a 100644 --- a/Common/cpp/headers/NativeModules/NativeReanimatedModule.h +++ b/Common/cpp/headers/NativeModules/NativeReanimatedModule.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include namespace reanimated { @@ -31,7 +33,8 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec std::unique_ptr rt, std::shared_ptr errorHandler, std::function propObtainer, - PlatformDepMethodsHolder platformDepMethodsHolder); + PlatformDepMethodsHolder platformDepMethodsHolder, + std::function()> runtimeObtainer); virtual ~NativeReanimatedModule(); @@ -48,7 +51,9 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec void unregisterEventHandler(jsi::Runtime &rt, const jsi::Value ®istrationId) override; jsi::Value getViewProp(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &propName, const jsi::Value &callback) override; - + + jsi::Value spawnThread(jsi::Runtime &rt, const jsi::Value &operations) override; + void onRender(double timestampMs); void onEvent(std::string eventName, std::string eventAsString); bool isAnyHandlerWaitingForEvent(std::string eventName); @@ -67,11 +72,19 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec std::vector frameCallbacks; bool renderRequested = false; std::function propObtainer; + std::function()> runtimeObtainer; public: std::shared_ptr errorHandler; std::shared_ptr workletsCache; std::shared_ptr valueSetter; std::shared_ptr scheduler; + + struct Th { + std::unique_ptr rt; + std::shared_ptr thread; + }; + int currentThreadId = 0; + std::unordered_map> threads; }; } // namespace reanimated diff --git a/Common/cpp/headers/NativeModules/NativeReanimatedModuleSpec.h b/Common/cpp/headers/NativeModules/NativeReanimatedModuleSpec.h index aa6eb42f05a..a67ed022506 100644 --- a/Common/cpp/headers/NativeModules/NativeReanimatedModuleSpec.h +++ b/Common/cpp/headers/NativeModules/NativeReanimatedModuleSpec.h @@ -40,6 +40,8 @@ class JSI_EXPORT NativeReanimatedModuleSpec : public TurboModule { // views virtual jsi::Value getViewProp(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &propName, const jsi::Value &callback) = 0; + + virtual jsi::Value spawnThread(jsi::Runtime &rt, const jsi::Value &operations) = 0; }; } // namespace reanimated diff --git a/Common/cpp/headers/Registries/WorkletsCache.h b/Common/cpp/headers/Registries/WorkletsCache.h index 0ede04ce1c9..8f514c4dca1 100644 --- a/Common/cpp/headers/Registries/WorkletsCache.h +++ b/Common/cpp/headers/Registries/WorkletsCache.h @@ -14,8 +14,10 @@ class FrozenObject; class WorkletsCache { std::unordered_map> worklets; + std::shared_ptr obtainFunction(jsi::Runtime &rt, const std::string &code); public: - std::shared_ptr getFunction(jsi::Runtime & rt, std::shared_ptr frozenObj); + jsi::Function functionFromString(jsi::Runtime &rt, const std::string &code); + std::shared_ptr getFunction(jsi::Runtime & rt, std::shared_ptr frozenObj, const int customThreadId = -1); }; } // namespace reanimated diff --git a/Common/cpp/headers/SharedItems/FrozenObject.h b/Common/cpp/headers/SharedItems/FrozenObject.h index 126fd41d870..5c06b5232dd 100644 --- a/Common/cpp/headers/SharedItems/FrozenObject.h +++ b/Common/cpp/headers/SharedItems/FrozenObject.h @@ -19,11 +19,12 @@ class FrozenObject : public jsi::HostObject { private: std::unordered_map> map; + int customThreadId; public: - FrozenObject(jsi::Runtime &rt, const jsi::Object &object, NativeReanimatedModule *module); - jsi::Object shallowClone(jsi::Runtime &rt); + FrozenObject(jsi::Runtime &rt, const jsi::Object &object, NativeReanimatedModule *module, const int customThreadId = -1); + jsi::Object shallowClone(jsi::Runtime &rt, const int customThreadId = -1); }; } diff --git a/Common/cpp/headers/SharedItems/ShareableValue.h b/Common/cpp/headers/SharedItems/ShareableValue.h index 9790698801b..428d309344e 100644 --- a/Common/cpp/headers/SharedItems/ShareableValue.h +++ b/Common/cpp/headers/SharedItems/ShareableValue.h @@ -42,6 +42,7 @@ friend void extractMutables(jsi::Runtime &rt, std::shared_ptr remoteObjectInitializer; std::shared_ptr remoteObject; std::vector> frozenArray; + const int customThreadId; std::unique_ptr hostValue; std::weak_ptr remoteValue; @@ -50,16 +51,15 @@ friend void extractMutables(jsi::Runtime &rt, jsi::Object createHost(jsi::Runtime &rt, std::shared_ptr host); - ShareableValue(NativeReanimatedModule *module, std::shared_ptr s): StoreUser(s), module(module) {} + ShareableValue(NativeReanimatedModule *module, std::shared_ptr s, const int customThreadId = -1) : StoreUser(s), module(module), customThreadId(customThreadId) {} void adapt(jsi::Runtime &rt, const jsi::Value &value, ValueType objectType); void adaptCache(jsi::Runtime &rt, const jsi::Value &value); public: ValueType type = ValueType::UndefinedType; std::shared_ptr mutableValue; - static std::shared_ptr adapt(jsi::Runtime &rt, const jsi::Value &value, NativeReanimatedModule *module, ValueType objectType = ValueType::UndefinedType); - jsi::Value getValue(jsi::Runtime &rt); - + static std::shared_ptr adapt(jsi::Runtime &rt, const jsi::Value &value, NativeReanimatedModule *module, ValueType valueType = ValueType::UndefinedType, const int customThreadId = -1); + jsi::Value getValue(jsi::Runtime &rt, const int customThreadId = -1); }; } diff --git a/Common/cpp/headers/Tools/RuntimeDecorator.h b/Common/cpp/headers/Tools/RuntimeDecorator.h index 0b53361693f..ae315122a54 100644 --- a/Common/cpp/headers/Tools/RuntimeDecorator.h +++ b/Common/cpp/headers/Tools/RuntimeDecorator.h @@ -12,7 +12,8 @@ using RequestFrameFunction = std::function)>; class RuntimeDecorator { public: - static void addNativeObjects(jsi::Runtime &rt, + static void decorateCustomThread(jsi::Runtime &rt); + static void decorateUI(jsi::Runtime &rt, UpdaterFunction updater, RequestFrameFunction requestFrame, ScrollToFunction scrollTo, diff --git a/Example/src/AnimatedStyleUpdateExample.js b/Example/src/AnimatedStyleUpdateExample.js index b44a99d5bdc..b0263999a2d 100644 --- a/Example/src/AnimatedStyleUpdateExample.js +++ b/Example/src/AnimatedStyleUpdateExample.js @@ -3,40 +3,73 @@ import Animated, { withTiming, useAnimatedStyle, Easing, + spawnThread, + runOnUI, + runOnJS, } from 'react-native-reanimated'; import { View, Button } from 'react-native'; import React from 'react'; -export default function AnimatedStyleUpdateExample(props) { - const randomWidth = useSharedValue(10); +export default function App() { + const sv = useSharedValue(0); - const config = { - duration: 500, - easing: Easing.bezier(0.5, 0.01, 0, 1), - }; + console.log('here 1'); + // for(let i=0;i<3000000000;++i) {} + console.log('here 2'); + /* * / + useAnimatedStyle(() => { + sv; + console.log('here', _WORKLET) + return {}; + }) +/* + runOnUI(() => { + 'worklet'; + sv.value = 1; + console.log('> run on ui #1 begin', _WORKLET); + // for(let i=0;i<3000000000;++i) {} + console.log('> run on ui #1 end', _WORKLET); + })(); - const style = useAnimatedStyle(() => { - return { - width: withTiming(randomWidth.value, config), - }; + console.log('here 3'); +/* */ +/* */ + // thread 1 + const vvv = 99; + spawnThread(() => { + 'worklet'; + _log('> spawn thread #1 start ' + vvv); + sv.value = 1; + for (let i = 0; i < 3000000000; ++i) {} + sv.value = 2; + _log('> spawn thread #1 end'); + return Math.random() * 100; }); + // thread 2 + /* * / + spawnThread(() => { + 'worklet'; + _log('> spawn thread #2 start'); + // sv.value = 3; + for (let i = 0; i < 3000000000; ++i) {} + _log('> spawn thread #2 end'); + return Math.random() * 100; + }); + */ + // + + setTimeout(() => { + console.log('here timeout'); + }, 100); + console.log('here 4'); +/* */ return ( - - +