Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple version checking #4914

Merged
merged 35 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2987693
init
tjzel Aug 10, 2023
4e0c7ed
androidele
tjzel Aug 10, 2023
d2ab1e9
invertio
tjzel Aug 10, 2023
f4e02fc
renamele
tjzel Aug 10, 2023
0a71101
hmmm... bugs...
tjzel Aug 10, 2023
4fbba50
init
tjzel Aug 10, 2023
9fc54c5
Merge branch 'main' into @tjzel/troubleshooting
tjzel Aug 10, 2023
4311419
remove future
tjzel Aug 10, 2023
80edeeb
sharebale pls
tjzel Aug 10, 2023
ba3861c
test trobule
tjzel Aug 11, 2023
99982f0
url validator lets goooo 🧨
tjzel Aug 11, 2023
3c551d6
fix urls
tjzel Aug 11, 2023
ba149e3
self-review
tjzel Aug 16, 2023
5a58f09
mergele to trobuleshooting
tjzel Aug 16, 2023
6f38b70
fix CI
tjzel Aug 16, 2023
65ca4aa
remove old checker
tjzel Aug 18, 2023
c5c4d67
mergele to trobuleshooting
tjzel Aug 23, 2023
4a107e0
actually...
tjzel Aug 24, 2023
4a86f30
Merge branch 'main' into @tjzel/version-checker
tjzel Aug 24, 2023
bf20b6a
cpp eats java
tjzel Aug 25, 2023
7413264
no more drafties
tjzel Aug 25, 2023
dd68a13
patch matching for js version
tjzel Aug 25, 2023
3fc88aa
Merge branch 'main' into @tjzel/version-checker
tjzel Aug 25, 2023
78d1bbd
mergele main
tjzel Aug 28, 2023
35ba611
huh
tjzel Aug 28, 2023
848916f
ok
tjzel Aug 28, 2023
6d174f7
review changes
tjzel Aug 30, 2023
bd5f532
version checker
tjzel Sep 7, 2023
cc6c399
mergele main
tjzel Sep 7, 2023
87afd30
review changes
tjzel Sep 14, 2023
12b6180
mergele main
tjzel Sep 26, 2023
2b5e2fa
trobuleshouting
tjzel Sep 26, 2023
cfe6749
remove whitespace
tjzel Sep 26, 2023
b8e5081
trobuleshouting
tjzel Sep 26, 2023
10dfb4b
final touches
tjzel Sep 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Common/cpp/NativeModules/NativeReanimatedModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ jsi::Value NativeReanimatedModule::makeShareableClone(
shareable =
std::make_shared<ShareableString>(value.getSymbol(rt).toString(rt));
} else {
throw std::runtime_error("attempted to convert an unsupported value type");
throw std::runtime_error(
"[Reanimated] Attempted to convert an unsupported value type.");
}
return ShareableJSRef::newHostObject(rt, shareable);
}
Expand Down
8 changes: 4 additions & 4 deletions Common/cpp/ReanimatedRuntime/ReanimatedHermesRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ using namespace react;

// ReentrancyCheck is copied from React Native
// from ReactCommon/hermes/executor/HermesExecutorFactory.cpp
// https://github.com/facebook/react-native/blob/main/ReactCommon/hermes/executor/HermesExecutorFactory.cpp
// https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp
struct ReanimatedReentrancyCheck {
// This is effectively a very subtle and complex assert, so only
// include it in builds which would include asserts.
// This is effectively a very subtle and complex assert, so only
// include it in builds which would include asserts.
#ifndef NDEBUG
ReanimatedReentrancyCheck() : tid(std::thread::id()), depth(0) {}

Expand Down Expand Up @@ -110,7 +110,7 @@ struct ReanimatedReentrancyCheck {
// jsi::Runtime. So the inheritance is: ReanimatedHermesRuntime ->
// WithRuntimeDecorator -> DecoratedRuntime -> jsi::Runtime You can find out
// more about this in ReactCommon/jsi/jsi/Decorator.h or by following this link:
// https://github.com/facebook/react-native/blob/main/ReactCommon/jsi/jsi/decorator.h
// https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/jsi/jsi/decorator.h
class ReanimatedHermesRuntime
: public jsi::WithRuntimeDecorator<ReanimatedReentrancyCheck> {
public:
Expand Down
13 changes: 5 additions & 8 deletions Common/cpp/ReanimatedRuntime/RuntimeInitialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ _Last updated_: 13/09/2022 by @Kwasow

This document describes the current way of initializing Hermes and connecting
it to the debugger. The work I did was mainly based on
[HermesExecutorFactory.cpp](https://github.com/facebook/react-native/blob/main/ReactCommon/hermes/executor/HermesExecutorFactory.cpp)

[HermesExecutorFactory.cpp](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp)
from React Native.

## Runtime initalization
## Runtime initialization

If you take a look at `NativeProxy` (both on Android and iOS) you'll find
that it only makes a call to `ReanimatedRuntime::make(jsQueue)`. This
Expand Down Expand Up @@ -35,6 +36,7 @@ appended to the source code. The generated source map will be a base64 encoded
json.

A workletized function would look like this (after formattings):

```js
function _f(number) {
console.log(_WORKLET, number);
Expand All @@ -48,12 +50,7 @@ And the base64 string after decoding is:
{
"version": 3,
"mappings": "AAasB,SAACA,EAAD,CAACA,MAAD,EAAoB;AAEtCC,SAAO,CAACC,GAARD,CAAYE,QAAZF,EAAsBD,MAAtBC;AAFkB",
"names": [
"number",
"console",
"log",
"_WORKLET"
],
"names": ["number", "console", "log", "_WORKLET"],
"sources": [
"/Users/karol/Git/react-native-reanimated/FabricExample/src/WorkletExample.tsx"
],
Expand Down
5 changes: 1 addition & 4 deletions Common/cpp/SharedItems/Shareables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ std::shared_ptr<Shareable> extractShareableOrThrow(
} else if (maybeShareableValue.isUndefined()) {
return Shareable::undefined();
}
throw std::runtime_error(
errorMessage != nullptr
? errorMessage
: "expecting the object to be of type ShareableJSRef");
throw std::runtime_error(std::string("[Reanimated] ") + errorMessage);
tjzel marked this conversation as resolved.
Show resolved Hide resolved
}

Shareable::~Shareable() {}
Expand Down
15 changes: 7 additions & 8 deletions Common/cpp/SharedItems/Shareables.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,19 @@ class ShareableJSRef : public jsi::HostObject {
std::shared_ptr<Shareable> extractShareableOrThrow(
jsi::Runtime &rt,
const jsi::Value &maybeShareableValue,
const char *errorMessage = nullptr);
const char *errorMessage =
"expecting the object to be of type ShareableJSRef.");

template <typename T>
std::shared_ptr<T> extractShareableOrThrow(
jsi::Runtime &rt,
const jsi::Value &shareableRef,
const char *errorMessage = nullptr) {
const char *errorMessage =
"provided shareable object is of an incompatible type.") {
auto res = std::dynamic_pointer_cast<T>(
extractShareableOrThrow(rt, shareableRef, errorMessage));
if (!res) {
throw std::runtime_error(
errorMessage != nullptr
? errorMessage
: "provided shareable object is of an incompatible type");
throw std::runtime_error(std::string("[Reanimated] ") + errorMessage);
}
return res;
}
Expand Down Expand Up @@ -308,7 +307,7 @@ class ShareableHandle : public Shareable {
remoteValue_ = std::make_unique<jsi::Value>(
runtimeHelper_->valueUnpacker->call(rt, initObj));
initializer_ = nullptr; // we can release ref to initializer as this
// method should be called at most once
// method should be called at most once
}
return jsi::Value(rt, *remoteValue_);
}
Expand Down Expand Up @@ -401,7 +400,7 @@ class ShareableScalar : public Shareable {
return jsi::Value(data_.number);
default:
throw std::runtime_error(
"attempted to convert object that's not of a scalar type");
"[Reanimated] Attempted to convert object that's not of a scalar type.");
}
}

Expand Down
2 changes: 1 addition & 1 deletion Common/cpp/Tools/JSISerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ std::string JSISerializer::stringifyJSIValueRecursively(
return stringifyObject(object);
}

throw std::runtime_error("unsupported value type");
throw std::runtime_error("[Reanimated] Unsupported value type.");
}

std::string stringifyJSIValue(jsi::Runtime &rt, const jsi::Value &value) {
Expand Down
2 changes: 1 addition & 1 deletion Common/cpp/Tools/JsiUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ inline int get<int>(jsi::Runtime &, const jsi::Value *value) {
template <>
inline bool get<bool>(jsi::Runtime &, const jsi::Value *value) {
if (!value->isBool()) {
throw jsi::JSINativeException("Expected a boolean");
throw jsi::JSINativeException("[Reanimated] Expected a boolean.");
}
return value->getBool();
}
Expand Down
34 changes: 32 additions & 2 deletions Common/cpp/Tools/RuntimeDecorator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,35 @@ void RuntimeDecorator::decorateUIRuntime(
rt, "_maybeFlushUIUpdatesQueue", maybeFlushUIUpdatesQueueFunction);
}

#ifdef DEBUG
void versionCheck(jsi::Runtime &rnRuntime) {
tjzel marked this conversation as resolved.
Show resolved Hide resolved
auto rawCppVersion = getReanimatedVersionString(rnRuntime);
tjzel marked this conversation as resolved.
Show resolved Hide resolved

auto maybeJSVersion =
rnRuntime.global().getProperty(rnRuntime, "_REANIMATED_VERSION_JS");
if (maybeJSVersion.isUndefined()) {
throw std::runtime_error(
std::string(
"[Reanimated] Native side failed to resolved JS version of `react-native-reanimated`\n") +
"See `http://localhost:3000/react-native-reanimated/docs/guides/troubleshooting#reanimated-native-side-failed-to-resolved-js-version-of-react-native-reanimated` for more details.");
}

auto cppVersion = rawCppVersion.utf8(rnRuntime);
auto JSVersion = maybeJSVersion.asString(rnRuntime).utf8(rnRuntime);
tjzel marked this conversation as resolved.
Show resolved Hide resolved

if (JSVersion != cppVersion) {
throw std::runtime_error(
std::string(
"[Reanimated] Native mismatch between JS version of `react-native-reanimated` and C++ version (") +
cppVersion + " vs " + "JSVersion" + ")\n" +
tjzel marked this conversation as resolved.
Show resolved Hide resolved
"See `http://localhost:3000/react-native-reanimated/docs/guides/troubleshooting#reanimated-native-mismatch-between-js-version-of-react-native-reanimated-and-c-version` for more details.");
}

rnRuntime.global().setProperty(
rnRuntime, "_REANIMATED_VERSION_CPP", rawCppVersion);
tjzel marked this conversation as resolved.
Show resolved Hide resolved
}
#endif // DEBUG

void RuntimeDecorator::decorateRNRuntime(
jsi::Runtime &rnRuntime,
const std::shared_ptr<jsi::Runtime> &uiRuntime,
Expand All @@ -178,8 +207,9 @@ void RuntimeDecorator::decorateRNRuntime(
#endif // RCT_NEW_ARCH_ENABLED
rnRuntime.global().setProperty(rnRuntime, "_IS_FABRIC", isFabric);

auto version = getReanimatedVersionString(rnRuntime);
rnRuntime.global().setProperty(rnRuntime, "_REANIMATED_VERSION_CPP", version);
#ifdef DEBUG
versionCheck(rnRuntime);
#endif // DEBUG

rnRuntime.global().setProperty(
rnRuntime, "_REANIMATED_IS_REDUCED_MOTION", isReducedMotion);
Expand Down
2 changes: 1 addition & 1 deletion Common/cpp/hidden_headers/Logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Logger {
template <typename T>
static void log(T value) {
if (instance == nullptr) {
throw std::runtime_error("no logger specified");
throw std::runtime_error("[Reanimated] No logger specified.");
}
instance->log(value);
}
Expand Down
2 changes: 1 addition & 1 deletion Example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ SPEC CHECKSUMS:
RNCMaskedView: 949696f25ec596bfc697fc88e6f95cf0c79669b6
RNCPicker: 0bc2f0a29abcca7b7ed44a2d036aac9ab6d25700
RNGestureHandler: dec4645026e7401a0899f2846d864403478ff6a5
RNReanimated: 66449430e0bed3c23148db98996f4925da8fe514
RNReanimated: 78e95d382de14fe5bdff1dad15f0c566eac65c8e
RNScreens: 6a8a3c6b808aa48dca1780df7b73ea524f602c63
RNSVG: 53c661b76829783cdaf9b7a57258f3d3b4c28315
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Expand Down
2 changes: 1 addition & 1 deletion __tests__/matrixUtils.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ describe('Matrix util functions', () => {
[1, 1, 1, 0],
];
expect(() => decomposeMatrix(incorrectMatrix)).toThrowError(
new Error('Invalid transform matrix!')
new Error('[Reanimated] Invalid transform matrix!')
);
});

Expand Down
89 changes: 12 additions & 77 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@ def resolveReactNativeDirectory() {
}

throw new GradleException(
"[Reanimated] Unable to resolve react-native location in " +
"node_modules. You should project extension property (in app/build.gradle) " +
"`REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
"[Reanimated] Unable to resolve react-native location in node_modules. You should project extension property (in `app/build.gradle`) `REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
)
}

Expand All @@ -109,19 +107,11 @@ def getPlaygroundAppName() { // only for the development
}
})
} catch (_) {
throw new GradleException("Couldn't determine playground app name.")
throw new GradleException("[Reanimated] Couldn't determine playground app name.")
}
return playgroundAppName
}

def shouldAssertNoMultipleInstances() {
if (rootProject.hasProperty("disableMultipleInstancesCheck")) {
return rootProject.property("disableMultipleInstancesCheck") != "true"
} else {
return true
}
}

def getReanimatedVersion() {
def inputFile = file(projectDir.path + '/../package.json')
def json = new JsonSlurper().parseText(inputFile.text)
Expand Down Expand Up @@ -258,7 +248,8 @@ android {
targetSdkVersion safeExtGet("targetSdkVersion", 30)
versionCode 1
versionName "1.0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", IS_NEW_ARCHITECTURE_ENABLED.toString()
buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", IS_NEW_ARCHITECTURE_ENABLED.toString())
buildConfigField("String", "_REANIMATED_VERSION_JAVA", "\"${REANIMATED_VERSION}\"")
tjzel marked this conversation as resolved.
Show resolved Hide resolved
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared",
Expand Down Expand Up @@ -391,73 +382,17 @@ android {
}
}

abstract class NoMultipleInstancesAssertionTask extends DefaultTask {
@Inject abstract ObjectFactory getObjectFactory()

@Input abstract Property<File> getProjectDirFile()
@Input abstract Property<File> getRootDirFile()
@Input abstract Property<Boolean> getShouldCheck()

def findReanimatedInstancesForPath(String path) {
return objectFactory.fileTree().from(path)
.include("**/react-native-reanimated/package.json")
.exclude("**/.yarn/**")
.exclude({ Files.isSymbolicLink(it.getFile().toPath()) })
.findAll()
}

@TaskAction
def check() {
if (shouldCheck.get()) {
// Assert there are no multiple installations of Reanimated
Set<File> files

if (projectDirFile.get().parent.contains(rootDirFile.get().parent)) {
// standard app
files = findReanimatedInstancesForPath(rootDirFile.get().parent + "/node_modules")
} else {
// monorepo
files = findReanimatedInstancesForPath(rootDirFile.get().parent + "/node_modules")
files.addAll(
findReanimatedInstancesForPath(projectDirFile.get().parentFile.parent)
)
}

if (files.size() > 1) {
String parsedLocation = files.stream().map({
File file -> "- " + file.toString().replace("/package.json", "")
}).collect().join("\n")
String exceptionMessage = "\n[react-native-reanimated] Multiple versions of Reanimated " +
"were detected. Only one instance of react-native-reanimated can be installed in a " +
"project. You need to resolve the conflict manually. Check out the documentation: " +
"https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/" +
"troubleshooting#multiple-versions-of-reanimated-were-detected \n\nConflict " +
"between: \n" + parsedLocation + "\n"
throw new GradleException(exceptionMessage)
}
}
}
}

tasks.register('assertNoMultipleInstances', NoMultipleInstancesAssertionTask) {
shouldCheck = shouldAssertNoMultipleInstances()
rootDirFile = rootDir
projectDirFile = projectDir
}

def assertLatestReactNativeWithNewArchitecture = task assertLatestReactNativeWithNewArchitectureTask {
onlyIf { IS_NEW_ARCHITECTURE_ENABLED && REANIMATED_MAJOR_VERSION == 3 && REACT_NATIVE_MINOR_VERSION < 72 }
doFirst {
throw new GradleException(
"\n[react-native-reanimated] Reanimated " + REANIMATED_VERSION + " supports the New Architecture " +
"only on the latest minor release of React Native. Please upgrade to React Native 0.72.0+ " +
"or downgrade to an older version of Reanimated v3."
"\n[Reanimated] Outdated version of `react-native` for New Architecture. Reanimated " + REANIMATED_VERSION + " supports the New Architecture on React Native 0.72.0+."
)
}
}

tasks.preBuild {
dependsOn assertNoMultipleInstances, assertLatestReactNativeWithNewArchitecture
dependsOn assertLatestReactNativeWithNewArchitecture
}

task cleanCmakeCache() {
Expand Down Expand Up @@ -716,7 +651,7 @@ if (REACT_NATIVE_MINOR_VERSION < 71) {
"${resolveBuildType()}.aar"
)
if (!hermesAAR.exists()) {
throw new GradleException("Could not find hermes-engine AAR", null)
throw new GradleException("[Reanimated] Could not find hermes-engine AAR.", null)
}

def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })
Expand All @@ -731,12 +666,12 @@ if (REACT_NATIVE_MINOR_VERSION < 71) {
doLast {
def hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine")
if (!hermesPackagePath) {
throw new GradleException("Could not find the hermes-engine npm package", null)
throw new GradleException("[Reanimated] Could not find the hermes-engine npm package.", null)
}

def hermesAAR = file("$hermesPackagePath/android/hermes-${resolveBuildType()}.aar") // e.g. hermes-debug.aar
if (!hermesAAR.exists()) {
throw new GradleException("The hermes-engine npm package is missing \"android/hermes-${resolveBuildType()}.aar\"", null)
throw new GradleException("[Reanimated] The hermes-engine npm package is missing \"android/hermes-${resolveBuildType()}.aar\".", null)
}

def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })
Expand All @@ -757,12 +692,12 @@ if (REACT_NATIVE_MINOR_VERSION < 71) {
doLast {
def jscPackagePath = findNodeModulePath(projectDir, "jsc-android")
if (!jscPackagePath) {
throw new GradleException("Could not find the jsc-android npm package", null)
throw new GradleException("[Reanimated] Could not find the jsc-android npm package.", null)
}

def jscDist = file("$jscPackagePath/dist")
if (!jscDist.exists()) {
throw new GradleException("The jsc-android npm package is missing its \"dist\" directory", null)
throw new GradleException("[Reanimated] The jsc-android npm package is missing its \"dist\" directory.", null)
}

def jscAAR = fileTree(jscDist).matching({ it.include "**/android-jsc/**/*.aar" }).singleFile
Expand Down Expand Up @@ -938,6 +873,6 @@ afterEvaluate {
extractSOFiles.dependsOn(prepareJSC)
}
} else {
throw GradleScriptException("Unknown JS runtime ${JS_RUNTIME}.")
throw GradleScriptException("[Reanimated] Unknown JS runtime ${JS_RUNTIME}.")
}
}
Loading