2019-09-26 17:30:28 -07:00
|
|
|
/*
|
2021-12-30 15:08:43 -08:00
|
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
2019-09-26 17:30:28 -07:00
|
|
|
*
|
2019-10-15 10:30:08 -07:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2019-09-26 17:30:28 -07:00
|
|
|
*/
|
2019-10-15 10:30:08 -07:00
|
|
|
|
2019-09-26 17:30:28 -07:00
|
|
|
#include "jni.h"
|
|
|
|
#include "YGJNIVanilla.h"
|
2019-10-08 14:23:57 -07:00
|
|
|
#include <cstring>
|
2019-10-08 14:23:57 -07:00
|
|
|
#include "YGJNI.h"
|
2019-10-08 17:48:32 -07:00
|
|
|
#include "common.h"
|
|
|
|
#include "YGJTypesVanilla.h"
|
2019-10-08 17:48:32 -07:00
|
|
|
#include <iostream>
|
2019-10-09 09:26:47 -07:00
|
|
|
#include <memory>
|
2019-12-02 05:21:56 -08:00
|
|
|
#include "YogaJniException.h"
|
2023-09-12 19:08:55 -07:00
|
|
|
#include "LayoutContext.h"
|
2019-10-08 17:48:32 -07:00
|
|
|
|
C++ Cleanup 8/N: Yoga-internal (#1355)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1355
X-link: https://github.com/facebook/react-native/pull/39198
## This diff
This splits up `Yoga-internal.h` which has become a grab bag. The actual header is left, with the purpose of being a private C ABI for bindings, but everything else is moved to a place more appropriate or removed.
A few notes:
1. `yoga::isUndefined` is replaced with `std::isnan` to avoid a layer of indirection (we will never be able to change its representation anyway). Internal usages of `YGFloatIsUndefined` are also replaced with `std::isnan` since the previous being at a library boundary means I'm not sure it can be inlined/.
2. `leading`, `trailing` arrays are factored into proper functions
3. `Values` is replaced entirely with `std::array`, since most of it was unused.
## This stack
The organization of the C++ internals of Yoga are in need of attention.
1. Some of the C++ internals are namespaced, but others not.
2. Some of the namespaces include `detail`, but are meant to be used outside of the translation unit (FB Clang Tidy rules warn on any usage of these)
2. Most of the files are in a flat hierarchy, except for event tracing in its own folder
3. Some files and functions begin with YG, others don’t
4. Some functions are uppercase, others are not
5. Almost all of the interesting logic is in Yoga.cpp, and the file is too large to reason about
6. There are multiple grab bag files where folks put random functions they need in (Utils, BitUtils, Yoga-Internal.h)
7. There is no clear indication from file structure or type naming what is private vs not
8. Handles like `YGNodeRef` and `YGConfigRef` can be used to access internals just by importing headers
This stack does some much needed spring cleaning:
1. All non-public headers and C++ implementation details are in separate folders from the root level `yoga`. This will give us room to split up logic and add more files without too large a flat hierarchy
3. All private C++ internals are under the `facebook::yoga` namespace. Details namespaces are only ever used within the same header, as they are intended
4. Utils files are split
5. Most C++ internals drop the YG prefix
6. Most C++ internal function names are all lower camel case
7. We start to split up Yoga.cpp
8. Every header beginning with YG or at the top-level directory is public and C only, with the exception of Yoga-Internal.h which has non-public functions for bindings
9. It is not possible to use private APIs without static casting handles to internal classes
This will give us more leeway to continue splitting monolithic files, and consistent guidelines for style in new files as well.
These changes should not be breaking to any project using only public Yoga headers. This includes every usage of Yoga in fbsource except for RN Fabric which is currently tied to internals. This refactor should make that boundary clearer.
Reviewed By: rshest
Differential Revision: D48769241
fbshipit-source-id: 5b8e2192309539e7c133c3b3b29b445b59dd5835
2023-09-04 11:20:17 -07:00
|
|
|
#include <yoga/Yoga-internal.h>
|
2023-09-08 13:03:48 -07:00
|
|
|
#include <yoga/bits/BitCast.h>
|
C++ Cleanup 8/N: Yoga-internal (#1355)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1355
X-link: https://github.com/facebook/react-native/pull/39198
## This diff
This splits up `Yoga-internal.h` which has become a grab bag. The actual header is left, with the purpose of being a private C ABI for bindings, but everything else is moved to a place more appropriate or removed.
A few notes:
1. `yoga::isUndefined` is replaced with `std::isnan` to avoid a layer of indirection (we will never be able to change its representation anyway). Internal usages of `YGFloatIsUndefined` are also replaced with `std::isnan` since the previous being at a library boundary means I'm not sure it can be inlined/.
2. `leading`, `trailing` arrays are factored into proper functions
3. `Values` is replaced entirely with `std::array`, since most of it was unused.
## This stack
The organization of the C++ internals of Yoga are in need of attention.
1. Some of the C++ internals are namespaced, but others not.
2. Some of the namespaces include `detail`, but are meant to be used outside of the translation unit (FB Clang Tidy rules warn on any usage of these)
2. Most of the files are in a flat hierarchy, except for event tracing in its own folder
3. Some files and functions begin with YG, others don’t
4. Some functions are uppercase, others are not
5. Almost all of the interesting logic is in Yoga.cpp, and the file is too large to reason about
6. There are multiple grab bag files where folks put random functions they need in (Utils, BitUtils, Yoga-Internal.h)
7. There is no clear indication from file structure or type naming what is private vs not
8. Handles like `YGNodeRef` and `YGConfigRef` can be used to access internals just by importing headers
This stack does some much needed spring cleaning:
1. All non-public headers and C++ implementation details are in separate folders from the root level `yoga`. This will give us room to split up logic and add more files without too large a flat hierarchy
3. All private C++ internals are under the `facebook::yoga` namespace. Details namespaces are only ever used within the same header, as they are intended
4. Utils files are split
5. Most C++ internals drop the YG prefix
6. Most C++ internal function names are all lower camel case
7. We start to split up Yoga.cpp
8. Every header beginning with YG or at the top-level directory is public and C only, with the exception of Yoga-Internal.h which has non-public functions for bindings
9. It is not possible to use private APIs without static casting handles to internal classes
This will give us more leeway to continue splitting monolithic files, and consistent guidelines for style in new files as well.
These changes should not be breaking to any project using only public Yoga headers. This includes every usage of Yoga in fbsource except for RN Fabric which is currently tied to internals. This refactor should make that boundary clearer.
Reviewed By: rshest
Differential Revision: D48769241
fbshipit-source-id: 5b8e2192309539e7c133c3b3b29b445b59dd5835
2023-09-04 11:20:17 -07:00
|
|
|
|
C++ Cleanup 2/N: Reorganize YGConfig (#1348)
Summary:
X-link: https://github.com/facebook/react-native/pull/39218
X-link: https://github.com/facebook/react-native/pull/39169
Pull Request resolved: https://github.com/facebook/yoga/pull/1348
## This diff
This diff adds a top level `config` directory for code related to configuring Yoga and Yoga Nodes.
The public API for config handles is `YGConfigRef`, which is forward declared to be a pointer to a struct named `YGConfig`. The existing `YGConfig` is split into `yoga::Config`, as the private C++ implementation, inheriting from `YGConfig`, a marker type represented as an empty struct. The public API continues to accept `YGConfigRef`, which continues to be `YGConfig *`, but it must be cast to its concrete internal representation at the API boundary before doing work on it.
## This stack
The organization of the C++ internals of Yoga are in need of attention.
1. Some of the C++ internals are namespaced, but others not.
2. Some of the namespaces include `detail`, but are meant to be used outside of the translation unit (FB Clang Tidy rules warn on any usage of these)
2. Most of the files are in a flat hierarchy, except for event tracing in its own folder
3. Some files and functions begin with YG, others don’t
4. Some functions are uppercase, others are not
5. Almost all of the interesting logic is in Yoga.cpp, and the file is too large to reason about
6. There are multiple grab bag files where folks put random functions they need in (Utils, BitUtils, Yoga-Internal.h)
7. There is no clear indication from file structure or type naming what is private vs not
8. Handles like `YGNodeRef` and `YGConfigRef` can be used to access internals just by importing headers
This stack does some much needed spring cleaning:
1. All non-public headers and C++ implementation details are in separate folders from the root level `yoga`. This will give us room to split up logic and add more files without too large a flat hierarchy
3. All private C++ internals are under the `facebook::yoga` namespace. Details namespaces are only ever used within the same header, as they are intended
4. Utils files are split
5. Most C++ internals drop the YG prefix
6. Most C++ internal function names are all lower camel case
7. We start to split up Yoga.cpp
8. Every header beginning with YG or at the top-level directory is public and C only, with the exception of Yoga-Internal.h which has non-public functions for bindings
9. It is not possible to use private APIs without static casting handles to internal classes
This will give us more leeway to continue splitting monolithic files, and consistent guidelines for style in new files as well.
These changes should not be breaking to any project using only public Yoga headers. This includes every usage of Yoga in fbsource except for RN Fabric which is currently tied to internals. This refactor should make that boundary clearer.
Changelog: [Internal]
Reviewed By: shwanton
Differential Revision: D48847257
fbshipit-source-id: 7a2157d169ba80a6f79620693ae45bb10dfca5a3
2023-08-30 16:27:32 -07:00
|
|
|
using namespace facebook;
|
|
|
|
using namespace facebook::yoga;
|
2019-10-08 17:48:32 -07:00
|
|
|
using namespace facebook::yoga::vanillajni;
|
|
|
|
|
2023-09-12 19:08:55 -07:00
|
|
|
static inline ScopedLocalRef<jobject> YGNodeJobject(YGNodeConstRef node) {
|
|
|
|
return LayoutContext::getNodeMap()->ref(node);
|
2019-10-08 17:48:32 -07:00
|
|
|
}
|
2019-09-26 17:30:28 -07:00
|
|
|
|
|
|
|
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
|
|
|
|
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
|
|
|
|
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
|
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
static jlong jni_YGConfigNewJNI(JNIEnv* /*env*/, jobject /*obj*/) {
|
2019-10-08 14:23:57 -07:00
|
|
|
return reinterpret_cast<jlong>(YGConfigNew());
|
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
static void jni_YGConfigFreeJNI(
|
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
|
|
|
jlong nativePointer) {
|
2019-10-09 09:26:47 -07:00
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
// unique_ptr will destruct the underlying global_ref, if present.
|
|
|
|
auto context = std::unique_ptr<ScopedGlobalRef<jobject>>{
|
|
|
|
static_cast<ScopedGlobalRef<jobject>*>(YGConfigGetContext(config))};
|
|
|
|
YGConfigFree(config);
|
|
|
|
}
|
2019-10-08 14:23:57 -07:00
|
|
|
|
|
|
|
static void jni_YGConfigSetExperimentalFeatureEnabledJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint feature,
|
|
|
|
jboolean enabled) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
YGConfigSetExperimentalFeatureEnabled(
|
|
|
|
config, static_cast<YGExperimentalFeature>(feature), enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGConfigSetUseWebDefaultsJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jboolean useWebDefaults) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
YGConfigSetUseWebDefaults(config, useWebDefaults);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGConfigSetPrintTreeFlagJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jboolean enable) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
YGConfigSetPrintTreeFlag(config, enable);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGConfigSetPointScaleFactorJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jfloat pixelsInPoint) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
YGConfigSetPointScaleFactor(config, pixelsInPoint);
|
|
|
|
}
|
|
|
|
|
2023-04-27 06:48:04 -07:00
|
|
|
static void jni_YGConfigSetErrataJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2023-04-27 06:48:04 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint errata) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
YGConfigSetErrata(config, static_cast<YGErrata>(errata));
|
|
|
|
}
|
|
|
|
|
|
|
|
static jint jni_YGConfigGetErrataJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2023-04-27 06:48:04 -07:00
|
|
|
jlong nativePointer) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
return static_cast<jint>(YGConfigGetErrata(config));
|
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
static jlong jni_YGNodeNewJNI(JNIEnv* /*env*/, jobject /*obj*/) {
|
2019-10-08 17:48:32 -07:00
|
|
|
const YGNodeRef node = YGNodeNew();
|
2023-05-02 18:08:58 -07:00
|
|
|
YGNodeSetContext(node, YGNodeContext{}.asVoidPtr);
|
2019-10-08 17:48:32 -07:00
|
|
|
return reinterpret_cast<jlong>(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
static jlong jni_YGNodeNewWithConfigJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 17:48:32 -07:00
|
|
|
jlong configPointer) {
|
|
|
|
const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer));
|
2023-05-02 18:08:58 -07:00
|
|
|
YGNodeSetContext(node, YGNodeContext{}.asVoidPtr);
|
2019-10-08 17:48:32 -07:00
|
|
|
return reinterpret_cast<jlong>(node);
|
|
|
|
}
|
|
|
|
|
2019-10-09 09:26:47 -07:00
|
|
|
static int YGJNILogFunc(
|
2023-09-11 19:51:40 -07:00
|
|
|
const YGConfigConstRef config,
|
|
|
|
const YGNodeConstRef /*node*/,
|
2019-10-09 09:26:47 -07:00
|
|
|
YGLogLevel level,
|
|
|
|
const char* format,
|
|
|
|
va_list args) {
|
2023-08-18 00:07:51 -07:00
|
|
|
va_list argsCopy;
|
|
|
|
va_copy(argsCopy, args);
|
|
|
|
int result = vsnprintf(nullptr, 0, format, argsCopy);
|
2023-09-06 08:16:42 -07:00
|
|
|
std::vector<char> buffer(1 + static_cast<size_t>(result));
|
2019-10-09 09:26:47 -07:00
|
|
|
vsnprintf(buffer.data(), buffer.size(), format, args);
|
|
|
|
|
|
|
|
auto jloggerPtr =
|
|
|
|
static_cast<ScopedGlobalRef<jobject>*>(YGConfigGetContext(config));
|
|
|
|
if (jloggerPtr != nullptr) {
|
|
|
|
if (*jloggerPtr) {
|
|
|
|
JNIEnv* env = getCurrentEnv();
|
|
|
|
|
2022-08-30 18:49:10 -07:00
|
|
|
jclass cl = env->FindClass("com/facebook/yoga/YogaLogLevel");
|
2019-10-09 09:26:47 -07:00
|
|
|
static const jmethodID smethodId =
|
|
|
|
facebook::yoga::vanillajni::getStaticMethodId(
|
|
|
|
env, cl, "fromInt", "(I)Lcom/facebook/yoga/YogaLogLevel;");
|
|
|
|
ScopedLocalRef<jobject> logLevel =
|
|
|
|
facebook::yoga::vanillajni::callStaticObjectMethod(
|
|
|
|
env, cl, smethodId, level);
|
|
|
|
|
|
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
|
|
env, env->GetObjectClass((*jloggerPtr).get()));
|
|
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
|
|
env,
|
|
|
|
objectClass.get(),
|
|
|
|
"log",
|
|
|
|
"(Lcom/facebook/yoga/YogaLogLevel;Ljava/lang/String;)V");
|
|
|
|
facebook::yoga::vanillajni::callVoidMethod(
|
|
|
|
env,
|
|
|
|
(*jloggerPtr).get(),
|
|
|
|
methodId,
|
|
|
|
logLevel.get(),
|
|
|
|
env->NewStringUTF(buffer.data()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGConfigSetLoggerJNI(
|
|
|
|
JNIEnv* env,
|
2023-05-11 09:43:36 -07:00
|
|
|
jobject /*obj*/,
|
2019-10-09 09:26:47 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jobject logger) {
|
|
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
|
|
auto context =
|
|
|
|
reinterpret_cast<ScopedGlobalRef<jobject>*>(YGConfigGetContext(config));
|
|
|
|
|
|
|
|
if (logger) {
|
|
|
|
if (context == nullptr) {
|
|
|
|
context = new ScopedGlobalRef<jobject>();
|
|
|
|
YGConfigSetContext(config, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
*context = newGlobalRef(env, logger);
|
2023-09-12 19:08:55 -07:00
|
|
|
YGConfigSetLogger(config, YGJNILogFunc);
|
2019-10-09 09:26:47 -07:00
|
|
|
} else {
|
|
|
|
if (context != nullptr) {
|
|
|
|
delete context;
|
|
|
|
YGConfigSetContext(config, nullptr);
|
|
|
|
}
|
2020-07-06 03:41:19 -07:00
|
|
|
YGConfigSetLogger(config, nullptr);
|
2019-10-09 09:26:47 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix use-after-free if JNI Yoga nodes are garbage collected using multiple threads (#1279)
Summary:
X-link: https://github.com/facebook/react-native/pull/37243
X-link: https://github.com/facebook/litho/pull/944
Pull Request resolved: https://github.com/facebook/yoga/pull/1279
Java bindings for Yoga rely solely on garbage collection for memory management. Each Java `YogaNode` has references to its children and parent Java Nodes. This means, for a node to be garbage collected, it cannot be reachable from any user accessible node. Each node then has single ownership of a `YGNodeRef`. When the `YogaNode` is garbage collected, a finalizer is run to call `YGNodeFree` and free the underlying native Yoga Node.
This may cause a use-after-free if finalizers are run from multiple threads. This is because `YGNodeFree` does more than just freeing, but instead also interacts with its parent and children nodes to detach itself, and remove any dangling pointers. If multiple threads run finalizers at once, one may traverse and try to mutate a node which another is freeing.
Because we know the entire connected tree is dead, there is no need to remove dangling pointers, so I want to expose a way to just free a Yoga Node, without it mutating the tree as a side effect.
This adds a currently private `YGNodeDeallocate` that frees without traversal. Ideally from naming this is what `YGNodeFree` would do, but we think changing the behavior of that might be too disruptive to OSS. At the same time there may be other memory safety related API changes we would like to eventually make, so this isn't made public beyond the JNI bindings to prevent needing to transition more APIs.
Changelog: [Internal]
Reviewed By: rshest
Differential Revision: D45556206
fbshipit-source-id: 62a1394c6f6bdc2b437b388098ea362a0fbcd0f7
2023-05-10 22:52:48 -07:00
|
|
|
static void jni_YGNodeDeallocateJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
Fix use-after-free if JNI Yoga nodes are garbage collected using multiple threads (#1279)
Summary:
X-link: https://github.com/facebook/react-native/pull/37243
X-link: https://github.com/facebook/litho/pull/944
Pull Request resolved: https://github.com/facebook/yoga/pull/1279
Java bindings for Yoga rely solely on garbage collection for memory management. Each Java `YogaNode` has references to its children and parent Java Nodes. This means, for a node to be garbage collected, it cannot be reachable from any user accessible node. Each node then has single ownership of a `YGNodeRef`. When the `YogaNode` is garbage collected, a finalizer is run to call `YGNodeFree` and free the underlying native Yoga Node.
This may cause a use-after-free if finalizers are run from multiple threads. This is because `YGNodeFree` does more than just freeing, but instead also interacts with its parent and children nodes to detach itself, and remove any dangling pointers. If multiple threads run finalizers at once, one may traverse and try to mutate a node which another is freeing.
Because we know the entire connected tree is dead, there is no need to remove dangling pointers, so I want to expose a way to just free a Yoga Node, without it mutating the tree as a side effect.
This adds a currently private `YGNodeDeallocate` that frees without traversal. Ideally from naming this is what `YGNodeFree` would do, but we think changing the behavior of that might be too disruptive to OSS. At the same time there may be other memory safety related API changes we would like to eventually make, so this isn't made public beyond the JNI bindings to prevent needing to transition more APIs.
Changelog: [Internal]
Reviewed By: rshest
Differential Revision: D45556206
fbshipit-source-id: 62a1394c6f6bdc2b437b388098ea362a0fbcd0f7
2023-05-10 22:52:48 -07:00
|
|
|
jlong nativePointer) {
|
2019-10-08 14:23:57 -07:00
|
|
|
if (nativePointer == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
2023-05-11 13:30:49 -07:00
|
|
|
YGNodeDeallocate(node);
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
static void jni_YGNodeResetJNI(
|
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
|
|
|
jlong nativePointer) {
|
2019-10-08 14:23:57 -07:00
|
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
2023-05-02 18:08:58 -07:00
|
|
|
void* context = YGNodeGetContext(node);
|
2019-10-08 14:23:57 -07:00
|
|
|
YGNodeReset(node);
|
2023-05-02 18:08:58 -07:00
|
|
|
YGNodeSetContext(node, context);
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeInsertChildJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jlong childPointer,
|
|
|
|
jint index) {
|
|
|
|
YGNodeInsertChild(
|
2023-09-06 08:16:42 -07:00
|
|
|
_jlong2YGNodeRef(nativePointer),
|
|
|
|
_jlong2YGNodeRef(childPointer),
|
|
|
|
static_cast<uint32_t>(index));
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
2020-01-30 03:41:45 -08:00
|
|
|
static void jni_YGNodeSwapChildJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2020-01-30 03:41:45 -08:00
|
|
|
jlong nativePointer,
|
|
|
|
jlong childPointer,
|
|
|
|
jint index) {
|
|
|
|
YGNodeSwapChild(
|
2023-09-06 08:16:42 -07:00
|
|
|
_jlong2YGNodeRef(nativePointer),
|
|
|
|
_jlong2YGNodeRef(childPointer),
|
|
|
|
static_cast<uint32_t>(index));
|
2020-01-30 03:41:45 -08:00
|
|
|
}
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
static void jni_YGNodeSetIsReferenceBaselineJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jboolean isReferenceBaseline) {
|
|
|
|
YGNodeSetIsReferenceBaseline(
|
|
|
|
_jlong2YGNodeRef(nativePointer), isReferenceBaseline);
|
|
|
|
}
|
|
|
|
|
|
|
|
static jboolean jni_YGNodeIsReferenceBaselineJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer) {
|
|
|
|
return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer));
|
|
|
|
}
|
|
|
|
|
2023-05-02 18:08:58 -07:00
|
|
|
static void jni_YGNodeRemoveAllChildrenJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer) {
|
|
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
2023-05-02 18:08:58 -07:00
|
|
|
YGNodeRemoveAllChildren(node);
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeRemoveChildJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jlong childPointer) {
|
|
|
|
YGNodeRemoveChild(
|
|
|
|
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer));
|
|
|
|
}
|
|
|
|
|
2019-10-08 17:48:32 -07:00
|
|
|
static void YGTransferLayoutOutputsRecursive(
|
|
|
|
JNIEnv* env,
|
|
|
|
jobject thiz,
|
2023-09-12 19:08:55 -07:00
|
|
|
YGNodeRef root) {
|
2023-05-02 18:08:58 -07:00
|
|
|
if (!YGNodeGetHasNewLayout(root)) {
|
2019-10-08 17:48:32 -07:00
|
|
|
return;
|
|
|
|
}
|
2023-09-12 19:08:55 -07:00
|
|
|
auto obj = YGNodeJobject(root);
|
2019-10-08 17:48:32 -07:00
|
|
|
if (!obj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto edgesSet = YGNodeEdges{root};
|
|
|
|
|
|
|
|
bool marginFieldSet = edgesSet.has(YGNodeEdges::MARGIN);
|
|
|
|
bool paddingFieldSet = edgesSet.has(YGNodeEdges::PADDING);
|
|
|
|
bool borderFieldSet = edgesSet.has(YGNodeEdges::BORDER);
|
|
|
|
|
|
|
|
int fieldFlags = edgesSet.get();
|
|
|
|
fieldFlags |= HAS_NEW_LAYOUT;
|
|
|
|
|
|
|
|
const int arrSize = 6 + (marginFieldSet ? 4 : 0) + (paddingFieldSet ? 4 : 0) +
|
|
|
|
(borderFieldSet ? 4 : 0);
|
|
|
|
float arr[18];
|
2023-09-06 08:16:42 -07:00
|
|
|
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = static_cast<float>(fieldFlags);
|
2019-10-08 17:48:32 -07:00
|
|
|
arr[LAYOUT_WIDTH_INDEX] = YGNodeLayoutGetWidth(root);
|
|
|
|
arr[LAYOUT_HEIGHT_INDEX] = YGNodeLayoutGetHeight(root);
|
|
|
|
arr[LAYOUT_LEFT_INDEX] = YGNodeLayoutGetLeft(root);
|
|
|
|
arr[LAYOUT_TOP_INDEX] = YGNodeLayoutGetTop(root);
|
|
|
|
arr[LAYOUT_DIRECTION_INDEX] =
|
2023-09-06 08:16:42 -07:00
|
|
|
static_cast<float>(YGNodeLayoutGetDirection(root));
|
2019-10-08 17:48:32 -07:00
|
|
|
if (marginFieldSet) {
|
|
|
|
arr[LAYOUT_MARGIN_START_INDEX] = YGNodeLayoutGetMargin(root, YGEdgeLeft);
|
|
|
|
arr[LAYOUT_MARGIN_START_INDEX + 1] = YGNodeLayoutGetMargin(root, YGEdgeTop);
|
|
|
|
arr[LAYOUT_MARGIN_START_INDEX + 2] =
|
|
|
|
YGNodeLayoutGetMargin(root, YGEdgeRight);
|
|
|
|
arr[LAYOUT_MARGIN_START_INDEX + 3] =
|
|
|
|
YGNodeLayoutGetMargin(root, YGEdgeBottom);
|
|
|
|
}
|
|
|
|
if (paddingFieldSet) {
|
|
|
|
int paddingStartIndex =
|
|
|
|
LAYOUT_PADDING_START_INDEX - (marginFieldSet ? 0 : 4);
|
|
|
|
arr[paddingStartIndex] = YGNodeLayoutGetPadding(root, YGEdgeLeft);
|
|
|
|
arr[paddingStartIndex + 1] = YGNodeLayoutGetPadding(root, YGEdgeTop);
|
|
|
|
arr[paddingStartIndex + 2] = YGNodeLayoutGetPadding(root, YGEdgeRight);
|
|
|
|
arr[paddingStartIndex + 3] = YGNodeLayoutGetPadding(root, YGEdgeBottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (borderFieldSet) {
|
|
|
|
int borderStartIndex = LAYOUT_BORDER_START_INDEX -
|
|
|
|
(marginFieldSet ? 0 : 4) - (paddingFieldSet ? 0 : 4);
|
|
|
|
arr[borderStartIndex] = YGNodeLayoutGetBorder(root, YGEdgeLeft);
|
|
|
|
arr[borderStartIndex + 1] = YGNodeLayoutGetBorder(root, YGEdgeTop);
|
|
|
|
arr[borderStartIndex + 2] = YGNodeLayoutGetBorder(root, YGEdgeRight);
|
|
|
|
arr[borderStartIndex + 3] = YGNodeLayoutGetBorder(root, YGEdgeBottom);
|
|
|
|
}
|
|
|
|
|
2023-08-24 12:48:56 -07:00
|
|
|
// Create scope to make sure to release any local refs created here
|
|
|
|
{
|
|
|
|
// Don't change this field name without changing the name of the field in
|
|
|
|
// Database.java
|
|
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
|
|
env, env->GetObjectClass(obj.get()));
|
|
|
|
static const jfieldID arrField = facebook::yoga::vanillajni::getFieldId(
|
|
|
|
env, objectClass.get(), "arr", "[F");
|
|
|
|
|
|
|
|
ScopedLocalRef<jfloatArray> arrFinal =
|
|
|
|
make_local_ref(env, env->NewFloatArray(arrSize));
|
|
|
|
env->SetFloatArrayRegion(arrFinal.get(), 0, arrSize, arr);
|
|
|
|
env->SetObjectField(obj.get(), arrField, arrFinal.get());
|
2023-06-16 06:15:07 -07:00
|
|
|
}
|
|
|
|
|
2023-05-02 18:08:58 -07:00
|
|
|
YGNodeSetHasNewLayout(root, false);
|
2019-10-08 17:48:32 -07:00
|
|
|
|
2023-09-11 19:51:40 -07:00
|
|
|
for (size_t i = 0; i < YGNodeGetChildCount(root); i++) {
|
2023-09-12 19:08:55 -07:00
|
|
|
YGTransferLayoutOutputsRecursive(env, thiz, YGNodeGetChild(root, i));
|
2019-10-08 17:48:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeCalculateLayoutJNI(
|
|
|
|
JNIEnv* env,
|
|
|
|
jobject obj,
|
|
|
|
jlong nativePointer,
|
|
|
|
jfloat width,
|
|
|
|
jfloat height,
|
|
|
|
jlongArray nativePointers,
|
|
|
|
jobjectArray javaNodes) {
|
|
|
|
|
2019-10-22 10:45:20 -07:00
|
|
|
try {
|
2023-09-12 19:08:55 -07:00
|
|
|
PtrJNodeMapVanilla* layoutContext = nullptr;
|
2019-10-22 10:45:20 -07:00
|
|
|
auto map = PtrJNodeMapVanilla{};
|
|
|
|
if (nativePointers) {
|
2021-06-03 07:02:49 -07:00
|
|
|
map = PtrJNodeMapVanilla{nativePointers, javaNodes};
|
2019-10-22 10:45:20 -07:00
|
|
|
layoutContext = ↦
|
|
|
|
}
|
2019-10-08 17:48:32 -07:00
|
|
|
|
2023-09-12 19:08:55 -07:00
|
|
|
LayoutContext::Provider contextProvider(layoutContext);
|
|
|
|
|
2019-10-22 10:45:20 -07:00
|
|
|
const YGNodeRef root = _jlong2YGNodeRef(nativePointer);
|
2023-09-12 19:08:55 -07:00
|
|
|
YGNodeCalculateLayout(
|
2019-10-22 10:45:20 -07:00
|
|
|
root,
|
|
|
|
static_cast<float>(width),
|
|
|
|
static_cast<float>(height),
|
2023-09-12 19:08:55 -07:00
|
|
|
YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)));
|
|
|
|
YGTransferLayoutOutputsRecursive(env, obj, root);
|
2019-12-02 05:21:56 -08:00
|
|
|
} catch (const YogaJniException& jniException) {
|
|
|
|
ScopedLocalRef<jthrowable> throwable = jniException.getThrowable();
|
|
|
|
if (throwable.get()) {
|
|
|
|
env->Throw(throwable.get());
|
|
|
|
}
|
2020-05-14 06:32:13 -07:00
|
|
|
} catch (const std::logic_error& ex) {
|
|
|
|
env->ExceptionClear();
|
2022-08-30 18:49:10 -07:00
|
|
|
jclass cl = env->FindClass("java/lang/IllegalStateException");
|
2020-05-14 06:32:13 -07:00
|
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
|
|
env, cl, "<init>", "(Ljava/lang/String;)V");
|
|
|
|
auto throwable = env->NewObject(cl, methodId, env->NewStringUTF(ex.what()));
|
|
|
|
env->Throw(static_cast<jthrowable>(throwable));
|
2019-10-22 10:45:20 -07:00
|
|
|
}
|
2019-10-08 17:48:32 -07:00
|
|
|
}
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
static void jni_YGNodeMarkDirtyJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer) {
|
|
|
|
YGNodeMarkDirty(_jlong2YGNodeRef(nativePointer));
|
|
|
|
}
|
|
|
|
|
2023-03-21 16:29:09 -07:00
|
|
|
static void jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer) {
|
2023-03-21 16:29:09 -07:00
|
|
|
YGNodeMarkDirtyAndPropagateToDescendants(_jlong2YGNodeRef(nativePointer));
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static jboolean jni_YGNodeIsDirtyJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer) {
|
2023-05-02 18:08:58 -07:00
|
|
|
return (jboolean) YGNodeIsDirty(_jlong2YGNodeRef(nativePointer));
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeCopyStyleJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong dstNativePointer,
|
|
|
|
jlong srcNativePointer) {
|
|
|
|
YGNodeCopyStyle(
|
|
|
|
_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer));
|
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \
|
|
|
|
static javatype jni_YGNodeStyleGet##name##JNI( \
|
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \
|
|
|
|
return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static void jni_YGNodeStyleSet##name##JNI( \
|
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, javatype value) { \
|
|
|
|
YGNodeStyleSet##name( \
|
|
|
|
_jlong2YGNodeRef(nativePointer), static_cast<type>(value)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \
|
|
|
|
static jlong jni_YGNodeStyleGet##name##JNI( \
|
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \
|
|
|
|
return YogaValue::asJavaLong( \
|
|
|
|
YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \
|
2019-10-08 14:23:57 -07:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
static void jni_YGNodeStyleSet##name##JNI( \
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jfloat value) { \
|
2019-10-08 14:23:57 -07:00
|
|
|
YGNodeStyleSet##name( \
|
2023-05-11 09:43:36 -07:00
|
|
|
_jlong2YGNodeRef(nativePointer), static_cast<float>(value)); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static void jni_YGNodeStyleSet##name##PercentJNI( \
|
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jfloat value) { \
|
|
|
|
YGNodeStyleSet##name##Percent( \
|
|
|
|
_jlong2YGNodeRef(nativePointer), static_cast<float>(value)); \
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP(name) \
|
|
|
|
static void jni_YGNodeStyleSet##name##AutoJNI( \
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \
|
2019-10-08 14:23:57 -07:00
|
|
|
YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \
|
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
|
|
|
|
static jlong jni_YGNodeStyleGet##name##JNI( \
|
|
|
|
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jint edge) { \
|
|
|
|
return YogaValue::asJavaLong(YGNodeStyleGet##name( \
|
|
|
|
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge))); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static void jni_YGNodeStyleSet##name##JNI( \
|
|
|
|
JNIEnv* /*env*/, \
|
|
|
|
jobject /*obj*/, \
|
|
|
|
jlong nativePointer, \
|
|
|
|
jint edge, \
|
|
|
|
jfloat value) { \
|
|
|
|
YGNodeStyleSet##name( \
|
|
|
|
_jlong2YGNodeRef(nativePointer), \
|
|
|
|
static_cast<YGEdge>(edge), \
|
|
|
|
static_cast<float>(value)); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static void jni_YGNodeStyleSet##name##PercentJNI( \
|
|
|
|
JNIEnv* /*env*/, \
|
|
|
|
jobject /*obj*/, \
|
|
|
|
jlong nativePointer, \
|
|
|
|
jint edge, \
|
|
|
|
jfloat value) { \
|
|
|
|
YGNodeStyleSet##name##Percent( \
|
|
|
|
_jlong2YGNodeRef(nativePointer), \
|
|
|
|
static_cast<YGEdge>(edge), \
|
|
|
|
static_cast<float>(value)); \
|
2019-10-08 14:23:57 -07:00
|
|
|
}
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignItems);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignSelf);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignContent);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGPositionType, PositionType);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display);
|
2019-10-08 14:23:57 -07:00
|
|
|
YG_NODE_JNI_STYLE_PROP(jfloat, float, Flex);
|
2019-10-08 14:23:57 -07:00
|
|
|
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow);
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink);
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(FlexBasis);
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Width);
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP(MinWidth);
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP(MaxWidth);
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height);
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight);
|
|
|
|
YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight);
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position);
|
|
|
|
|
|
|
|
static jlong jni_YGNodeStyleGetMarginJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) {
|
|
|
|
return YogaValue::undefinedAsJavaLong();
|
|
|
|
}
|
|
|
|
return YogaValue::asJavaLong(
|
|
|
|
YGNodeStyleGetMargin(yogaNodeRef, static_cast<YGEdge>(edge)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetMarginJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge,
|
|
|
|
jfloat margin) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
|
|
|
|
YGNodeStyleSetMargin(
|
|
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(margin));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetMarginPercentJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge,
|
|
|
|
jfloat percent) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
|
|
|
|
YGNodeStyleSetMarginPercent(
|
|
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(percent));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetMarginAutoJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
|
|
|
|
YGNodeStyleSetMarginAuto(yogaNodeRef, static_cast<YGEdge>(edge));
|
|
|
|
}
|
|
|
|
|
|
|
|
static jlong jni_YGNodeStyleGetPaddingJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::PADDING)) {
|
|
|
|
return YogaValue::undefinedAsJavaLong();
|
|
|
|
}
|
|
|
|
return YogaValue::asJavaLong(
|
|
|
|
YGNodeStyleGetPadding(yogaNodeRef, static_cast<YGEdge>(edge)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetPaddingJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge,
|
|
|
|
jfloat padding) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::PADDING).setOn(yogaNodeRef);
|
|
|
|
YGNodeStyleSetPadding(
|
|
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(padding));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetPaddingPercentJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge,
|
|
|
|
jfloat percent) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::PADDING).setOn(yogaNodeRef);
|
|
|
|
YGNodeStyleSetPaddingPercent(
|
|
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(percent));
|
|
|
|
}
|
|
|
|
|
|
|
|
static jfloat jni_YGNodeStyleGetBorderJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::BORDER)) {
|
|
|
|
return (jfloat) YGUndefined;
|
|
|
|
}
|
|
|
|
return (jfloat) YGNodeStyleGetBorder(yogaNodeRef, static_cast<YGEdge>(edge));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetBorderJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 14:23:57 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint edge,
|
|
|
|
jfloat border) {
|
|
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::BORDER).setOn(yogaNodeRef);
|
|
|
|
YGNodeStyleSetBorder(
|
|
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(border));
|
|
|
|
}
|
|
|
|
|
2023-09-11 19:51:40 -07:00
|
|
|
static void YGTransferLayoutDirection(YGNodeConstRef node, jobject javaNode) {
|
2019-10-08 17:48:32 -07:00
|
|
|
// Don't change this field name without changing the name of the field in
|
|
|
|
// Database.java
|
|
|
|
JNIEnv* env = getCurrentEnv();
|
|
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
|
|
env, env->GetObjectClass(javaNode));
|
|
|
|
static const jfieldID layoutDirectionField =
|
|
|
|
facebook::yoga::vanillajni::getFieldId(
|
|
|
|
env, objectClass.get(), "mLayoutDirection", "I");
|
|
|
|
env->SetIntField(
|
|
|
|
javaNode,
|
|
|
|
layoutDirectionField,
|
|
|
|
static_cast<jint>(YGNodeLayoutGetDirection(node)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static YGSize YGJNIMeasureFunc(
|
2023-09-11 19:51:40 -07:00
|
|
|
YGNodeConstRef node,
|
2019-10-08 17:48:32 -07:00
|
|
|
float width,
|
|
|
|
YGMeasureMode widthMode,
|
|
|
|
float height,
|
2023-09-12 19:08:55 -07:00
|
|
|
YGMeasureMode heightMode) {
|
|
|
|
if (auto obj = YGNodeJobject(node)) {
|
2019-10-08 17:48:32 -07:00
|
|
|
YGTransferLayoutDirection(node, obj.get());
|
|
|
|
JNIEnv* env = getCurrentEnv();
|
|
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
|
|
env, env->GetObjectClass(obj.get()));
|
|
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
|
|
env, objectClass.get(), "measure", "(FIFI)J");
|
|
|
|
const auto measureResult = facebook::yoga::vanillajni::callLongMethod(
|
|
|
|
env, obj.get(), methodId, width, widthMode, height, heightMode);
|
|
|
|
|
|
|
|
static_assert(
|
|
|
|
sizeof(measureResult) == 8,
|
|
|
|
"Expected measureResult to be 8 bytes, or two 32 bit ints");
|
|
|
|
|
2023-09-06 08:16:42 -07:00
|
|
|
uint32_t wBits = 0xFFFFFFFF & (measureResult >> 32);
|
|
|
|
uint32_t hBits = 0xFFFFFFFF & measureResult;
|
2019-10-08 17:48:32 -07:00
|
|
|
|
2023-09-08 13:03:48 -07:00
|
|
|
const float measuredWidth = yoga::bit_cast<float>(wBits);
|
|
|
|
const float measuredHeight = yoga::bit_cast<float>(hBits);
|
2019-10-08 17:48:32 -07:00
|
|
|
|
2023-09-08 13:03:48 -07:00
|
|
|
return YGSize{measuredWidth, measuredHeight};
|
2019-10-08 17:48:32 -07:00
|
|
|
} else {
|
|
|
|
return YGSize{
|
|
|
|
widthMode == YGMeasureModeUndefined ? 0 : width,
|
|
|
|
heightMode == YGMeasureModeUndefined ? 0 : height,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeSetHasMeasureFuncJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 17:48:32 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jboolean hasMeasureFunc) {
|
2023-09-12 19:08:55 -07:00
|
|
|
YGNodeSetMeasureFunc(
|
|
|
|
_jlong2YGNodeRef(nativePointer),
|
|
|
|
hasMeasureFunc ? YGJNIMeasureFunc : nullptr);
|
2019-10-08 17:48:32 -07:00
|
|
|
}
|
|
|
|
|
2023-09-12 19:08:55 -07:00
|
|
|
static float YGJNIBaselineFunc(YGNodeConstRef node, float width, float height) {
|
|
|
|
if (auto obj = YGNodeJobject(node)) {
|
2019-10-08 17:48:32 -07:00
|
|
|
JNIEnv* env = getCurrentEnv();
|
|
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
|
|
env, env->GetObjectClass(obj.get()));
|
|
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
|
|
env, objectClass.get(), "baseline", "(FF)F");
|
|
|
|
return facebook::yoga::vanillajni::callFloatMethod(
|
|
|
|
env, obj.get(), methodId, width, height);
|
|
|
|
} else {
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeSetHasBaselineFuncJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2019-10-08 17:48:32 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jboolean hasBaselineFunc) {
|
2023-09-12 19:08:55 -07:00
|
|
|
YGNodeSetBaselineFunc(
|
|
|
|
_jlong2YGNodeRef(nativePointer),
|
|
|
|
hasBaselineFunc ? YGJNIBaselineFunc : nullptr);
|
2019-10-08 17:48:32 -07:00
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
static void jni_YGNodePrintJNI(
|
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
|
|
|
jlong nativePointer) {
|
2019-10-08 14:23:57 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
|
|
|
YGNodePrint(
|
|
|
|
node,
|
2021-05-20 21:22:47 -07:00
|
|
|
(YGPrintOptions) (YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren));
|
2023-05-11 09:43:36 -07:00
|
|
|
#else
|
|
|
|
(void) nativePointer;
|
2019-10-08 14:23:57 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-05-11 09:43:36 -07:00
|
|
|
static jlong jni_YGNodeCloneJNI(
|
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
|
|
|
jlong nativePointer) {
|
2019-10-08 14:23:57 -07:00
|
|
|
auto node = _jlong2YGNodeRef(nativePointer);
|
|
|
|
const YGNodeRef clonedYogaNode = YGNodeClone(node);
|
2023-05-02 18:08:58 -07:00
|
|
|
YGNodeSetContext(clonedYogaNode, YGNodeGetContext(node));
|
2019-10-08 14:23:57 -07:00
|
|
|
|
|
|
|
return reinterpret_cast<jlong>(clonedYogaNode);
|
|
|
|
}
|
|
|
|
|
2022-10-13 08:18:49 -07:00
|
|
|
static jfloat jni_YGNodeStyleGetGapJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2022-10-13 08:18:49 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint gutter) {
|
|
|
|
return (jfloat) YGNodeStyleGetGap(
|
|
|
|
_jlong2YGNodeRef(nativePointer), static_cast<YGGutter>(gutter));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jni_YGNodeStyleSetGapJNI(
|
2023-05-11 09:43:36 -07:00
|
|
|
JNIEnv* /*env*/,
|
|
|
|
jobject /*obj*/,
|
2022-10-13 08:18:49 -07:00
|
|
|
jlong nativePointer,
|
|
|
|
jint gutter,
|
|
|
|
jfloat gapLength) {
|
|
|
|
YGNodeStyleSetGap(
|
|
|
|
_jlong2YGNodeRef(nativePointer),
|
|
|
|
static_cast<YGGutter>(gutter),
|
|
|
|
static_cast<float>(gapLength));
|
|
|
|
}
|
|
|
|
|
2019-10-08 14:23:57 -07:00
|
|
|
// Yoga specific properties, not compatible with flexbox specification
|
|
|
|
YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
|
|
|
|
|
2019-09-26 17:30:28 -07:00
|
|
|
static JNINativeMethod methods[] = {
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGConfigNewJNI", "()J", (void*) jni_YGConfigNewJNI},
|
2019-10-09 09:26:47 -07:00
|
|
|
{"jni_YGConfigFreeJNI", "(J)V", (void*) jni_YGConfigFreeJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGConfigSetExperimentalFeatureEnabledJNI",
|
|
|
|
"(JIZ)V",
|
|
|
|
(void*) jni_YGConfigSetExperimentalFeatureEnabledJNI},
|
|
|
|
{"jni_YGConfigSetUseWebDefaultsJNI",
|
|
|
|
"(JZ)V",
|
|
|
|
(void*) jni_YGConfigSetUseWebDefaultsJNI},
|
|
|
|
{"jni_YGConfigSetPrintTreeFlagJNI",
|
|
|
|
"(JZ)V",
|
|
|
|
(void*) jni_YGConfigSetPrintTreeFlagJNI},
|
|
|
|
{"jni_YGConfigSetPointScaleFactorJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGConfigSetPointScaleFactorJNI},
|
2023-04-27 06:48:04 -07:00
|
|
|
{"jni_YGConfigSetErrataJNI", "(JI)V", (void*) jni_YGConfigSetErrataJNI},
|
|
|
|
{"jni_YGConfigGetErrataJNI", "(J)I", (void*) jni_YGConfigGetErrataJNI},
|
2019-10-09 09:26:47 -07:00
|
|
|
{"jni_YGConfigSetLoggerJNI",
|
|
|
|
"(JLcom/facebook/yoga/YogaLogger;)V",
|
|
|
|
(void*) jni_YGConfigSetLoggerJNI},
|
2019-10-08 17:48:32 -07:00
|
|
|
{"jni_YGNodeNewJNI", "()J", (void*) jni_YGNodeNewJNI},
|
|
|
|
{"jni_YGNodeNewWithConfigJNI", "(J)J", (void*) jni_YGNodeNewWithConfigJNI},
|
Fix use-after-free if JNI Yoga nodes are garbage collected using multiple threads (#1279)
Summary:
X-link: https://github.com/facebook/react-native/pull/37243
X-link: https://github.com/facebook/litho/pull/944
Pull Request resolved: https://github.com/facebook/yoga/pull/1279
Java bindings for Yoga rely solely on garbage collection for memory management. Each Java `YogaNode` has references to its children and parent Java Nodes. This means, for a node to be garbage collected, it cannot be reachable from any user accessible node. Each node then has single ownership of a `YGNodeRef`. When the `YogaNode` is garbage collected, a finalizer is run to call `YGNodeFree` and free the underlying native Yoga Node.
This may cause a use-after-free if finalizers are run from multiple threads. This is because `YGNodeFree` does more than just freeing, but instead also interacts with its parent and children nodes to detach itself, and remove any dangling pointers. If multiple threads run finalizers at once, one may traverse and try to mutate a node which another is freeing.
Because we know the entire connected tree is dead, there is no need to remove dangling pointers, so I want to expose a way to just free a Yoga Node, without it mutating the tree as a side effect.
This adds a currently private `YGNodeDeallocate` that frees without traversal. Ideally from naming this is what `YGNodeFree` would do, but we think changing the behavior of that might be too disruptive to OSS. At the same time there may be other memory safety related API changes we would like to eventually make, so this isn't made public beyond the JNI bindings to prevent needing to transition more APIs.
Changelog: [Internal]
Reviewed By: rshest
Differential Revision: D45556206
fbshipit-source-id: 62a1394c6f6bdc2b437b388098ea362a0fbcd0f7
2023-05-10 22:52:48 -07:00
|
|
|
{"jni_YGNodeDeallocateJNI", "(J)V", (void*) jni_YGNodeDeallocateJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI},
|
|
|
|
{"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI},
|
2020-01-30 03:41:45 -08:00
|
|
|
{"jni_YGNodeSwapChildJNI", "(JJI)V", (void*) jni_YGNodeSwapChildJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeSetIsReferenceBaselineJNI",
|
|
|
|
"(JZ)V",
|
|
|
|
(void*) jni_YGNodeSetIsReferenceBaselineJNI},
|
|
|
|
{"jni_YGNodeIsReferenceBaselineJNI",
|
|
|
|
"(J)Z",
|
|
|
|
(void*) jni_YGNodeIsReferenceBaselineJNI},
|
2023-05-02 18:08:58 -07:00
|
|
|
{"jni_YGNodeRemoveAllChildrenJNI",
|
|
|
|
"(J)V",
|
|
|
|
(void*) jni_YGNodeRemoveAllChildrenJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeRemoveChildJNI", "(JJ)V", (void*) jni_YGNodeRemoveChildJNI},
|
2019-10-08 17:48:32 -07:00
|
|
|
{"jni_YGNodeCalculateLayoutJNI",
|
|
|
|
"(JFF[J[Lcom/facebook/yoga/YogaNodeJNIBase;)V",
|
|
|
|
(void*) jni_YGNodeCalculateLayoutJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeMarkDirtyJNI", "(J)V", (void*) jni_YGNodeMarkDirtyJNI},
|
2023-03-21 16:29:09 -07:00
|
|
|
{"jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI",
|
2019-10-08 14:23:57 -07:00
|
|
|
"(J)V",
|
2023-03-21 16:29:09 -07:00
|
|
|
(void*) jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeIsDirtyJNI", "(J)Z", (void*) jni_YGNodeIsDirtyJNI},
|
|
|
|
{"jni_YGNodeCopyStyleJNI", "(JJ)V", (void*) jni_YGNodeCopyStyleJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetDirectionJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetDirectionJNI},
|
|
|
|
{"jni_YGNodeStyleSetDirectionJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetDirectionJNI},
|
|
|
|
{"jni_YGNodeStyleGetFlexDirectionJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetFlexDirectionJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexDirectionJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexDirectionJNI},
|
|
|
|
{"jni_YGNodeStyleGetJustifyContentJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetJustifyContentJNI},
|
|
|
|
{"jni_YGNodeStyleSetJustifyContentJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetJustifyContentJNI},
|
|
|
|
{"jni_YGNodeStyleGetAlignItemsJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetAlignItemsJNI},
|
|
|
|
{"jni_YGNodeStyleSetAlignItemsJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetAlignItemsJNI},
|
|
|
|
{"jni_YGNodeStyleGetAlignSelfJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetAlignSelfJNI},
|
|
|
|
{"jni_YGNodeStyleSetAlignSelfJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetAlignSelfJNI},
|
|
|
|
{"jni_YGNodeStyleGetAlignContentJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetAlignContentJNI},
|
|
|
|
{"jni_YGNodeStyleSetAlignContentJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetAlignContentJNI},
|
|
|
|
{"jni_YGNodeStyleGetPositionTypeJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetPositionTypeJNI},
|
|
|
|
{"jni_YGNodeStyleSetPositionTypeJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetPositionTypeJNI},
|
|
|
|
{"jni_YGNodeStyleGetFlexWrapJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetFlexWrapJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexWrapJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexWrapJNI},
|
|
|
|
{"jni_YGNodeStyleGetOverflowJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetOverflowJNI},
|
|
|
|
{"jni_YGNodeStyleSetOverflowJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetOverflowJNI},
|
|
|
|
{"jni_YGNodeStyleGetDisplayJNI",
|
|
|
|
"(J)I",
|
|
|
|
(void*) jni_YGNodeStyleGetDisplayJNI},
|
|
|
|
{"jni_YGNodeStyleSetDisplayJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetDisplayJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetFlexJNI", "(J)F", (void*) jni_YGNodeStyleGetFlexJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexJNI", "(JF)V", (void*) jni_YGNodeStyleSetFlexJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetFlexGrowJNI",
|
|
|
|
"(J)F",
|
|
|
|
(void*) jni_YGNodeStyleGetFlexGrowJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexGrowJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexGrowJNI},
|
|
|
|
{"jni_YGNodeStyleGetFlexShrinkJNI",
|
|
|
|
"(J)F",
|
|
|
|
(void*) jni_YGNodeStyleGetFlexShrinkJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexShrinkJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexShrinkJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetFlexBasisJNI",
|
|
|
|
"(J)J",
|
|
|
|
(void*) jni_YGNodeStyleGetFlexBasisJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexBasisJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexBasisJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexBasisPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexBasisPercentJNI},
|
|
|
|
{"jni_YGNodeStyleSetFlexBasisAutoJNI",
|
|
|
|
"(J)V",
|
|
|
|
(void*) jni_YGNodeStyleSetFlexBasisAutoJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetMarginJNI",
|
|
|
|
"(JI)J",
|
|
|
|
(void*) jni_YGNodeStyleGetMarginJNI},
|
|
|
|
{"jni_YGNodeStyleSetMarginJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMarginJNI},
|
|
|
|
{"jni_YGNodeStyleSetMarginPercentJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMarginPercentJNI},
|
|
|
|
{"jni_YGNodeStyleSetMarginAutoJNI",
|
|
|
|
"(JI)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMarginAutoJNI},
|
|
|
|
{"jni_YGNodeStyleGetPaddingJNI",
|
|
|
|
"(JI)J",
|
|
|
|
(void*) jni_YGNodeStyleGetPaddingJNI},
|
|
|
|
{"jni_YGNodeStyleSetPaddingJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetPaddingJNI},
|
|
|
|
{"jni_YGNodeStyleSetPaddingPercentJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetPaddingPercentJNI},
|
|
|
|
{"jni_YGNodeStyleGetBorderJNI",
|
|
|
|
"(JI)F",
|
|
|
|
(void*) jni_YGNodeStyleGetBorderJNI},
|
|
|
|
{"jni_YGNodeStyleSetBorderJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetBorderJNI},
|
|
|
|
{"jni_YGNodeStyleGetPositionJNI",
|
|
|
|
"(JI)J",
|
|
|
|
(void*) jni_YGNodeStyleGetPositionJNI},
|
|
|
|
{"jni_YGNodeStyleSetPositionJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetPositionJNI},
|
|
|
|
{"jni_YGNodeStyleSetPositionPercentJNI",
|
|
|
|
"(JIF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetPositionPercentJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetWidthJNI", "(J)J", (void*) jni_YGNodeStyleGetWidthJNI},
|
|
|
|
{"jni_YGNodeStyleSetWidthJNI", "(JF)V", (void*) jni_YGNodeStyleSetWidthJNI},
|
|
|
|
{"jni_YGNodeStyleSetWidthPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetWidthPercentJNI},
|
|
|
|
{"jni_YGNodeStyleSetWidthAutoJNI",
|
|
|
|
"(J)V",
|
|
|
|
(void*) jni_YGNodeStyleSetWidthAutoJNI},
|
|
|
|
{"jni_YGNodeStyleGetHeightJNI",
|
|
|
|
"(J)J",
|
|
|
|
(void*) jni_YGNodeStyleGetHeightJNI},
|
|
|
|
{"jni_YGNodeStyleSetHeightJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetHeightJNI},
|
|
|
|
{"jni_YGNodeStyleSetHeightPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetHeightPercentJNI},
|
|
|
|
{"jni_YGNodeStyleSetHeightAutoJNI",
|
|
|
|
"(J)V",
|
|
|
|
(void*) jni_YGNodeStyleSetHeightAutoJNI},
|
|
|
|
{"jni_YGNodeStyleGetMinWidthJNI",
|
|
|
|
"(J)J",
|
|
|
|
(void*) jni_YGNodeStyleGetMinWidthJNI},
|
|
|
|
{"jni_YGNodeStyleSetMinWidthJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMinWidthJNI},
|
|
|
|
{"jni_YGNodeStyleSetMinWidthPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMinWidthPercentJNI},
|
|
|
|
{"jni_YGNodeStyleGetMinHeightJNI",
|
|
|
|
"(J)J",
|
|
|
|
(void*) jni_YGNodeStyleGetMinHeightJNI},
|
|
|
|
{"jni_YGNodeStyleSetMinHeightJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMinHeightJNI},
|
|
|
|
{"jni_YGNodeStyleSetMinHeightPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMinHeightPercentJNI},
|
|
|
|
{"jni_YGNodeStyleGetMaxWidthJNI",
|
|
|
|
"(J)J",
|
|
|
|
(void*) jni_YGNodeStyleGetMaxWidthJNI},
|
|
|
|
{"jni_YGNodeStyleSetMaxWidthJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMaxWidthJNI},
|
|
|
|
{"jni_YGNodeStyleSetMaxWidthPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMaxWidthPercentJNI},
|
|
|
|
{"jni_YGNodeStyleGetMaxHeightJNI",
|
|
|
|
"(J)J",
|
|
|
|
(void*) jni_YGNodeStyleGetMaxHeightJNI},
|
|
|
|
{"jni_YGNodeStyleSetMaxHeightJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMaxHeightJNI},
|
|
|
|
{"jni_YGNodeStyleSetMaxHeightPercentJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetMaxHeightPercentJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodeStyleGetAspectRatioJNI",
|
|
|
|
"(J)F",
|
|
|
|
(void*) jni_YGNodeStyleGetAspectRatioJNI},
|
|
|
|
{"jni_YGNodeStyleSetAspectRatioJNI",
|
|
|
|
"(JF)V",
|
|
|
|
(void*) jni_YGNodeStyleSetAspectRatioJNI},
|
2019-10-08 17:48:32 -07:00
|
|
|
{"jni_YGNodeSetHasMeasureFuncJNI",
|
|
|
|
"(JZ)V",
|
|
|
|
(void*) jni_YGNodeSetHasMeasureFuncJNI},
|
2022-10-13 08:18:49 -07:00
|
|
|
{"jni_YGNodeStyleGetGapJNI", "(JI)F", (void*) jni_YGNodeStyleGetGapJNI},
|
|
|
|
{"jni_YGNodeStyleSetGapJNI", "(JIF)V", (void*) jni_YGNodeStyleSetGapJNI},
|
2019-10-08 17:48:32 -07:00
|
|
|
{"jni_YGNodeSetHasBaselineFuncJNI",
|
|
|
|
"(JZ)V",
|
|
|
|
(void*) jni_YGNodeSetHasBaselineFuncJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
{"jni_YGNodePrintJNI", "(J)V", (void*) jni_YGNodePrintJNI},
|
|
|
|
{"jni_YGNodeCloneJNI", "(J)J", (void*) jni_YGNodeCloneJNI},
|
2019-10-08 14:23:57 -07:00
|
|
|
};
|
2019-09-26 17:30:28 -07:00
|
|
|
|
|
|
|
void YGJNIVanilla::registerNatives(JNIEnv* env) {
|
2019-10-08 17:48:32 -07:00
|
|
|
facebook::yoga::vanillajni::registerNatives(
|
2019-09-26 17:30:28 -07:00
|
|
|
env,
|
|
|
|
"com/facebook/yoga/YogaNative",
|
|
|
|
methods,
|
|
|
|
sizeof(methods) / sizeof(JNINativeMethod));
|
|
|
|
}
|