Add `Unsafe` based storage backend

Summary:
@public

Adds another version of property storage for `YogaNode`, using `sun.misc.Unsafe`.

Adopts the stub concept from Litho for `Unsafe`, as it is hidden by the Android SDK.

Reviewed By: pasqualeanatriello

Differential Revision: D9140103

fbshipit-source-id: a4b376eca341b724a00f873467ae8bf8eaac69f4
This commit is contained in:
David Aurelio 2018-08-05 16:36:09 -07:00 committed by Facebook Github Bot
parent 1d93d70af4
commit 73d5746122
12 changed files with 670 additions and 13 deletions

7
ReactAndroid/BUCK Normal file
View File

@ -0,0 +1,7 @@
load("//ReactNative:DEFS.bzl", "rn_android_library")
rn_android_library(
name = "stubs",
srcs = glob(["stubs/src/**/*.java"]),
visibility = ["PUBLIC"],
)

View File

@ -305,6 +305,7 @@ dependencies {
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0'
compile 'com.squareup.okio:okio:1.14.0'
compile 'org.webkit:android-jsc:r174650'
compileOnly project(':ReactAndroid:stubs')
testCompile "junit:junit:${JUNIT_VERSION}"
testCompile "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}"

View File

@ -1,4 +1,4 @@
load("//ReactNative:DEFS.bzl", "react_native_dep", "rn_android_library")
load("//ReactNative:DEFS.bzl", "react_native_dep", "rn_android_library", "JAVA_STUBS_TARGET")
rn_android_library(
name = "yoga",
@ -10,4 +10,7 @@ rn_android_library(
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
react_native_dep("third-party/java/jsr-305:jsr-305"),
],
provided_deps = [
JAVA_STUBS_TARGET,
]
)

View File

@ -23,6 +23,7 @@ public class YogaNode implements Cloneable {
public static final int BYTE_BUFFER = 1;
public static final int HYBRID = 2;
public static final int UNSAFE = 3;
/** Get native instance count. Useful for testing only. */
static native int jni_YGNodeGetInstanceCount();
@ -50,6 +51,9 @@ public class YogaNode implements Cloneable {
case HYBRID:
mDelegate = new YogaNodePropertiesHybrid(this);
break;
case UNSAFE:
mDelegate = new YogaNodePropertiesUnsafe(this);
break;
default:
mDelegate = new YogaNodePropertiesJNI(this);
}
@ -63,6 +67,9 @@ public class YogaNode implements Cloneable {
case HYBRID:
mDelegate = new YogaNodePropertiesHybrid(this, config);
break;
case UNSAFE:
mDelegate = new YogaNodePropertiesUnsafe(this, config);
break;
default:
mDelegate = new YogaNodePropertiesJNI(this, config);
}

View File

@ -31,16 +31,16 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab
private static native ByteBuffer jni_getLayoutBuffer(long nativePointer);
private static native long jni_YGNodeNewByteBuffer(YogaNode node);
private static native long jni_YGNodeNewNoProps(YogaNode node);
public YogaNodePropertiesByteBuffer(YogaNode node) {
this(jni_YGNodeNewByteBuffer(node));
this(jni_YGNodeNewNoProps(node));
}
private static native long jni_YGNodeNewByteBufferWithConfig(YogaNode node, long configPointer);
private static native long jni_YGNodeNewNoPropsWithConfig(YogaNode node, long configPointer);
public YogaNodePropertiesByteBuffer(YogaNode node, YogaConfig config) {
this(jni_YGNodeNewByteBufferWithConfig(node, config.mNativePointer));
this(jni_YGNodeNewNoPropsWithConfig(node, config.mNativePointer));
}
public YogaNodePropertiesByteBuffer(long nativePointer) {
@ -84,6 +84,7 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab
@Override
public void reset() {
mHasBorderSet = false;
mHasNewLayout = true;
jni_YGNodeReset(getNativePointer());
}

View File

@ -0,0 +1,580 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*
*/
package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
@DoNotStrip
public class YogaNodePropertiesUnsafe implements YogaNodeProperties {
private static final int TRUE_BITS = 0x01000001;
private static final int FLOAT_SIZE = 4;
private static final int AUTO = YogaUnit.AUTO.intValue();
private static final int POINT = YogaUnit.POINT.intValue();
private static final int PERCENT = YogaUnit.PERCENT.intValue();
private static final int UNDEFINED = YogaUnit.UNDEFINED.intValue();
private static final int RTL = YogaDirection.RTL.intValue();
private static final Unsafe UNSAFE;
private final long mNativePointer;
private final long mStyleNativePointer;
private final long mLayoutNativePointer;
private boolean mHasBorderSet = false;
private boolean mHasNewLayout = true;
private boolean mIsFreed = false;
static {
SoLoader.loadLibrary("yoga");
Field instanceField = null;
try {
instanceField = Unsafe.class.getDeclaredField("theUnsafe");
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
instanceField.setAccessible(true);
try {
UNSAFE = (Unsafe) instanceField.get(null);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private static native long jni_YGNodeNewNoProps(YogaNode node);
private static native long jni_YGNodeNewNoPropsWithConfig(YogaNode node, long configPointer);
private static native long jni_YGNodeStylePointer(long nativePointer);
private static native long jni_YGNodeLayoutPointer(long nativePointer);
public YogaNodePropertiesUnsafe(YogaNode node) {
this(jni_YGNodeNewNoProps(node));
}
public YogaNodePropertiesUnsafe(YogaNode node, YogaConfig config) {
this(jni_YGNodeNewNoPropsWithConfig(node, config.mNativePointer));
}
public YogaNodePropertiesUnsafe(long nativePointer) {
mNativePointer = nativePointer;
mStyleNativePointer = jni_YGNodeStylePointer(nativePointer);
mLayoutNativePointer = jni_YGNodeLayoutPointer(nativePointer);
}
private static native long jni_YGNodeCloneNoProps(long nativePointer, YogaNode newNode);
@Override
public YogaNodeProperties clone(YogaNode node) {
long clonedNativePointer = jni_YGNodeCloneNoProps(getNativePointer(), node);
YogaNodePropertiesUnsafe clone =
new YogaNodePropertiesUnsafe(clonedNativePointer);
clone.mHasBorderSet = mHasBorderSet;
clone.mHasNewLayout = mHasNewLayout;
return clone;
}
@Override
public long getNativePointer() {
return mNativePointer;
}
@Override
public void onAfterCalculateLayout(boolean hasNewLayout) {
mHasNewLayout = hasNewLayout;
}
private static native void jni_YGNodeReset(long nativePointer);
@Override
public void reset() {
mHasNewLayout = true;
jni_YGNodeReset(getNativePointer());
}
@Override
public boolean hasNewLayout() {
return mHasNewLayout;
}
private static native boolean jni_YGNodeIsDirty(long nativePointer);
@Override
public boolean isDirty() {
return jni_YGNodeIsDirty(mNativePointer);
}
@Override
public void markLayoutSeen() {
mHasNewLayout = false;
}
@Override
public YogaDirection getStyleDirection() {
return YogaDirection.fromInt(getStyleInt(YogaNodeMemoryLayout.styleDirection));
}
@Override
public void setDirection(YogaDirection direction) {
putStyleInt(YogaNodeMemoryLayout.styleDirection, direction.intValue());
}
@Override
public YogaFlexDirection getFlexDirection() {
return YogaFlexDirection.fromInt(getStyleInt(YogaNodeMemoryLayout.styleFlexDirection));
}
@Override
public void setFlexDirection(YogaFlexDirection flexDirection) {
putStyleInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue());
}
@Override
public YogaJustify getJustifyContent() {
return YogaJustify.fromInt(getStyleInt(YogaNodeMemoryLayout.styleJustifyContent));
}
@Override
public void setJustifyContent(YogaJustify justifyContent) {
putStyleInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue());
}
@Override
public YogaAlign getAlignItems() {
return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignItems));
}
@Override
public void setAlignItems(YogaAlign alignItems) {
putStyleInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue());
}
@Override
public YogaAlign getAlignSelf() {
return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignSelf));
}
@Override
public void setAlignSelf(YogaAlign alignSelf) {
putStyleInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue());
}
@Override
public YogaAlign getAlignContent() {
return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignContent));
}
@Override
public void setAlignContent(YogaAlign alignContent) {
putStyleInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue());
}
@Override
public YogaPositionType getPositionType() {
return YogaPositionType.fromInt(getStyleInt(YogaNodeMemoryLayout.stylePositionType));
}
@Override
public void setPositionType(YogaPositionType positionType) {
putStyleInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue());
}
@Override
public void setWrap(YogaWrap flexWrap) {
putStyleInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue());
}
@Override
public YogaOverflow getOverflow() {
return YogaOverflow.fromInt(getStyleInt(YogaNodeMemoryLayout.styleOverflow));
}
@Override
public void setOverflow(YogaOverflow overflow) {
putStyleInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue());
}
@Override
public YogaDisplay getDisplay() {
return YogaDisplay.fromInt(getStyleInt(YogaNodeMemoryLayout.styleDisplay));
}
@Override
public void setDisplay(YogaDisplay display) {
putStyleInt(YogaNodeMemoryLayout.styleDisplay, display.intValue());
}
@Override
public void setFlex(float flex) {
putStyleOptional(YogaNodeMemoryLayout.styleFlex, flex);
}
@Override
public float getFlexGrow() {
return getStyleFloat(YogaNodeMemoryLayout.styleFlexGrow);
}
@Override
public void setFlexGrow(float flexGrow) {
putStyleOptional(YogaNodeMemoryLayout.styleFlexGrow, flexGrow);
}
@Override
public float getFlexShrink() {
return getStyleFloat(YogaNodeMemoryLayout.styleFlexShrink);
}
@Override
public void setFlexShrink(float flexShrink) {
putStyleOptional(YogaNodeMemoryLayout.styleFlexShrink, flexShrink);
}
@Override
public YogaValue getFlexBasis() {
return getStyleValue(YogaNodeMemoryLayout.styleFlexBasis);
}
@Override
public void setFlexBasis(float flexBasis) {
putStylePoints(YogaNodeMemoryLayout.styleFlexBasis, flexBasis);
}
@Override
public void setFlexBasisPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleFlexBasis, percent);
}
@Override
public void setFlexBasisAuto() {
putStyleAuto(YogaNodeMemoryLayout.styleFlexBasis);
}
@Override
public YogaValue getMargin(YogaEdge edge) {
return getStyleValue(YogaNodeMemoryLayout.styleMarginOffset(edge));
}
@Override
public void setMargin(YogaEdge edge, float margin) {
putStylePoints(YogaNodeMemoryLayout.styleMarginOffset(edge), margin);
}
@Override
public void setMarginPercent(YogaEdge edge, float percent) {
putStylePercent(YogaNodeMemoryLayout.styleMarginOffset(edge), percent);
}
@Override
public void setMarginAuto(YogaEdge edge) {
putStyleAuto(YogaNodeMemoryLayout.styleMarginOffset(edge));
}
@Override
public YogaValue getPadding(YogaEdge edge) {
return getStyleValue(YogaNodeMemoryLayout.stylePaddingOffset(edge));
}
@Override
public void setPadding(YogaEdge edge, float padding) {
putStylePoints(YogaNodeMemoryLayout.stylePaddingOffset(edge), padding);
}
@Override
public void setPaddingPercent(YogaEdge edge, float percent) {
putStylePercent(YogaNodeMemoryLayout.stylePaddingOffset(edge), percent);
}
@Override
public float getBorder(YogaEdge edge) {
return mHasBorderSet
? getStyleFloat(YogaNodeMemoryLayout.styleBorderOffset(edge))
: YogaConstants.UNDEFINED;
}
@Override
public void setBorder(YogaEdge edge, float border) {
mHasBorderSet = true;
putStylePoints(YogaNodeMemoryLayout.styleBorderOffset(edge), border);
}
@Override
public YogaValue getPosition(YogaEdge edge) {
return getStyleValue(YogaNodeMemoryLayout.stylePositionOffset(edge));
}
@Override
public void setPosition(YogaEdge edge, float position) {
putStylePoints(YogaNodeMemoryLayout.stylePositionOffset(edge), position);
}
@Override
public void setPositionPercent(YogaEdge edge, float percent) {
putStylePercent(YogaNodeMemoryLayout.stylePositionOffset(edge), percent);
}
@Override
public YogaValue getWidth() {
return getStyleValue(YogaNodeMemoryLayout.styleWidth);
}
@Override
public void setWidth(float width) {
putStylePoints(YogaNodeMemoryLayout.styleWidth, width);
}
@Override
public void setWidthPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleWidth, percent);
}
@Override
public void setWidthAuto() {
putStyleAuto(YogaNodeMemoryLayout.styleWidth);
}
@Override
public YogaValue getHeight() {
return getStyleValue(YogaNodeMemoryLayout.styleHeight);
}
@Override
public void setHeight(float height) {
putStylePoints(YogaNodeMemoryLayout.styleHeight, height);
}
@Override
public void setHeightPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleHeight, percent);
}
@Override
public void setHeightAuto() {
putStyleAuto(YogaNodeMemoryLayout.styleHeight);
}
@Override
public YogaValue getMinWidth() {
return getStyleValue(YogaNodeMemoryLayout.styleMinWidth);
}
@Override
public void setMinWidth(float minWidth) {
putStylePoints(YogaNodeMemoryLayout.styleMinWidth, minWidth);
}
@Override
public void setMinWidthPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleMinWidth, percent);
}
@Override
public YogaValue getMinHeight() {
return getStyleValue(YogaNodeMemoryLayout.styleMinHeight);
}
@Override
public void setMinHeight(float minHeight) {
putStylePoints(YogaNodeMemoryLayout.styleMinHeight, minHeight);
}
@Override
public void setMinHeightPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleMinHeight, percent);
}
@Override
public YogaValue getMaxWidth() {
return getStyleValue(YogaNodeMemoryLayout.styleMaxWidth);
}
@Override
public void setMaxWidth(float maxWidth) {
putStylePoints(YogaNodeMemoryLayout.styleMaxWidth, maxWidth);
}
@Override
public void setMaxWidthPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleMaxWidth, percent);
}
@Override
public YogaValue getMaxHeight() {
return getStyleValue(YogaNodeMemoryLayout.styleMaxHeight);
}
@Override
public void setMaxHeight(float maxHeight) {
putStylePoints(YogaNodeMemoryLayout.styleMaxHeight, maxHeight);
}
@Override
public void setMaxHeightPercent(float percent) {
putStylePercent(YogaNodeMemoryLayout.styleMaxHeight, percent);
}
@Override
public float getAspectRatio() {
return getStyleOptional(YogaNodeMemoryLayout.styleAspectRatio);
}
@Override
public void setAspectRatio(float aspectRatio) {
putStyleOptional(YogaNodeMemoryLayout.styleAspectRatio, aspectRatio);
}
@Override
public float getLayoutX() {
return getLayoutFloat(YogaNodeMemoryLayout.layoutX);
}
@Override
public float getLayoutY() {
return getLayoutFloat(YogaNodeMemoryLayout.layoutY);
}
@Override
public float getLayoutWidth() {
return getLayoutFloat(YogaNodeMemoryLayout.layoutWidth);
}
@Override
public float getLayoutHeight() {
return getLayoutFloat(YogaNodeMemoryLayout.layoutHeight);
}
@Override
public boolean getDoesLegacyStretchFlagAffectsLayout() {
return getBool(mLayoutNativePointer + YogaNodeMemoryLayout.layoutDoesLegacyStretchFlagAffectsLayout);
}
@Override
public float getLayoutMargin(YogaEdge edge) {
return getLayoutFloat(YogaNodeMemoryLayout.layoutMarginOffset(layoutEdge(edge)));
}
@Override
public float getLayoutPadding(YogaEdge edge) {
return getLayoutFloat(YogaNodeMemoryLayout.layoutPaddingOffset(layoutEdge(edge)));
}
@Override
public float getLayoutBorder(YogaEdge edge) {
return getLayoutFloat(YogaNodeMemoryLayout.layoutBorderOffset(layoutEdge(edge)));
}
@Override
public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(getLayoutDirectionInt());
}
private static native void jni_YGNodeFree(long nativePointer);
@Override
public void freeNatives() {
if (!mIsFreed) {
mIsFreed = true;
jni_YGNodeFree(mNativePointer);
}
}
private int getLayoutDirectionInt() {
return UNSAFE.getInt(null, mLayoutNativePointer + YogaNodeMemoryLayout.layoutDirection);
}
private YogaEdge layoutEdge(YogaEdge edge) {
int layoutDirection = getLayoutDirectionInt();
switch (edge) {
case LEFT:
return layoutDirection == RTL ? YogaEdge.END : YogaEdge.START;
case RIGHT:
return layoutDirection == RTL ? YogaEdge.START : YogaEdge.END;
case TOP:
case BOTTOM:
case START:
case END:
return edge;
default:
throw new IllegalArgumentException("Cannot get layout properties of multi-edge shorthands");
}
}
private int getStyleInt(int offset) {
return UNSAFE.getInt(null, mStyleNativePointer + offset);
}
private void putStyleInt(int offset, int value) {
UNSAFE.putInt(null, mStyleNativePointer + offset, value);
}
private float getStyleFloat(int offset) {
return getFloat(mStyleNativePointer + offset);
}
private void putStyleFloat(int offset, float value) {
putFloat(mStyleNativePointer + offset, value);
}
private void putStylePoints(int offset, float value) {
putStyleValue(offset, value, POINT);
}
private void putStylePercent(int offset, float value) {
putStyleValue(offset, value, PERCENT);
}
private void putStyleAuto(int offset) {
putStyleValue(offset, 0, AUTO);
}
private void putStyleValue(int offset, float value, int unit) {
if (YogaConstants.isUndefined(value)) {
value = YogaConstants.UNDEFINED;
unit = UNDEFINED;
}
putStyleFloat(offset, value);
putStyleInt(offset + FLOAT_SIZE, unit);
}
private YogaValue getStyleValue(int offset) {
float value = getStyleFloat(offset);
int unit = getStyleInt(offset + FLOAT_SIZE);
return new YogaValue(value, YogaUnit.fromInt(unit));
}
private void putStyleOptional(int offset, float value) {
int isUndefinedBits = YogaConstants.isUndefined(value) ? TRUE_BITS : 0;
putStyleFloat(offset, value);
putStyleInt(offset + FLOAT_SIZE, isUndefinedBits);
}
private float getStyleOptional(int offset) {
boolean isUndefined = getBool(mStyleNativePointer + offset + FLOAT_SIZE);
return isUndefined
? YogaConstants.UNDEFINED
: getStyleFloat(offset);
}
private float getLayoutFloat(int offset) {
return getFloat(mLayoutNativePointer + offset);
}
private static float getFloat(long offset) {
int intBits = UNSAFE.getInt(null, offset);
return Float.intBitsToFloat(intBits);
}
private static void putFloat(long offset, float value) {
int intBits = Float.floatToRawIntBits(value);
UNSAFE.putInt(null, offset, intBits);
}
private static boolean getBool(long offset) {
// assumes little endian
return (UNSAFE.getInt(null, offset) & 0xFF) != 0;
}
}

View File

@ -344,13 +344,11 @@ jlong jni_YGNodeNewWithConfig(
return reinterpret_cast<jlong>(node);
}
jlong jni_YGNodeNewByteBuffer(
alias_ref<jclass>,
alias_ref<JYogaNode> javaNode) {
jlong jni_YGNodeNewNoProps(alias_ref<jclass>, alias_ref<JYogaNode> javaNode) {
return jni_YGNodeNew(nullptr, javaNode);
}
jlong jni_YGNodeNewByteBufferWithConfig(
jlong jni_YGNodeNewNoPropsWithConfig(
alias_ref<jclass>,
alias_ref<JYogaNode> javaNode,
jlong configPointer) {
@ -747,6 +745,14 @@ local_ref<JByteBuffer> jni_getLayoutBuffer(
reinterpret_cast<uint8_t*>(layout), sizeof(YGLayout));
}
jlong jni_YGNodeStylePointer(alias_ref<jclass>, jlong nativePointer) {
return reinterpret_cast<jlong>(&_jlong2YGNodeRef(nativePointer)->getStyle());
}
jlong jni_YGNodeLayoutPointer(alias_ref<jclass>, jlong nativePointer) {
return reinterpret_cast<jlong>(&_jlong2YGNodeRef(nativePointer)->getLayout());
}
#define YGMakeNativeMethod(name) makeNativeMethod(#name, name)
jint JNI_OnLoad(JavaVM* vm, void*) {
@ -860,8 +866,8 @@ jint JNI_OnLoad(JavaVM* vm, void*) {
{
YGMakeNativeMethod(jni_YGNodeCloneNoProps),
YGMakeNativeMethod(jni_YGNodeFree),
YGMakeNativeMethod(jni_YGNodeNewByteBuffer),
YGMakeNativeMethod(jni_YGNodeNewByteBufferWithConfig),
YGMakeNativeMethod(jni_YGNodeNewNoProps),
YGMakeNativeMethod(jni_YGNodeNewNoPropsWithConfig),
YGMakeNativeMethod(jni_YGNodeReset),
YGMakeNativeMethod(jni_YGNodeIsDirty),
YGMakeNativeMethod(jni_getStyleBuffer),
@ -872,5 +878,17 @@ jint JNI_OnLoad(JavaVM* vm, void*) {
{
YGMakeNativeMethod(jni_getStyleBuffer),
});
registerNatives(
"com/facebook/yoga/YogaNodePropertiesUnsafe",
{
YGMakeNativeMethod(jni_YGNodeCloneNoProps),
YGMakeNativeMethod(jni_YGNodeFree),
YGMakeNativeMethod(jni_YGNodeNewNoProps),
YGMakeNativeMethod(jni_YGNodeNewNoPropsWithConfig),
YGMakeNativeMethod(jni_YGNodeStylePointer),
YGMakeNativeMethod(jni_YGNodeLayoutPointer),
YGMakeNativeMethod(jni_YGNodeIsDirty),
YGMakeNativeMethod(jni_YGNodeReset),
});
});
}

View File

@ -0,0 +1,10 @@
apply plugin: 'java'
sourceSets {
main {
java {
srcDirs = ['src']
}
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*
*/
package sun.misc;
/**
* Stub for sun.misc.Unsafe, which is not exposed by the Android SDK.
*
* This only contains the methods and fields we need for Yoga.
*/
public final class Unsafe {
private static final Unsafe theUnsafe = null;
public final int getInt(Object object, long offset) {
throw new RuntimeException("Stub!");
}
public final void putInt(Object object, long offset, int value) {
throw new RuntimeException("Stub!");
}
}

View File

@ -271,3 +271,5 @@ def jni_instrumentation_test_lib(**kwargs):
def fb_xplat_cxx_test(**kwargs):
"""A noop stub for OSS build."""
pass
JAVA_STUBS_TARGET = "//ReactAndroid:stubs"

View File

@ -6,6 +6,7 @@
buildscript {
repositories {
jcenter()
google()
mavenLocal()
maven {
url 'https://maven.google.com/'
@ -13,7 +14,7 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.android.tools.build:gradle:3.0.0'
classpath 'de.undercouch:gradle-download-task:3.4.3'
// NOTE: Do not place your application dependencies here; they belong

View File

@ -3,4 +3,4 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
include ':ReactAndroid', ':RNTester:android:app'
include ':ReactAndroid', ':RNTester:android:app', ':ReactAndroid:stubs'