Compare commits

...

129 Commits

Author SHA1 Message Date
Sidharth Guglani
26dbe8b4ff bump version to 1.16.0
Summary: Bump version to 1.16.0 for new yoga release

Reviewed By: amir-shalem

Differential Revision: D17395785

fbshipit-source-id: b01b31d58b5b1a2a9532e9cce0892c08960ec31c
2019-09-16 07:48:59 -07:00
Sidharth Guglani
a5c2f7f27a fix yoga build issue Could not find yoga:libfb:unspecified.
Summary:
Fixes the yoga build 1:15:0 build issue

    Could not find yoga:libfb:unspecified.
    Required by:
    project :app > com.facebook.yoga:yoga:1.15.0

libfb dependency was added to solve import issue in YogaPhantomJNIRefs but since we don't have that file now in codebase , it will not be a problem.

Reviewed By: amir-shalem

Differential Revision: D17395380

fbshipit-source-id: ab8eb2c89afe29b4688787db2214c328d875041e
2019-09-16 05:25:39 -07:00
Sidharth Guglani
10811e1a94 bump version to 1.15.0-SNAPSHOT
Summary: Bumping version to 1.15.0-SNAPSHOT

Reviewed By: amir-shalem

Differential Revision: D17394807

fbshipit-source-id: 2ba8ecbb903b9810905fabf3b60efaa8458b6bfd
2019-09-16 04:37:39 -07:00
Sidharth Guglani
10f4bceac0 bump version to 1.15.0
Summary: Bumping version to 1.15.0 for new yoga release

Reviewed By: amir-shalem

Differential Revision: D17394805

fbshipit-source-id: de43e97a0c155f332ecbe4e98b78c2f7c9ffe771
2019-09-16 03:42:43 -07:00
Sidharth Guglani
47717324d4 fix fbjni and yoga event files not found in testutil issue
Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/928

Reviewed By: amir-shalem

Differential Revision: D17383979

fbshipit-source-id: 755c2cc3749d5e23fbd1e0ac7a41632c1400ae24
2019-09-15 13:54:06 -07:00
Amir Shalem
1043c35f2b Fix libfbjni compilation (#927)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/927

When D16220924 brought a new fbjni copy (with new directories), we forgot to fix the cmake files which are used by gradle build system.

Reviewed By: SidharthGuglani

Differential Revision: D17367160

fbshipit-source-id: 3e7d20d4c53ff3012a164bf6e32f1000ecb3ffc2
2019-09-13 09:21:06 -07:00
Amir Shalem
fde89b056d Add standalone factory classes which generate YogaNode + YogaConfig
Summary:
Add standalone factory classes which generate YogaNode + YogaConfig, later on it will allow us to separate the yoga interface and actual implementation buck targets (see D17266406)

We've done such breakage change previously in D14122974.

Reviewed By: SidharthGuglani

Differential Revision: D17258196

fbshipit-source-id: b12f1a0d23c3f82b14cee0731a1daf1c015ee32c
2019-09-12 06:05:02 -07:00
Sidharth Guglani
a08a57b33c Remove unused YogaNodeJNIPhantomRefs.java
Summary:
Removed unused file YogaNodeJNIPhantomRefs.java as this was causing oss build failures because of an import.

````:yoga:compileDebugJavaWithJavac/home/travis/build/facebook/yoga/java/com/facebook/yoga/YogaNodeJNIPhantomRefs.java:9: error: package com.facebook.jni does not exist
import com.facebook.jni.DestructorThread;
                       ^
/home/travis/build/facebook/yoga/java/com/facebook/yoga/YogaNodeJNIPhantomRefs.java:30: error: package DestructorThread does not exist
    new DestructorThread.Destructor(node) {
                        ^
2 errors
 FAILED

Reviewed By: pasqualeanatriello

Differential Revision: D17257330

fbshipit-source-id: 98b0c5d5b7dcd94bee559b58194c13b07f47723d
2019-09-11 10:28:56 -07:00
Amir Shalem
31de91bbac fix gradle compliation (#925)
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/925

Gradle is failing to compile yoga for two reasons:
1. Ever since `YogaNodeJNIPhantomRefs` was introduced which uses `DestructorThread.Destructor` from fbjni which was the first direct Java dependency from yoga java to fbjni java code.

2. Adding a missing gradle endpoint for `testutil` since it is now required for yoga unit-tests

Reviewed By: SidharthGuglani

Differential Revision: D17274226

fbshipit-source-id: 3df9648321162d34f81fd3675ca1474e8a1c6d3a
2019-09-10 08:18:56 -07:00
Sidharth Guglani
e6e224ce48 Add dist: trusty to yoga travis configuration
Summary:
clang 6.0 install was failing in yoga oss tests

Travis has made xenial as default distribution
https://changelog.travis-ci.com/xenial-as-the-default-build-environment-is-coming-97772

Added dist: trusty to the configuration to fix this.

Reviewed By: passy

Differential Revision: D17257300

fbshipit-source-id: f9fcd6ba774dad1c28bd953c0d850c7078d02015
2019-09-09 03:34:52 -07:00
Paul O'Shannessy
a04a6b5e8f Adopt Contributor Covenant
Summary:
In order to foster healthy open source communities, we're adopting the
[Contributor Covenant](https://www.contributor-covenant.org/). It has been
built by open source community members and represents a shared understanding of
what is expected from a healthy community.

Reviewed By: josephsavona, danobi, rdzhabarov

Differential Revision: D17104640

fbshipit-source-id: d210000de686c5f0d97d602b50472d5869bc6a49
2019-08-29 23:48:24 -07:00
Pascal Hartig
442d84ccfc Remove built-in DoNotStrip annotations
Summary:
Use the Yoga dependency instead which can be deduplicated by Gradle.

This solves (parts of) a bunch of issues concerning the use of
multiple FB libraries in one Android project.

Reviewed By: danielbuechele

Differential Revision: D16783243

fbshipit-source-id: 7f7915821dd286c51ec4ccbd95a2cdcb18b53bde
2019-08-15 04:21:56 -07:00
Pascal Hartig
4a2ccc658e Target Java 7
Summary: The artifacts generated otherwise can cause issues in Android projects.

Reviewed By: SidharthGuglani

Differential Revision: D16803253

fbshipit-source-id: db139560dfbddb917c27bdfd80e1bf5747e4a74b
2019-08-14 05:37:32 -07:00
Pascal Hartig
58622fa747 Set up proguard-annotations as separate Maven artifact
Summary:
We need one place, any place really, to publish that good old `DoNotStrip` annotation
from that we currently copy across various repos, causing havoc for anybody who
tries to integrate more than one FB Android library into their project.

Yoga is very well positioned for this because it's already its own Gradle module and
all that's missing are these few lines.

Reviewed By: SidharthGuglani

Differential Revision: D16783035

fbshipit-source-id: 69b6224a725194d036c6a23a36bd76d3487b9811
2019-08-13 06:26:15 -07:00
Sidharth Guglani
90cded3819 use array for passing measure callback reasons count
Summary:
Use an array for counting measure callbacks due to each reason.
and this is now added as qpl metadata in Layout Calculation qpl event

Reviewed By: davidaurelio

Differential Revision: D16666786

fbshipit-source-id: ff85fba835148f06b9c5d90c4604e552a813777a
2019-08-08 07:18:03 -07:00
Adlai Holler
d1e188341b Don't copy children in YGNodeComputeFlexBasisForChildren (#919)
Summary:
No need for a copy here.
Pull Request resolved: https://github.com/facebook/yoga/pull/919

Differential Revision: D16701461

Pulled By: davidaurelio

fbshipit-source-id: 3a90adbb2b5c43d5aefe693a8525aa3a37e53b3d
2019-08-08 00:24:07 -07:00
Nicola Ferruzzi
0f2350308e Properly test for the lack of a node measure func in YogaKit (#915)
Summary:
The test was broken and caused a few crashes on my project.
Pull Request resolved: https://github.com/facebook/yoga/pull/915

Differential Revision: D16701613

Pulled By: davidaurelio

fbshipit-source-id: 9ab5c43bb74e77593bc2426a249750a7ee8f4034
2019-08-08 00:10:25 -07:00
Luis Miguel Alvarado
9b120eded9 add space-evenly prop to justify-content.md (#918)
Summary:
This PR add the `space-evenly` prop, to the [justify-content.md](https://github.com/facebook/yoga/blob/master/website/contents/properties/justify-content.md) file.

The description was taken from [Mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)
Pull Request resolved: https://github.com/facebook/yoga/pull/918

Differential Revision: D16701547

Pulled By: davidaurelio

fbshipit-source-id: cd1bb7dd20cb1184a1bafb0d8f33e851051bd9e5
2019-08-08 00:01:12 -07:00
Tim
a218880216 Fix compilation with CMake (#909)
Summary:
This adds the root of the source tree to the include path, which allow `#include <yoga/YGEnums.h>` to work.

Fixes https://github.com/facebook/yoga/issues/908
Pull Request resolved: https://github.com/facebook/yoga/pull/909

Differential Revision: D16701716

Pulled By: davidaurelio

fbshipit-source-id: 0fdc6479e4f3119a3e4ddbcd4b48541b282c1bbd
2019-08-07 23:53:44 -07:00
Denis
1a2802028b Update link: (#920)
Summary:
Update link for component kit on docs to `https://componentkit.org/docs/getting-started/`
Pull Request resolved: https://github.com/facebook/yoga/pull/920

Differential Revision: D16701505

Pulled By: davidaurelio

fbshipit-source-id: 10f7df4f7aa29d884d21135a92041b0630e1a31e
2019-08-07 19:51:39 -07:00
Tim
a37b286bae Yoga is written in C++ (#907)
Summary:
As far as I can tell now. Would be nice if you had an actual changelog somewhere!
Pull Request resolved: https://github.com/facebook/yoga/pull/907

Differential Revision: D16701738

Pulled By: davidaurelio

fbshipit-source-id: cf32dc96eca5258979bcaa9947d6ed6b5496398d
2019-08-07 19:44:24 -07:00
David Aurelio
dcfdb955b3 Back out "[Yoga] Experiment: double invocations of measure callbacks"
Summary:
Removes the double measure callbacks experiment
Original commit changesets: c6cf9c01a173,  b157d8137c72

Reviewed By: SidharthGuglani

Differential Revision: D16687367

fbshipit-source-id: 9649f8731bd1b27f4d291cee4fa30153165cea02
2019-08-07 18:24:32 -07:00
David Aurelio
72cefead02 Use Bitfield in YGLayout
Summary: Replaces the usage of C++ bitfields with our portable `Bitfield` class.

Reviewed By: SidharthGuglani

Differential Revision: D16656361

fbshipit-source-id: 05f679e2e994e109b2bd1090c879d6850fabdc40
2019-08-07 16:29:04 -07:00
David Aurelio
884e064a99 Use Bitfield in YGNode and YGStyle
Summary:
@public

Replaces the usage of C++ bitfields with our portable `Bitfield` class.

Reviewed By: SidharthGuglani

Differential Revision: D16649875

fbshipit-source-id: 539f016d5e1c9a8c48cc9bacbbf6ed985e385e69
2019-08-07 16:29:03 -07:00
David Aurelio
3ed9bec05c Remove style property bitmask
Summary:
@public

Removes the style properties bitmask. We have used this for experimentation, and it's no longer necessary.

This simplifyies the code, and allows us to cut over to `Bitfield.h` more easily.

Reviewed By: astreet

Differential Revision: D16648862

fbshipit-source-id: 17c0899807af976f4ba34db54f8f0f6a3cd92519
2019-08-07 16:29:03 -07:00
David Aurelio
dadf0473b7 Add portable bit field implementation
Summary:
@public
Our usage of C++ bit fields has lead to quite some problems with different compiler setups. Problems include sign bits, alignment, etc.

Here we introduce a portable implementation as a variadic template, allowing the user to store a number of booleans and enums (defined with `YG_ENUM_SEQ_DECL`) in an unsigned integer type of their choice.

This will replace all usages of bit fields across the Yoga code base.

Differential Revision: D16647801

fbshipit-source-id: 230ffab500885a3ad662ea8f19e35a5e9357a563
2019-08-07 16:29:02 -07:00
Daniel Büchele
947230958d make npm module
Summary: We want to use the yoga playground as a standalone package as well. This adds a webpack config to bundle the playground for npm. The package can then be distributed as `yoga-playground` via npm

Reviewed By: fabiomassimo

Differential Revision: D16583334

fbshipit-source-id: 84807ddd8983ba9f0fb43570b518c975f35544ab
2019-08-01 04:15:25 -07:00
Sidharth Guglani
095c991b85 Added counts for measure callbacks reasons in an array inside qpl annotations
Summary:
Added an array to maintain the counts of each of the reason of measure callbacks
and this is now added as qpl metadata in Layout Calculation qpl event

Reviewed By: davidaurelio

Differential Revision: D16516379

fbshipit-source-id: 201c5d2463f0a921841a0bbfec8f4d5e007000c8
2019-07-31 14:37:37 -07:00
Sidharth Guglani
825da1e868 create two layout pass reason flexLayout and flexMeasure instead of flex
Summary:
We had flex as a reason for both layout and measure. Now creating separating reason flexLayout and flexMeasure in this diff.

Also changed ordering of items in Enum to group layout and measure reasons

Reviewed By: davidaurelio

Differential Revision: D16562350

fbshipit-source-id: 75501f9d4dde0974009193b3991a8acc97b02ad0
2019-07-31 14:37:36 -07:00
Sidharth Guglani
5a25805cb5 Update flow-copy-source to use latest version
Summary:
Fixes vulnerability in mem dependency by updating the version of flow-copy-source in javascript/yarn.lock
da4e4398cb

Reviewed By: danielbuechele

Differential Revision: D16542191

fbshipit-source-id: e900ac2d358883fc269688b93faad3ffbec10f0d
2019-07-31 06:48:07 -07:00
Sidharth Guglani
adff8d96dd remove getInstanceCount usages
Summary:
This diffs removes the usages of getInstanceCount as it has been removed from yoga.
We will add event support in js later to handle these test cases

Reviewed By: davidaurelio

Differential Revision: D16560269

fbshipit-source-id: 52590c426faf87209f8635602b401fd5760af8ab
2019-07-31 06:48:06 -07:00
Sidharth Guglani
8c270e68cc add subdirectories of yoga also to js sources
Summary: Update build file to include subdirectories of yoga also in sources

Reviewed By: davidaurelio

Differential Revision: D16560253

fbshipit-source-id: 5dee4379912e003d4a1fa611882fbf736321615c
2019-07-31 06:48:06 -07:00
Samuel Susla
a2aa1b7fca Fix onDismiss in Modal
Summary:
# Disclaimer:
I might be missing something as the solution I implemented here seems like something that was considered by original author. If this solution isn't good, I have a plan B.

# Problem:
`onDismiss` prop isn't being called once the modal is dismissed, this diff fixes it.

Also I've noticed that `onDismiss` is meant to only work on iOS, why is that? By landing this diff, it'll be called on Android as well so we need to change the docs (https://facebook.github.io/react-native/docs/modal.html#ondismiss).

## Video that shows the problem
Following code is in playground.js P70222409 which just increments number everytime onDismiss is called

{F166303269}

Reviewed By: shergin

Differential Revision: D16109536

fbshipit-source-id: 3fba56f5671912387b217f03b613dffd89614c9d
2019-07-29 11:18:00 -07:00
Min ho Kim
ae956f06fb Fix typos (#25770)
Summary:
Fix typos mostly in comments and some string literals.

## Changelog

[General] [Fixed] - Fix typos
Pull Request resolved: https://github.com/facebook/react-native/pull/25770

Differential Revision: D16437857

Pulled By: cpojer

fbshipit-source-id: ffeb4d6b175e341381352091134f7c97d78c679f
2019-07-23 03:24:00 -07:00
David Aurelio
8c0eed3c75 Add PhantomRef based YogaNode subclass
Summary: Adds a subclass of `YogaNodeJNIBase` that uses `PhantomReference` for deallocating native memory rather than `Object#finalize()`. This should help making garbage collection more efficient.

Reviewed By: amir-shalem

Differential Revision: D16182667

fbshipit-source-id: d310fdb6af184168c43462b24f5e18ab5d0d7ad0
2019-07-19 17:24:49 -07:00
David Aurelio
4e4ef06de1 Implement double measure experiment
Reviewed By: SidharthGuglani

Differential Revision: D16340462

fbshipit-source-id: b157d8137c72f83a3bea46f30d0f46f65055f9ef
2019-07-19 10:40:17 -07:00
David Aurelio
a53c14dc75 Add internal experiments API
Summary: Adds internal API that we can use to conduct experiments.

Reviewed By: SidharthGuglani

Differential Revision: D16340463

fbshipit-source-id: 07a8bb7dbc4a02c5c95f1ad29b18845ab43752cf
2019-07-19 10:40:16 -07:00
Sidharth Guglani
c99fc9c4da using enum struct for LayoutPassReason and LayoutType
Summary: Using enum struct for using enums in form ENUM_NAME::ENUM_VALUE for better code readablility

Reviewed By: davidaurelio

Differential Revision: D16356562

fbshipit-source-id: cbe7adadad78eb5d0756c44679c0e102b7d31ec6
2019-07-18 07:04:47 -07:00
Uladzislau Paulovich
2fb857d73d yoga | Fix error about implicit conversion to bit-field
Summary:
`YGStyle` puts Yoga enums (which are signed integers by default) into bitfields: https://fburl.com/7fowlunu

Mixing signed values and bit-fields can be error-prone and it also fails to build on Windows with `clang-cl` due to `-Wbitfield-constant-conversion` warning being treated as error:

```
stderr: In file included from xplat\yoga\yoga\YGLayout.cpp:8:
In file included from xplat\yoga\yoga/Utils.h:8:
In file included from xplat\yoga\yoga/YGNode.h:13:
xplat\yoga\yoga/YGStyle.h(110,9): error: implicit truncation from 'YGAlign' to bit-field changes value from 4 to -4 [-Werror,-Wbitfield-constant-conversion]
        alignItems_(YGAlignStretch),
```

This diff fixes the problem by making all enums unsigned integers. This change can be problematic only if values of the enums are serialized somewhere. CC: David Aurelio

Reviewed By: davidaurelio

Differential Revision: D16336729

fbshipit-source-id: ee4dabd7bd1ee429e644bd322b375ec2694cc742
2019-07-18 06:20:18 -07:00
Sidharth Guglani
e6dfe04388 Pass reason for measure pass along with measurecallbackend event (#566)
Summary:
Pull Request resolved: https://github.com/facebook/litho/pull/566

Pull Request resolved: https://github.com/facebook/react-native/pull/25702

Pass reason for each measure callback to the flipper plugin

Reviewed By: davidaurelio

Differential Revision: D16221771

fbshipit-source-id: 2e72e1ebb3c7e633d189e7a7a81d655ac9531e51
2019-07-18 05:21:11 -07:00
Sidharth Guglani
5e40e4b682 remove YGMarker code
Summary: Removes code for now unused marker based approach

Reviewed By: davidaurelio

Differential Revision: D16048800

fbshipit-source-id: 228e0e906252782ee0bed543728b666d1f9cc854
2019-07-17 08:11:38 -07:00
Sidharth Guglani
7c891db9af move YGMarkerMeasure and YGMarkerBaselineFn to event based system
Summary: Using yoga event listener for adding systrace sections for measure and baseline events

Reviewed By: davidaurelio

Differential Revision: D16048795

fbshipit-source-id: 3c2161328250184929ed1a3357b8c42ec8ca2e29
2019-07-17 08:11:37 -07:00
David Aurelio
6d916ab063 Do not depend on libfb
Reviewed By: SidharthGuglani

Differential Revision: D16220913

fbshipit-source-id: c6851d8dbda572aa50117b92353460f8a5b6df36
2019-07-17 06:57:18 -07:00
David Aurelio
59d680f4e9 Upgrade fbjni
Summary:
Upgrades Yoga’s copy of *fbjni* to the latest version.

This will enable us

- to move from `finalize()` to `PhantomReference` to deallocate native memory, with the potential of making GC more efficient.
- to remove the internal dependency to *libfb,* allowing apps without an own dependency to ship less code

Reviewed By: passy

Differential Revision: D16220924

fbshipit-source-id: e8233fe2b5403946ff51f43cb6def558ded52fda
2019-07-17 06:57:18 -07:00
Amir Shalem
be305b5d0f Rename fbjni shared library name to the standard soname
Summary:
Before we can upgrade to latest fbjni, we need to make sure our shared libraries are named the same.

Currently when we compile libfbjni it is named as `liblib_fb_fbjni.so`, where as the regular fbjni is expected to be named as `libfbjni.so`

Reviewed By: davidaurelio

Differential Revision: D16250801

fbshipit-source-id: 9a7f0f803d7e525985b40a49edcc0e660e9025f5
2019-07-17 03:35:31 -07:00
Sidharth Guglani
d676d917e3 moved all yoga node jni batching code to YogaNodeJNIBase and removed subclasses
Summary: Removed classes YogaNodeJNI and YogaNodeJNIBatching and all the logic have been moved to base class

Reviewed By: davidaurelio

Differential Revision: D16221484

fbshipit-source-id: 830819f5bc6010291b8bc0c6d90897cea991909f
2019-07-15 11:16:38 -07:00
Sidharth Guglani
838fc3f019 remove useBatchingForLayoutOutputs config param and start using batching for layout outputs
Summary: Removes config param useBatchingForLayoutOutputs and now we are using batching of layout outputs as float array while passing data from c++ to java

Reviewed By: davidaurelio

Differential Revision: D16221483

fbshipit-source-id: 326c668d4dfd13b2cf031f98a84bfa50b1440513
2019-07-15 11:16:38 -07:00
David Aurelio
296982a29e Enable events in OSS
Summary:
- Events are our new approach to instrumentation, and keeping debug code out of the core library
- This has run internally at FB for some time now
- Enabling for OSS, too, to make Java tests pass

Reviewed By: SidharthGuglani

Differential Revision: D16202541

fbshipit-source-id: c13f5270f04bba59f9f0a06d9c793da92b73d4ff
2019-07-12 01:43:49 -07:00
David Aurelio
1d0668692b Make tests runnable with Buck/OSS again
Summary:
Fixes test execution for open source:

- adds hamcrest jar and dependency, as required by buck (to not throw `"Unable to locate hamcrest on the classpath. Please add as a test dependency."`)
- enables events for OSS, to make tests pass

Reviewed By: SidharthGuglani

Differential Revision: D16202542

fbshipit-source-id: a56069de162f739b3b989961b5dc00f3d37f5849
2019-07-12 01:43:48 -07:00
Sidharth Guglani
39e512f691 Add tests for measure and baseline events
Summary: Add tests for measure and baseline events , same as we had in InstrumentationTests for marker based approach

Reviewed By: davidaurelio

Differential Revision: D16074402

fbshipit-source-id: 8b11cd6468420428701fd5be5c57700cbd913d23
2019-07-10 08:50:44 -07:00
Sidharth Guglani
0f250490d4 add baseline start and baseline end events
Summary: Adds Baseline start and end events to be handled later for instrumentation

Reviewed By: davidaurelio

Differential Revision: D16048790

fbshipit-source-id: 8409dbb633168753a7bf8fab20bc6551d113ddd6
2019-07-10 08:50:43 -07:00
Sidharth Guglani
eeae39d707 move YGMarkerLayout to event based system
Summary: Using layoutPassStart and LayoutPassEnd events instead of YGMarkerLayout for instrumentation

Reviewed By: davidaurelio

Differential Revision: D16048789

fbshipit-source-id: 041a35bc2cb1b7281ca83cf9d35041b4011cfeb9
2019-07-10 08:50:42 -07:00
Sidharth Guglani
ce517689ff add tests for layoutPassStart and layoutPassEnd
Summary: Add tests for layout pass start and end , same as what we had in InstrumentationTests for marker based approach

Reviewed By: davidaurelio

Differential Revision: D16073121

fbshipit-source-id: 838f01cb2a41d2d2764ba7ce2f317147f737b287
2019-07-10 08:50:42 -07:00
Sidharth Guglani
9c82ba783f Adds typed event test data for test cases
Summary: We are now using custom TypedEventTestData for test cases as we need to copy some data passed from the yoga event system

Reviewed By: davidaurelio

Differential Revision: D16090931

fbshipit-source-id: 4d11bdbdd73b67172ad4bba4b294c71f1c24cc10
2019-07-10 08:50:41 -07:00
James Burnett
1c8e8d3aec Compile Issues with Recent GCC (#895)
Summary:
GCC 8.3.0 (and possibly all gcc 7+) identified several warnings for signed unsigned integer comparison. With `-Werror` enabled this broke compiling tests. I suspect the warning is related to google/googletest#683. This diff updates those `ASSERT_EQ` calls that attempt to compare signed and unsigned errors by specifically declaring the literals to be unsigned.

There is also an issue with Buck where it will not link to pthreads. facebook/buck#1443. Adding a `prebuilt_cxx_library` for pthread fixes that issue and the tests will compile and run.

Finally, there was a warning about a missing return after a switch in `InstrumentationTest.cpp`. I added a `return ""` as a default, but it might be better to throw something. Thoughts?
Pull Request resolved: https://github.com/facebook/yoga/pull/895

Reviewed By: davidaurelio

Differential Revision: D15393082

Pulled By: davidaurelio

fbshipit-source-id: 4f13ec2f016af39537c08fb591b188a6a0ed55ce
2019-07-04 19:08:18 -07:00
Uladzislau Paulovich
cc27d85110 Remove incorrect constexpr specifier in YGLayout (#25430)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/25430

Pull Request resolved: https://github.com/facebook/litho/pull/561

Pull Request resolved: https://github.com/facebook/yoga/pull/910

* According to C++ standard values which produce undefined behavior cannot be declared as `constexpr`.
* Expressions which evaluate to `nan, infinity, etc` are undefined behavior.

For more details you can checkout this Stackoverflow answer: https://stackoverflow.com/a/46373136

Reviewed By: davidaurelio

Differential Revision: D16055108

fbshipit-source-id: ee85ba63a714b18bfb8aa8c0770652e184454f74
2019-07-01 08:52:10 -07:00
David Aurelio
cd5324378d Move YG_ENABLE_EVENTS checks to event.h
Summary:
Instead of checking whether `YG_ENABLE_EVENTS` is defined for every publish, we simply wrap the body of the `publish` function macro that delegates to the method that actually publishes the event.

This way we get

1. easier to write code where we publish events
2. more type safety when editing, enabling editors/IDEs to show errors without knowing about `YG_ENABLE_EVENTS`

Reviewed By: SidharthGuglani

Differential Revision: D16049888

fbshipit-source-id: cbf362d6f7be5053c3f377125d303b7137d6a241
2019-06-28 09:58:57 -07:00
David Aurelio
c6ae314202 Stop recording measure callback duration
Summary: Removes time measurements for measure callbacks. This functionality should not be part of Yoga/core, and can now be done by event subscribers themselves, as we have two events per measure callback.

Reviewed By: SidharthGuglani

Differential Revision: D16049812

fbshipit-source-id: e16556f3854e42f4bada39a97a668e718719b22c
2019-06-28 09:58:57 -07:00
David Aurelio
73224c62b5 Publish two events for measure callbacks
Summary: Publishing two events will allow us to replace marker functionality completely with events. This also allows us to remove measuring time spent from Yoga itself.

Reviewed By: SidharthGuglani

Differential Revision: D16049810

fbshipit-source-id: 98628a92ed3c94d479e9fbcd53fac90c5f524087
2019-06-28 09:58:56 -07:00
David Aurelio
2c6a4485f5 Remove duplicate declaration of YGRoundValueToPixelGrid from Yoga-internal.h
Summary:
@public

Removes the declaration of `YGRoundValueToPixelGrid` from `Yoga-internal.h`, as it is already declared in `Yoga.h`. `Yoga.h` is included from `Yoga-internal.h`

Reviewed By: SidharthGuglani

Differential Revision: D16047832

fbshipit-source-id: 72d9d2510372c983eedacc5d7af406b9346f18e6
2019-06-28 05:17:06 -07:00
dattc2
cf005df828 make yoga threadsafe (#852)
Summary:
Continuing https://github.com/facebook/yoga/pull/791
nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request.
# Solution
Improved from previous solution with jpap's suggestions.
2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```.
In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth.
Pull Request resolved: https://github.com/facebook/yoga/pull/852

Reviewed By: SidharthGuglani

Differential Revision: D15537450

Pulled By: davidaurelio

fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
2019-06-25 12:10:23 -07:00
Chris Hopman
f539d68049 Force ordering of :yoga/:yogaForDebug
Summary:
Due to testutil depending on :yoga, we are always linking against both
:yoga and :yogaForDebug in tests. This is only working right now due to luck in
how Buck orders the link line. Adding a dependency is silly but it enforces
that Buck maintain the ordering that we currently have even when it changes how
it does its traversal.

Reviewed By: philipjameson

Differential Revision: D15973581

fbshipit-source-id: 3d18aff578ee4d56175ce5efae52b56aeb2d9586
2019-06-24 17:10:45 -07:00
Sidharth Guglani
39996512fc pass cachedLayout and cachedMeasure measures to plugin
Summary: Passing whether layout cache or measure cache was used or not

Reviewed By: davidaurelio

Differential Revision: D15920937

fbshipit-source-id: a6728e7af07ea228a285f824fbdfddc8130c5990
2019-06-24 08:37:18 -07:00
Sidharth Guglani
2dc5a16d1f Move event NodeLayout to end of NodeLayout step
Summary:
Added event NodeLayoutEnd and this is being used now instead of NodeLayout
It will be used later to add more information about caches

Reviewed By: davidaurelio

Differential Revision: D15920935

fbshipit-source-id: c9f5e193bc8cc70d26ff5d84882d483c9b09f67d
2019-06-24 08:37:17 -07:00
David Aurelio
d667ebd66e Replace relative include
Summary: Replaces the relative include to `YGEnums.h` in `yoga/event/event.h` with `#include <yoga/YGEnums.h>

Reviewed By: SidharthGuglani

Differential Revision: D15778634

fbshipit-source-id: 2bceeb58f26c0d9d0df6c0e7ea20b8ddf68a1ee5
2019-06-21 04:11:36 -07:00
Sidharth Guglani
2b8217ce8d Send measure pass duration
Summary: Send measure callback duration time to yoga plugin

Reviewed By: davidaurelio

Differential Revision: D15917548

fbshipit-source-id: 2c947f14ddbc5932cedd0aab8622260478ec29a6
2019-06-21 02:38:57 -07:00
Stiopa Koltsov
9dac56e824 Migrate Yoga targets to raw_headers
Summary:
In "regular" header mode, Buck will symlink from `buck-out/` to the actual header file. This works fine with GCC and clang, but not with MSVC. Headers will be treated as different file, sidestepping `#pragma once` directives.

As a result, all kinds of symbols get declared twice, leading to compile errors.

Reviewed By: davidaurelio

Differential Revision: D15781947

fbshipit-source-id: a3b4e211b8b74b9ef44fc39471a3009b2cf47260
2019-06-15 12:07:14 -07:00
David Aurelio
a7e8aec3d9 Allow to end markers early
Summary:
Adds the ability to `MarkerSection` to end the marker before it goes out of scope.

This unlocks two scenarios:
- reuse the data associated with a marker after ending it.
- end markers in the middle of a function without adding arbitrary blocks.

Reviewed By: SidharthGuglani

Differential Revision: D15837840

fbshipit-source-id: c0afaeeabd169c65189b5028be54ea7dac3e3b84
2019-06-15 10:26:32 -07:00
David Aurelio
6b5bf570c8 Count the number measure callback invocations
Summary: Counts how many times measure callbacks have been invoked during a layout pass. This is made available via the marker and event APIs.

Reviewed By: SidharthGuglani

Differential Revision: D15836983

fbshipit-source-id: 3835bef94e497375821c9f2ad8209447b4f11518
2019-06-15 10:26:31 -07:00
Sidharth Guglani
a130ac2f9c pass measure callback data from c++ to java
Summary:
Passing Measure callback data - width, widthMeasureMode, height, heightMeasureMode, measuredWidth and measuredHeight along with NodeMeasure event
This data is then propagated to java layer in this diff

Reviewed By: davidaurelio

Differential Revision: D15697523

fbshipit-source-id: 615463da237175ff88abef3f6528b55333ccd915
2019-06-12 00:33:31 -07:00
David Aurelio
19fd066507 Pass layout context for Event::LayoutPassStart
Summary: Adds the layout context pointer when publishing `Event::LayoutPassStart`.

Reviewed By: SidharthGuglani

Differential Revision: D15754425

fbshipit-source-id: 6295ae1ebec9eab72a79c43bc1cb0e05a6d7ae68
2019-06-11 01:41:22 -07:00
David Aurelio
204e849218 rm YogaEventListener
Reviewed By: SidharthGuglani

Differential Revision: D15742456

fbshipit-source-id: b90a221e177e936e141c582500dccf0ac38027c2
2019-06-11 01:41:22 -07:00
Aditya Sharat
8ff13c922a Back out "[litho] Adds check to unset a YogaNode's parent during reconciliation."
Summary: Removes `unsetOwner` from Yoga. This was temporarily for patching a crash.

Reviewed By: colriot

Differential Revision: D15737613

fbshipit-source-id: 8ab93ecf7ffb913df6207fe5db47a8cc93eded2c
2019-06-10 06:57:05 -07:00
Sidharth Guglani
af219f8836 add node layout event and pass it java layer
Summary: Listen to NodeLayout event and passes this event callback to java layer along with the information whether layout or measure was done in this pass

Reviewed By: davidaurelio

Differential Revision: D15696021

fbshipit-source-id: 8c5ca69330a9baca26b77052d4965cc67fe97c75
2019-06-10 01:51:53 -07:00
Aditya Sharat
e33123f955 Adds check to unset a YogaNode's parent during reconciliation.
Summary: Adds check to unset a YogaNode's parent during reconciliation.

Reviewed By: davidaurelio

Differential Revision: D15714899

fbshipit-source-id: 6e2c2a28106574d062fec722c9a051acea87d0b6
2019-06-07 09:28:24 -07:00
Sidharth Guglani
755fa07b39 add node measure event and passing the callback to java layer
Summary: Adds measure event and its listener initial code structure

Reviewed By: davidaurelio

Differential Revision: D15600738

fbshipit-source-id: d15764e0b64edb170fcb15e0912ecce5f7e53595
2019-06-06 21:03:24 -07:00
Sidharth Guglani
2701d80078 passing layout context and getting local reference from it
Summary: We are passing layout context from yoga as event data for Layout Pass End event and it is being then used to get the local reference of node so that we can pass it as method parameter to java layer

Reviewed By: davidaurelio

Differential Revision: D15619640

fbshipit-source-id: 5f6c29d9e6acb73a8d87f8e0cb1577d35a271aeb
2019-06-06 21:03:24 -07:00
Sidharth Guglani
c393ed1381 moved PtrJNode map to YGJtypes.h and passing layout context as data in LayoutPassEnd Event
Summary: Move PtrJNodeMap to header file so that it can be accessed in events subscribers outside yoga

Reviewed By: davidaurelio

Differential Revision: D15619629

fbshipit-source-id: 1bf213efd38ec7bcac6a38070f21fa837c5f17da
2019-06-06 21:03:23 -07:00
Rain ⁣
a4bdd9cd9b standardize C-like MIT copyright headers throughout fbsource
Summary:
`/*` is the standard throughout open source code. For example, Firefox uses single /*: https://hg.mozilla.org/mozilla-central/file/21d22b2f541258d3d1cf96c7ba5ad73e96e616b5/gfx/ipc/CompositorWidgetVsyncObserver.cpp#l3

In addition, Rust considers `/**` to be a doc comment (similar to Javadoc) and having such a comment at the beginning of the file causes `rustc` to barf.

Note that some JavaScript tooling requires `/**`. This is OK since JavaScript files were not covered by the linter in the first place, but it would be good to have that tooling fixed too.

Reviewed By: zertosh

Differential Revision: D15640366

fbshipit-source-id: b4ed4599071516364d6109720750d6a43304c089
2019-06-06 19:44:16 -07:00
Joshua Gross
4a4325afb6 Revert D15602627: [yoga] moved PtrJNode map to YGJtypes.h and passing layout context as data in LayoutPassEnd Event
Differential Revision:
D15602627

Original commit changeset: bb5bd5bbf8dc

fbshipit-source-id: 5ae08826eb706c3794c36738cb9625f82b58641e
2019-06-03 19:57:53 -07:00
Joshua Gross
586eb6102a Revert D15602923: [yoga] passing layout context and getting local reference from it
Differential Revision:
D15602923

Original commit changeset: 54b25956af09

fbshipit-source-id: 8ce26a7f00d76bd5ade18f32ad14d943118a6f31
2019-06-03 19:57:53 -07:00
Sidharth Guglani
b1e6793460 passing layout context and getting local reference from it
Summary: We are passing layout context from yoga as event data for Layout Pass End event and it is being then used to get the local reference of node so that we can pass it as method parameter to java layer

Reviewed By: davidaurelio

Differential Revision: D15602923

fbshipit-source-id: 54b25956af098700cea25c4f7f8ffe0b9117432c
2019-06-03 16:01:51 -07:00
Sidharth Guglani
8b17459254 moved PtrJNode map to YGJtypes.h and passing layout context as data in LayoutPassEnd Event
Summary: Move PtrJNodeMap to header file so that it can be accessed in events subscribers outside yoga

Reviewed By: davidaurelio

Differential Revision: D15602627

fbshipit-source-id: bb5bd5bbf8dcb279f5f87a4fd7287909d4e895d8
2019-06-03 16:01:50 -07:00
David Aurelio
195c166efe Back out "[Yoga] Remove comparison to YGUndefined *and* 0.0f"
Summary: Original commit changeset: 13c8f24e1bc8

Reviewed By: fabiomassimo

Differential Revision: D15583502

fbshipit-source-id: efc6175f6c4925a383fea723195c073f49e2eff1
2019-05-31 15:56:50 -07:00
David Aurelio
0908d3a173 Data structure for exclusive writing
Summary:
Adds a data structure that holds a series of values that can be *borrowed* for exclusive writing.
That means, that only a single consumer can write to any value owned by the data structure.

In addition, the data structure exposes read access via iteration over all contained values.

A typical use case would be a counter with thread-local values that are accumulated by readers in other parts of a programm. The design carefully avoids the use of atomics or locks for reading and writing. This approach avoids cache flushes and bus sync between cores.

Borrowing and returning a value go through a central lock to guarantee the consistency of the underlying data structure.

Values are allocated in a `std::forward_list`, which typically should avoid two values in the same cache line -- in that case, writing to one value would still cause cache flushing on other cores. An alternative approach would be to allocate values continuously on cache line boundaries (with padding between them). We can still change the code if the current approach turns out to be too naive (non-deterministic).

Reviewed By: SidharthGuglani

Differential Revision: D15535018

fbshipit-source-id: 212ac88bba9682a4c9d4326b46de0ee2fb5d9a7e
2019-05-31 09:43:43 -07:00
David Aurelio
f304990656 Use atomic list for event subscribers
Summary:
Replace the *copy on write* vector with an atomic pointer to a linked list.

This allows to publish without locking a mutex, at the cost of the slower traversal of a linked list (a vector has better locality).

At the moment, the typical use case is to have one subscriber, meaning that the afforementioned slower traversal is not a problem.

Adding subscribers is implemented as atomic *compare and swap.*

Reviewed By: SidharthGuglani

Differential Revision: D15546964

fbshipit-source-id: 41bfa41f1ac6be5c9b6bf4288ea3271ee995877e
2019-05-31 01:26:42 -07:00
David Aurelio
cea3865c74 Deprecate YGNode::setConfig
Summary:
We want to phase out usage of config pointers on nodes. Setting configs is no longer needed, as a config is unly used during construction.

Here we deprecate the setter, as it is no longer working as it used to (e.g. changing `useWebDefaults` after a node is constructed).

Reviewed By: SidharthGuglani

Differential Revision: D15416474

fbshipit-source-id: a2cc06cad0c5148cecce056ece5f141b3defe9a9
2019-05-29 07:50:11 -07:00
David Aurelio
b74c0d4766 Remove comparison to YGUndefined *and* 0.0f
Summary: Removes a check introduced in D6969537, comparing `totalFlexGrowFactors` and `resolveFlexGrow` to both `0.0` *and* undefined.

Reviewed By: SidharthGuglani

Differential Revision: D15431425

fbshipit-source-id: 13c8f24e1bc8c49496097a6aa78e20ee5d3964a7
2019-05-22 09:44:36 -07:00
David Aurelio
54e863cef2 Remove YGNode::setAndPropogateUseLegacyFlag
Summary:
`YGNode::setAndPropogateUseLegacyFlag` was only used for debugging purposes.
Here, we replace it with a free function in `Yoga.cpp`.

Now that we have events, the diffing functionality should go into a separate debugging package and be implemented in terms of an event listener. Let's do that as soon as we can support multiple listeners.

Reviewed By: SidharthGuglani

Differential Revision: D15316863

fbshipit-source-id: db929eba7c2de8aa1550e362dd2c175929c0070e
2019-05-21 06:06:37 -07:00
David Aurelio
1938792517 YGNode: Field for web defaults
Summary:
In order to remove the config pointer from nodes, we have to keep track of whether the node is using web defaults.
This information fits into one bit that we can place in padding (i.e. no extra memory needed).

This allows us to get rid of config usage withing `YGNode` with some exceptions:

- `iterChildrenAfterCloningIfNeeded` -- this function will simply receive the configuration, or the cloning callback.
- `setAndPropogateUseLegacyFlag` -- will be removed in D15316863
- in `YGNode::reset` -- will go away utomatically once we remove the config pointer

Reviewed By: SidharthGuglani

Differential Revision: D15391536

fbshipit-source-id: 0fa0d0805c6862bd741fe4a7d9b637ed534f56a4
2019-05-20 10:51:38 -07:00
Sidharth Guglani
aa71dbb5bd mutex lock while accessing event subscribers vector for thread safety
Summary: Using Mutex lock_guard mechanism when writing to subscribers and when accessing them in publish to make a copy

Reviewed By: davidaurelio

Differential Revision: D15391679

fbshipit-source-id: 16713ff28ce1762a5ca4c48c152897a92417e80b
2019-05-19 23:34:41 -07:00
David Aurelio
8dc46c0a87 YGNode: one byte of private storage
Summary:
Adds one byte of private storage to `YGNode`, intended to be used by Yoga itself.

This is in previously unused alignment space, and won’t cause more memory to be allocated.

Reviewed By: SidharthGuglani

Differential Revision: D15296732

fbshipit-source-id: 3caf0a3cd506e4e324e51c31869c69be5781d476
2019-05-16 11:47:30 -07:00
David Aurelio
1180afed9c Fix style property bits
Summary: Style bits had overlap, because `dimensionBit` was set with an incorrect increment.

Reviewed By: SidharthGuglani

Differential Revision: D15335134

fbshipit-source-id: 370e1a73547d76b0e26bc6ab67acb96d33ddf180
2019-05-16 11:47:30 -07:00
Sidharth Guglani
1562bce9b4 use shared_ptr for subscribers vector in event system
Summary:
using shared_ptr for vector of subscribers
Further changes in commit stack support the mutiple subscribers in event system

Reviewed By: davidaurelio

Differential Revision: D15352512

fbshipit-source-id: fac7f4268abf9ca4277734aca2f21cd711eb7d6e
2019-05-15 09:01:06 -07:00
Sidharth Guglani
a9514513a7 use vector for subscribers in event system
Summary:
Replaced global event subscriber with a vector of subscriber functions
Further changes in commit stack support the mutiple subscribers in event system

Reviewed By: davidaurelio

Differential Revision: D15352451

fbshipit-source-id: 7ca6f0943735bf1f76a906c23e15e14ae3c5f42c
2019-05-15 09:01:04 -07:00
Sidharth Guglani
cf809b8e8b added listener in flipper plugin for yoga
Summary:
Adds YogaEventListener interface and it's implementation which will be used in flipper for events coming from Yoga
After this diff , we will start getting layout calculate events in flipper listener

Reviewed By: davidaurelio

Differential Revision: D15316928

fbshipit-source-id: da3a53374a52386037b553d460038d988b0162c2
2019-05-15 01:18:11 -07:00
Yadong Wen
d7ff5c0689 Remove c++1y compiler flag
Reviewed By: meyering

Differential Revision: D15326600

fbshipit-source-id: 837f454ccf27299bc9360174bf54e48e4209bb52
2019-05-14 13:48:02 -07:00
David Aurelio
e3156279fc Travis: Fix C++ compilation
Summary:
@public

Removes the usage of C++14 features, and enforces C++11 via compiler flags.

Reviewed By: SidharthGuglani

Differential Revision: D15334938

fbshipit-source-id: 011764b5f226fef6a35e0c7c1dd170a39ae2261e
2019-05-14 07:45:31 -07:00
gengjiawen
0ce42d83e0 add missing gradle script for windows
Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/885

Differential Revision: D15334309

Pulled By: davidaurelio

fbshipit-source-id: c594c0216a967c776606443a50f14e81da228d64
2019-05-14 06:24:18 -07:00
Shawn Presser
afc1108659 Fix cmake build / update CMakeLists.txt to use C++11 (#887)
Summary:
On MacOS, the following steps result in build errors:

```
mkdir build
cd build
cmake ..
make
```

The problem is that yogacore uses C++11 features (`constexpr`) but C++11 isn't specified in CMakeLists.txt.

This PR solves the poblem by adding the following code to the bottom of CMakeLists.txt:

```
set_target_properties(yogacore PROPERTIES CXX_STANDARD 11)
```

This solution was derived from https://stackoverflow.com/questions/45688522/how-to-enable-c17-in-cmake
Pull Request resolved: https://github.com/facebook/yoga/pull/887

Differential Revision: D15334282

Pulled By: davidaurelio

fbshipit-source-id: a599d8a8f555f7f9cd8dc333e12dc2387d5b2d7a
2019-05-14 05:28:19 -07:00
David Aurelio
a15bf6e701 Publish events for layout pass
Summary:
Adds `LayoutPassStart` and `LayoutPassEnd` events.

The existing `NodeLayout` event in isolation is not as useful as it could be. Having events that mark start and end of a layout pass are a useful addition.

Differential Revision: D15305467

fbshipit-source-id: 14af6f65e698fb1e3112eb2ffd87a74d31df4840
2019-05-10 19:05:07 -07:00
Sidharth Guglani
74fc37efc8 move event files to yoga/events folder
Summary: Moved events files to yoga/events for better code structure

Reviewed By: davidaurelio

Differential Revision: D15198566

fbshipit-source-id: 74d451011841d59fae5a1c637f9c33a7d2d1f87e
2019-05-09 07:46:10 -07:00
David Aurelio
5824dbda66 Publish event when visiting nodes during layout
Summary:
@public

Publish an event when visiting nodes during layouts.

Reviewed By: SidharthGuglani

Differential Revision: D15206965

fbshipit-source-id: c201f084b1d4186bc64560b8033be965f2549236
2019-05-09 04:31:25 -07:00
David Aurelio
e96a09e5ff **breaking:** remove YGNodeGetInstanceCount
Summary:
@public

`YGNodeGetInstanceCount` was only ever meant for tests, and caused data races in multi-threaded environments.

It was completely replaced with event-based counting for tests.

Here we remove public API around the counter, and the counter itself.

Reviewed By: SidharthGuglani

Differential Revision: D15174857

fbshipit-source-id: 228e85da565bac9e8485121e956a2e41910b11c8
2019-05-09 04:31:24 -07:00
David Aurelio
9e20dfeea1 Switch tests to test utility for counting nodes
Summary:
@public
replaces the global node counter with the event-based one for all tests.

Reviewed By: SidharthGuglani

Differential Revision: D15174856

fbshipit-source-id: f4401d502bdbaf3b6e4632a4d985aac260cb35a8
2019-05-09 04:31:24 -07:00
David Aurelio
6e04631862 Add test utilities for C++ and Java
Summary:
@public

Test utility on top of the new event system that maintains a counter of instantiated nodes. Meant to replace the global node counter.

Reviewed By: SidharthGuglani

Differential Revision: D15174855

fbshipit-source-id: 6998472f95a09b8da652257a26596164bdcf43d6
2019-05-09 04:31:23 -07:00
David Aurelio
88b23ebb3d Publish events for node allocation and deallocation
Summary:
@public

Publish two events, `NodeAllocation` and `NodeDeallocation`, in the same places where the global node counter is changed.

Reviewed By: SidharthGuglani

Differential Revision: D15174858

fbshipit-source-id: 6e4e9add88513b9e987189ca5035d76da2a1de55
2019-05-09 04:31:23 -07:00
David Aurelio
018916403e Reduce measure cache size to 8
Summary:
@public

Reduces measure cache size to a number that is enough for 95% of nodes, according to our (FB-internal) measurements.

Node size: 776b -> 584b

Reviewed By: SidharthGuglani

Differential Revision: D15183567

fbshipit-source-id: 9ae8cc78074271a015e7618b931ba0356de87a0c
2019-05-09 03:24:31 -07:00
Adrian Zgorzalek
af38fd31f8 Upgrade prettier to 1.17.0
Summary:
Run `js1 upgrade prettier 1.17.0` and `xplat/js/scripts/update-oss-yarn-lockfile.sh` and `hg revert -r .^ xplat/js/rome`

allow-large-files

Reviewed By: zackargyle, pvdz

Differential Revision: D15164375

fbshipit-source-id: 2fe68733dfa93ea64a67d170ba2f80c5af086917
2019-05-07 12:39:46 -07:00
David Aurelio
1e0ebdae2f Remove API to constrain measure cache size
Summary: We conducted an experiment with different measure cache sizes. This has now been deallocatedi (D15183473). Remove the necessary APIs.

Reviewed By: SidharthGuglani

Differential Revision: D15183486

fbshipit-source-id: a38fa5a3ab0321c2521265f7d1cd6b495efd76cf
2019-05-03 05:54:40 -07:00
David Aurelio
1adbafe950 Fix YGConfig constructors
Summary:
@public

`YGConfig::YGConfig(YGConfig*)` was not initializing the same fields as the default constructors.

Here, we make the default constructor delegate to the more specialized one to remove duplication.

Reviewed By: SidharthGuglani

Differential Revision: D15164599

fbshipit-source-id: 27247709091b7664386057d09ac67d481877871f
2019-05-03 05:01:32 -07:00
David Aurelio
e51ca95713 Add foundations for event system
Summary:
@public

We want to enable tooling, instrumentation, and statistics within Yoga without coupling these functionalities to our core code.

This commit introduces the foundations of a simple, global event system.
For the time being, we will only support a single subscriber. Should we require more than one, we can add support for it later.

Reviewed By: SidharthGuglani

Differential Revision: D15153678

fbshipit-source-id: 7d96f4c8def646a6a1b3908f946e7f81a6dba9c3
2019-05-01 17:08:02 -07:00
David Aurelio
a803421739 YGStyle: Make getters/setters template args of BitfieldRef
Summary:
@public

Makes bitfield getters/setters part of the bitfield ref template.
Since we introduced the tracking bit as template parameter in D14933022, every bitfield ref is an individual class anyway, and having function pointers doesn’t potentially lead to less code generation anyway.

Furthermore, this change can (in the absence of tracking bits) avoid less specialized templates dealing with refs, and to dynamic dispatch as a consequence.

Reviewed By: SidharthGuglani

Differential Revision: D15085495

fbshipit-source-id: 0dd70fa05e9d43a29e38a619cddb642c9ca3f7ab
2019-05-01 06:52:55 -07:00
David Aurelio
011c1964a0 Track which style properties have been set on YGStyle
Summary:
@public

In order to optimise property storage, we have to know how style properties are used in our apps.
Here, we add a bitmask that allows us to track which properties are set explicitely, and use that for our analysis.

Reviewed By: SidharthGuglani

Differential Revision: D14933022

fbshipit-source-id: 1ab8af562b14baba1d02057e527aa36d5c9a7823
2019-05-01 06:52:55 -07:00
David Aurelio
05d205cf89 Deduplicate updateStyle overloads
Summary:
@public

The extra overload of `updateStyle` introduced in D15078961 can also handle `BitfieldRef`.
That means that we can remove the more specific implementation previously introduced for `BitfieldRef`

Reviewed By: SidharthGuglani

Differential Revision: D15081069

fbshipit-source-id: 98f1f3478627974c5273c85d268ca07350f303d7
2019-05-01 06:52:54 -07:00
David Aurelio
0a4f7bd558 YGStyle: mutable accessors return Ref instances
Summary:
@public

Change style property accessors to return `Ref` instances instead of references to `CompactValue`.

This will allow to track assignments to properties later on, e.g. for instrumentation or dynamic property storage.

Reviewed By: SidharthGuglani

Differential Revision: D15078961

fbshipit-source-id: 259f05f7d30f093c04bf333c5bd4fb3601b8e933
2019-05-01 06:52:54 -07:00
David Aurelio
cea862a6bf Expose the value type used by YGStyle as ValueRepr
Summary:
@public

Adds `YGStyle::ValueRepr` to make code depending on the actual type easier to write.

So far, we have treated `yoga::detail::CompactValue` as an implementation detail, and that’s what it’s supposed to stay.

React Native Fabric has one value conversion overload that depends on that type, though, and used `decltype(YGStyle{}.margin()[0])` until now.
That’s problematic for two reasons:

- we want to constrain the parameter of `operator[](...)` to enum types, making the `0` unsuitable
- we want to return the non-const overload of the operator to return a custom `Ref` type, which is not the type needed by Fabric.

Making the storage type explicit allows to write more forward-compatible code.

Reviewed By: SidharthGuglani

Differential Revision: D15078960

fbshipit-source-id: 932c27ef2f2cdc6ce965b79894268170f0ccdce5
2019-04-29 09:23:18 -07:00
David Aurelio
cc02a20c9e More constness
Summary:
@public

Some `YGNode*` passed as `const YGNode*`, some const refs to sub-objects introduced.
This helps selecting the desired methods in more places, i.e. `const` overloads of accessors on `YGStyle`.

Reviewed By: SidharthGuglani

Differential Revision: D15078963

fbshipit-source-id: 5013721d6edcc68f42f4504f5c331da647a294bd
2019-04-29 09:23:17 -07:00
David Aurelio
98fda9c587 YGFloatOptional: Move binary operators to free functions
Summary:
@public

Having binary operators as member functions has disadvantages:

- the left hand side cannot be converted to `YGFloatOptional` implicitly (which we need for `YGStyle` refs)
- Operators are not necessarily commutative.

By moving these operators into free functions, and adding overloads for both variants if one operand is `float`, we get these properties.

Reviewed By: SidharthGuglani

Differential Revision: D15078962

fbshipit-source-id: 2e228a2ef90a8083c91788caa9eedfd4d140677f
2019-04-29 09:23:16 -07:00
David Aurelio
2eed95f3e4 YGNodeToString: take const ref to node style
Summary:
@public

Takes a const reference to the style of the printed node once, instead of using repeated calls to `node->getStyle()`.
Makes the code a bit shorter, and ensures that we are operating on `const YGStyle&`, which helps selecting the correct methods further up the stack.

Reviewed By: SidharthGuglani

Differential Revision: D14999094

fbshipit-source-id: 814f06b7e3179ac8cfb43d79fbec48ee4115d6e3
2019-04-26 02:15:06 -07:00
David Aurelio
e5d3baca81 Introduce YGNodeConstRef
Summary:
@public

Introduces `YGNodeConstRef` as `const YGNode*`, i.e. a pointer to a constant `YGNode`.
We also use it for all style getters, which will avoid casts to `const YGNode*` in diffs up the stack.

We should use this pointer type for all functions that do not modify the underlying node.

Reviewed By: SidharthGuglani

Differential Revision: D14999095

fbshipit-source-id: 61cc53bb35e787a12ae12e70438d84c0a4983752
2019-04-23 10:10:24 -07:00
David Aurelio
dee93017f7 YGStyle: wrap all fields into accessors
Summary:
@public

In order to encapsulate property access on `YGStyle`, as a first measure we wrap all fields with accessors.

This will e.g. enable dynamic property storage and instrumentation in the future.

All accessors have a `const` version that allows direct access via `const&`. For mutation, bit fields are wrapped with a custom reference object.

This style allows for the least amount of changes in client code. Property access simply needs appended parens, eg `style.direction` becomes `style.direction`.

Reviewed By: shergin

Differential Revision: D14999096

fbshipit-source-id: fbf29f7ddab520513d4618f5e70094c4f6330b30
2019-04-23 08:17:18 -07:00
David Aurelio
e167642672 Yoga.h: clean up const / extern
Summary:
@public

Remove unnecessary `const` and `extern` specifiers from `Yoga.h`.

- Function declarations are `extern` by default
- The removed `const` specifiers for pass-by-valye parameters are only meaningful for the *definition* of functions, not for the declaration.
In this specific case, I found `const YGNodeRef` particularly confusing, as it is a `typedef` for a pointer type. `const` does not refer to the pointed-to object, but to the parameter itself, i.e. `const YGNodeRef` is `YGNode * const`, and not `const YGNode *`.

Reviewed By: SidharthGuglani

Differential Revision: D14999097

fbshipit-source-id: 8350870cb67f4a34722f796c4f4a2fc7dde41b99
2019-04-23 08:17:16 -07:00
David Aurelio
e9bb1efb03 Code formatting: allow short inline methods on one line
Summary:
@public

This allows short methods defined in class declarations to occupy a single line.
The change makes class declarations more readable.

Reviewed By: SidharthGuglani

Differential Revision: D14950012

fbshipit-source-id: 1321949475184181c6cceb86613f730e430763e2
2019-04-16 07:12:58 -07:00
David Aurelio
3f7d03b443 Define all style getters/setters explicitely
Summary:
@public

For better grepping, we define all `YGNodeStyle...` accessors explicitely. This also replaces all macros with a set of templates that can easily be updated when we switch to style accessors on `YGNode`.

Transitioning to a consistent set of templates also allowed to end up with a single *needs update* / *do update* / *mark dirty* block.

The new template code also takes full advantage of the properties of `YGOptional` (constructor call with *not a number* creates an empty optional) and `detail::CompactValue` (conversions of *auto* and *undefined* are always well-formed) to get rid of some additional code:

Removed `NAN` check:
```
 _YGNodeStyleSetFlex:
 	pushq	%rbp
 	movq	%rsp, %rbp
 	movss	0x34(%rdi), %xmm1
 	ucomiss	%xmm0, %xmm1
 	jne	0x____
 	jnp	0x____
 	ucomiss	%xmm0, %xmm0
 	jnp	0x____
 	ucomiss	%xmm1, %xmm1
 	jnp	0x____
 	popq	%rbp
 	retq
-	ucomiss	%xmm0, %xmm0
-	movd	%xmm0, %eax
-	movl	$0x7fc00000, %ecx
-	cmovnpl	%eax, %ecx
-	movl	%ecx, 0x34(%rdi)
+	movss	%xmm0, 0x34(%rdi)
 	popq	%rbp
 	jmp	0x____
-	nopw	%cs:(%rax,%rax)
-	nop
+	nopw	(%rax,%rax)
```

Removed well-formedness check:
```
 _YGNodeStyleGetPosition:
 	pushq	%rbp
 	movq	%rsp, %rbp
 	movl	%esi, %eax
 	movl	0x68(%rdi,%rax,4), %ecx
+	xorl	%eax, %eax
 	movq	(%rip), %rcx
 	movl	(%rcx), %eax
 	movl	0x4(%rcx), %ecx
-	movq	%rcx, %rdx
-	shlq	$0x20, %rdx
+	shlq	$0x20, %rcx
 	movl	%eax, %eax
-	orq	%rdx, %rax
-	cmpl	$0x3, %ecx
-	je	0x____
-	testl	%ecx, %ecx
-	jne	0x____
-	movl	$0x7fc00000, %ecx
-	jmp	0x____
-	movq	%rax, %rcx
-	movabsq	$-0x100000000, %rdx
-	andq	%rax, %rdx
-	movl	%ecx, %eax
-	orq	%rdx, %rax
+	orq	%rcx, %rax
 	popq	%rbp
 	retq
 	nopw	(%rax,%rax)
```

Reviewed By: SidharthGuglani

Differential Revision: D14911973

fbshipit-source-id: db6eef65f8fdaf70875f7fe8799919ca88bd50ee
2019-04-15 10:51:44 -07:00
Sidharth Guglani
ffce716557 Use only 4 edges for margin, padding, border in YGLayout
Summary:
We were using four edges for margin, padding and border. This diff changes the array size in YGLayout for margin, padding, border to reduce YGNode size and corresponding changes while we are setting values in YGLayout.
Reduces the YGNode size by 24 bytes

Reviewed By: davidaurelio

Differential Revision: D14892666

fbshipit-source-id: 94013d5183ee869901267c4c9941fd94fa05d848
2019-04-15 05:41:59 -07:00
Andres Suarez
fcfb19e9cf Enable black for xplat/yoga
Summary:
This directory was excluded from Black formatting in D14888843 when Black
was turned on for all of `xplat/`. Since there aren't a lot of `.py` files in
this directory, the opt-out is being removed, and the outstanding issues fixed.

Reviewed By: d16r

Differential Revision: D14889104

fbshipit-source-id: 440077c1efcb4c653151bca1da5636212978add5
2019-04-11 05:24:34 -07:00
David Aurelio
c5f105a7b6 JNI: set language level to C++11
Summary:
@public

compiler flags were pushed to C++14, but we don’t currently have any code that requires it. Setting to `-std=c++11` in order to fix the OSS build.

Reviewed By: SidharthGuglani

Differential Revision: D14833737

fbshipit-source-id: df2cd7da8c7124e89863c90d7b77bcf86c495618
2019-04-09 03:12:32 -07:00
David Aurelio
b062d23947 Add -SNAPSHOT to gradle version
Summary:
@public

needed for snapshot releases off of master.

Reviewed By: colriot

Differential Revision: D14833415

fbshipit-source-id: f3b1fb1c41318a9b8f634cd16d37d5e2d050398f
2019-04-08 10:57:18 -07:00
297 changed files with 10081 additions and 6227 deletions

View File

@@ -9,7 +9,7 @@ AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None

View File

@@ -1,5 +1,6 @@
language: java
os: linux
dist: trusty
addons:
apt:
sources:

22
BUCK
View File

@@ -9,21 +9,17 @@ GMOCK_OVERRIDE_FLAGS = [
"-Wno-inconsistent-missing-override",
]
COMPILER_FLAGS = LIBRARY_COMPILER_FLAGS + [
"-std=c++1y",
]
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + [
"-std=c++1y",
"-DDEBUG",
"-DYG_ENABLE_EVENTS",
]
yoga_cxx_library(
name = "yoga",
srcs = glob(["yoga/*.cpp"]),
header_namespace = "",
exported_headers = subdir_glob([("", "yoga/*.h")]),
compiler_flags = COMPILER_FLAGS,
srcs = glob(["yoga/**/*.cpp"]),
compiler_flags = LIBRARY_COMPILER_FLAGS,
public_include_directories = ["."],
raw_headers = glob(["yoga/**/*.h"]),
soname = "libyogacore.$(ext)",
tests = [":YogaTests"],
visibility = ["PUBLIC"],
@@ -34,14 +30,15 @@ yoga_cxx_library(
yoga_cxx_library(
name = "yogaForDebug",
srcs = glob(["yoga/*.cpp"]),
header_namespace = "",
exported_headers = subdir_glob([("", "yoga/*.h")]),
srcs = glob(["yoga/**/*.cpp"]),
compiler_flags = TEST_COMPILER_FLAGS,
public_include_directories = ["."],
raw_headers = glob(["yoga/**/*.h"]),
soname = "libyogacore.$(ext)",
tests = [":YogaTests"],
visibility = ["PUBLIC"],
deps = [
":yoga",
yoga_dep("lib/fb:ndklog"),
],
)
@@ -55,6 +52,7 @@ yoga_cxx_test(
visibility = ["PUBLIC"],
deps = [
":yogaForDebug",
yoga_dep("testutil:testutil"),
GTEST_TARGET,
],
)

View File

@@ -9,7 +9,9 @@ cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
file(GLOB yogacore_SRC yoga/*.cpp)
file(GLOB_RECURSE yogacore_SRC yoga/*.cpp)
add_library(yogacore STATIC ${yogacore_SRC})
target_include_directories(yogacore PUBLIC .)
target_link_libraries(yogacore android log)
set_target_properties(yogacore PROPERTIES CXX_STANDARD 11)

View File

@@ -1,3 +1,77 @@
# Code of Conduct
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct/) so that you can understand what actions will and will not be tolerated.
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at <opensource-conduct@fb.com>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@@ -1,7 +1,7 @@
# Yoga [![CocoaPods](https://img.shields.io/cocoapods/v/YogaKit.svg)](http://cocoapods.org/pods/YogaKit) [![npm](https://img.shields.io/npm/v/yoga-layout.svg)](https://www.npmjs.com/package/yoga-layout) [![bintray](https://img.shields.io/bintray/v/facebook/maven/com.facebook.yoga:yoga.svg)](https://bintray.com/facebook/maven/com.facebook.yoga%3Ayoga/_latestVersion) [![NuGet](https://img.shields.io/nuget/v/Facebook.Yoga.svg)](https://www.nuget.org/packages/Facebook.Yoga)
## Building
Yoga builds with [buck](https://buckbuild.com). Make sure you install buck before contributing to Yoga. Yoga's main implementation is in C, with bindings to supported languages and frameworks. When making changes to Yoga please ensure the changes are also propagated to these bindings when applicable.
Yoga builds with [buck](https://buckbuild.com). Make sure you install buck before contributing to Yoga. Yoga's main implementation is in C++, with bindings to supported languages and frameworks. When making changes to Yoga please ensure the changes are also propagated to these bindings when applicable.
## Testing
For testing we rely on [gtest](https://github.com/google/googletest) as a submodule. After cloning Yoga run `git submodule init` followed by `git submodule update`.

View File

@@ -859,9 +859,6 @@
597633381F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */; };
597633391F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */; };
598FD1921F816A2A006C54CB /* RAMBundleRegistry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = C6D380181F71D75B00621378 /* RAMBundleRegistry.h */; };
598FD1951F817335006C54CB /* RCTModalManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 91076A881F743AB00081B4FA /* RCTModalManager.h */; };
598FD1961F817335006C54CB /* RCTModalManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91076A871F743AB00081B4FA /* RCTModalManager.m */; };
598FD1971F817336006C54CB /* RCTModalManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 91076A881F743AB00081B4FA /* RCTModalManager.h */; };
599FAA361FB274980058CCF6 /* RCTSurface.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2A1FB274970058CCF6 /* RCTSurface.h */; };
599FAA371FB274980058CCF6 /* RCTSurface.h in Headers */ = {isa = PBXBuildFile; fileRef = 599FAA2A1FB274970058CCF6 /* RCTSurface.h */; };
599FAA381FB274980058CCF6 /* RCTSurface.mm in Sources */ = {isa = PBXBuildFile; fileRef = 599FAA2B1FB274970058CCF6 /* RCTSurface.mm */; };
@@ -999,7 +996,6 @@
8507BBBF21EDACC200AEAFCA /* JSCExecutorFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8507BBBC21EDACC200AEAFCA /* JSCExecutorFactory.mm */; };
8507BBC021EDACC200AEAFCA /* JSCExecutorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 8507BBBD21EDACC200AEAFCA /* JSCExecutorFactory.h */; };
8507BBC121EDACC200AEAFCA /* JSCExecutorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 8507BBBD21EDACC200AEAFCA /* JSCExecutorFactory.h */; };
916F9C2D1F743F57002E5920 /* RCTModalManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91076A871F743AB00081B4FA /* RCTModalManager.m */; };
A2440AA21DF8D854006E7BFC /* RCTReloadCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = A2440AA01DF8D854006E7BFC /* RCTReloadCommand.h */; };
A2440AA31DF8D854006E7BFC /* RCTReloadCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = A2440AA11DF8D854006E7BFC /* RCTReloadCommand.m */; };
A2440AA41DF8D865006E7BFC /* RCTReloadCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = A2440AA01DF8D854006E7BFC /* RCTReloadCommand.h */; };
@@ -2059,8 +2055,6 @@
83F15A171B7CC46900F10295 /* UIView+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+Private.h"; sourceTree = "<group>"; };
8507BBBC21EDACC200AEAFCA /* JSCExecutorFactory.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSCExecutorFactory.mm; sourceTree = "<group>"; };
8507BBBD21EDACC200AEAFCA /* JSCExecutorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCExecutorFactory.h; sourceTree = "<group>"; };
91076A871F743AB00081B4FA /* RCTModalManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTModalManager.m; sourceTree = "<group>"; };
91076A881F743AB00081B4FA /* RCTModalManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTModalManager.h; sourceTree = "<group>"; };
A2440AA01DF8D854006E7BFC /* RCTReloadCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTReloadCommand.h; sourceTree = "<group>"; };
A2440AA11DF8D854006E7BFC /* RCTReloadCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTReloadCommand.m; sourceTree = "<group>"; };
AC70D2E81DE489E4002E6351 /* RCTJavaScriptLoader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTJavaScriptLoader.mm; sourceTree = "<group>"; };
@@ -2405,8 +2399,6 @@
83392EB21B6634E10013B15F /* RCTModalHostViewController.m */,
83A1FE8D1B62643A00BE0E65 /* RCTModalHostViewManager.h */,
83A1FE8E1B62643A00BE0E65 /* RCTModalHostViewManager.m */,
91076A881F743AB00081B4FA /* RCTModalManager.h */,
91076A871F743AB00081B4FA /* RCTModalManager.m */,
58114A121AAE854800E7D092 /* RCTPicker.h */,
58114A131AAE854800E7D092 /* RCTPicker.m */,
58114A141AAE854800E7D092 /* RCTPickerManager.h */,
@@ -3028,7 +3020,6 @@
3D7BFD301EA8E3FA008DFB7A /* RCTSRWebSocket.h in Headers */,
59EDBCA81FDF4E0C003573DE /* RCTScrollableProtocol.h in Headers */,
3D302F6C1DF828F800D6DDAE /* RCTAnimationType.h in Headers */,
598FD1951F817335006C54CB /* RCTModalManager.h in Headers */,
657734871EE834E000A0E9EA /* RCTInspectorDevServerHelper.h in Headers */,
3D302F6D1DF828F800D6DDAE /* RCTAutoInsetsProtocol.h in Headers */,
3D302F6E1DF828F800D6DDAE /* RCTBorderDrawing.h in Headers */,
@@ -3189,7 +3180,6 @@
3D80DA2D1DF820620028D040 /* RCTFrameUpdate.h in Headers */,
3D80DA2E1DF820620028D040 /* RCTImageSource.h in Headers */,
3D80DA2F1DF820620028D040 /* RCTInvalidating.h in Headers */,
598FD1971F817336006C54CB /* RCTModalManager.h in Headers */,
599FAA3A1FB274980058CCF6 /* RCTSurfaceDelegate.h in Headers */,
3D80DA301DF820620028D040 /* RCTJavaScriptExecutor.h in Headers */,
3DCE53281FEAB23100613583 /* RCTDatePicker.h in Headers */,
@@ -4002,7 +3992,6 @@
2D3B5EA81D9B08D300451313 /* RCTUtils.m in Sources */,
599FAA451FB274980058CCF6 /* RCTSurfaceRootView.mm in Sources */,
2D3B5EC81D9B095800451313 /* RCTActivityIndicatorViewManager.m in Sources */,
598FD1961F817335006C54CB /* RCTModalManager.m in Sources */,
3DCD185D1DF978E7007FE5A1 /* RCTReloadCommand.m in Sources */,
130443DB1E401ADD00D93A67 /* RCTConvert+Transform.m in Sources */,
3D0B84301EC0B51200B2BD8E /* RCTTVNavigationEventEmitter.m in Sources */,
@@ -4254,7 +4243,6 @@
391E86A41C623EC800009732 /* RCTTouchEvent.m in Sources */,
1450FF861BCFF28A00208362 /* RCTProfile.m in Sources */,
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */,
916F9C2D1F743F57002E5920 /* RCTModalManager.m in Sources */,
F1EFDA50201F661000EE6E4C /* RCTUIUtils.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -180,7 +180,7 @@ static YGConfigRef globalConfig;
// the measure function. Since we already know that this is a leaf,
// this *should* be fine. Forgive me Hack Gods.
const YGNodeRef node = self.node;
if (YGNodeHasMeasureFunc(node)) {
if (!YGNodeHasMeasureFunc(node)) {
YGNodeSetMeasureFunc(node, YGMeasureView);
}

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -12,7 +12,7 @@ load(
"yoga_dep",
)
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++14"]
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"]
fb_native.csharp_library(
name = "yogalibnet46",

View File

@@ -43,9 +43,6 @@ namespace Facebook.Yoga
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGConfigFree(IntPtr node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int YGNodeGetInstanceCount();
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int YGConfigGetInstanceCount();

View File

@@ -673,10 +673,5 @@ namespace Facebook.Yoga
return _children != null ? ((IEnumerable<YogaNode>)_children).GetEnumerator() :
System.Linq.Enumerable.Empty<YogaNode>().GetEnumerator();
}
public static int GetInstanceCount()
{
return Native.YGNodeGetInstanceCount();
}
}
}

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,3 +1,9 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Yoga.rc

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

286
enums.py
View File

@@ -3,107 +3,57 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import absolute_import, division, print_function, unicode_literals
import os
ENUMS = {
'Direction': [
'Inherit',
'LTR',
'RTL',
"Direction": ["Inherit", "LTR", "RTL"],
"Unit": ["Undefined", "Point", "Percent", "Auto"],
"FlexDirection": ["Column", "ColumnReverse", "Row", "RowReverse"],
"Justify": [
"FlexStart",
"Center",
"FlexEnd",
"SpaceBetween",
"SpaceAround",
"SpaceEvenly",
],
'Unit': [
'Undefined',
'Point',
'Percent',
'Auto',
"Overflow": ["Visible", "Hidden", "Scroll"],
"Align": [
"Auto",
"FlexStart",
"Center",
"FlexEnd",
"Stretch",
"Baseline",
"SpaceBetween",
"SpaceAround",
],
'FlexDirection': [
'Column',
'ColumnReverse',
'Row',
'RowReverse',
"PositionType": ["Relative", "Absolute"],
"Display": ["Flex", "None"],
"Wrap": ["NoWrap", "Wrap", "WrapReverse"],
"MeasureMode": ["Undefined", "Exactly", "AtMost"],
"Dimension": ["Width", "Height"],
"Edge": [
"Left",
"Top",
"Right",
"Bottom",
"Start",
"End",
"Horizontal",
"Vertical",
"All",
],
'Justify': [
'FlexStart',
'Center',
'FlexEnd',
'SpaceBetween',
'SpaceAround',
'SpaceEvenly',
],
'Overflow': [
'Visible',
'Hidden',
'Scroll',
],
'Align': [
'Auto',
'FlexStart',
'Center',
'FlexEnd',
'Stretch',
'Baseline',
'SpaceBetween',
'SpaceAround',
],
'PositionType': [
'Relative',
'Absolute',
],
'Display': [
'Flex',
'None',
],
'Wrap': [
'NoWrap',
'Wrap',
'WrapReverse',
],
'MeasureMode': [
'Undefined',
'Exactly',
'AtMost',
],
'Dimension': [
'Width',
'Height',
],
'Edge': [
'Left',
'Top',
'Right',
'Bottom',
'Start',
'End',
'Horizontal',
'Vertical',
'All',
],
'NodeType': [
'Default',
'Text',
],
'LogLevel': [
'Error',
'Warn',
'Info',
'Debug',
'Verbose',
'Fatal',
],
'ExperimentalFeature': [
"NodeType": ["Default", "Text"],
"LogLevel": ["Error", "Warn", "Info", "Debug", "Verbose", "Fatal"],
"ExperimentalFeature": [
# Mimic web flex-basis behavior.
'WebFlexBasis',
],
'PrintOptions': [
('Layout', 1),
('Style', 2),
('Children', 4),
"WebFlexBasis"
],
"PrintOptions": [("Layout", 1), ("Style", 2), ("Children", 4)],
}
LICENSE = """/**
@@ -115,23 +65,25 @@ LICENSE = """/**
"""
def to_java_upper(symbol):
symbol = str(symbol)
out = ''
out = ""
for i in range(0, len(symbol)):
c = symbol[i]
if str.istitle(c) and i is not 0 and not str.istitle(symbol[i - 1]):
out += '_'
out += "_"
out += c.upper()
return out
def to_log_lower(symbol):
symbol = str(symbol)
out = ''
out = ""
for i in range(0, len(symbol)):
c = symbol[i]
if str.istitle(c) and i is not 0 and not str.istitle(symbol[i - 1]):
out += '-'
out += "-"
out += c.lower()
return out
@@ -139,114 +91,128 @@ def to_log_lower(symbol):
root = os.path.dirname(os.path.abspath(__file__))
# write out C & Objective-C headers
with open(root + '/yoga/YGEnums.h', 'w') as f:
with open(root + "/yoga/YGEnums.h", "w") as f:
f.write(LICENSE)
f.write('#pragma once\n\n')
f.write("#pragma once\n\n")
f.write('#include "YGMacros.h"\n\n')
f.write('YG_EXTERN_C_BEGIN\n\n')
f.write("YG_EXTERN_C_BEGIN\n\n")
for name, values in sorted(ENUMS.items()):
f.write('#define YG%sCount %s\n' % (name, len(values)))
f.write('typedef YG_ENUM_BEGIN(YG%s) {\n' % name)
f.write("#define YG%sCount %s\n" % (name, len(values)))
f.write("typedef YG_ENUM_BEGIN(YG%s) {\n" % name)
for value in values:
if isinstance(value, tuple):
f.write(' YG%s%s = %d,\n' % (name, value[0], value[1]))
f.write(" YG%s%s = %d,\n" % (name, value[0], value[1]))
else:
f.write(' YG%s%s,\n' % (name, value))
f.write('} YG_ENUM_END(YG%s);\n' % name)
f.write('WIN_EXPORT const char *YG%sToString(const YG%s value);\n' % (name, name))
f.write('\n')
f.write('YG_EXTERN_C_END\n')
f.write(" YG%s%s,\n" % (name, value))
f.write("} YG_ENUM_END(YG%s);\n" % name)
f.write(
"WIN_EXPORT const char *YG%sToString(const YG%s value);\n" % (name, name)
)
f.write("\n")
f.write("YG_EXTERN_C_END\n")
# write out C body for printing
with open(root + '/yoga/YGEnums.cpp', 'w') as f:
with open(root + "/yoga/YGEnums.cpp", "w") as f:
f.write(LICENSE)
f.write('#include "YGEnums.h"\n\n')
for name, values in sorted(ENUMS.items()):
f.write('const char *YG%sToString(const YG%s value){\n' % (name, name))
f.write(' switch(value){\n')
f.write("const char *YG%sToString(const YG%s value){\n" % (name, name))
f.write(" switch(value){\n")
for value in values:
if isinstance(value, tuple):
f.write(' case YG%s%s:\n' % (name, value[0]))
f.write(" case YG%s%s:\n" % (name, value[0]))
f.write(' return "%s";\n' % to_log_lower(value[0]))
else:
f.write(' case YG%s%s:\n' % (name, value))
f.write(" case YG%s%s:\n" % (name, value))
f.write(' return "%s";\n' % to_log_lower(value))
f.write(' }\n')
f.write(" }\n")
f.write(' return "unknown";\n')
f.write('}\n\n')
f.write("}\n\n")
# write out java files
for name, values in sorted(ENUMS.items()):
with open(root + '/java/com/facebook/yoga/Yoga%s.java' % name, 'w') as f:
f.write(LICENSE.replace('/**', '/*', 1))
f.write('package com.facebook.yoga;\n\n')
f.write('import com.facebook.proguard.annotations.DoNotStrip;\n\n')
f.write('@DoNotStrip\n')
f.write('public enum Yoga%s {\n' % name)
with open(root + "/java/com/facebook/yoga/Yoga%s.java" % name, "w") as f:
f.write(LICENSE.replace("/**", "/*", 1))
f.write("package com.facebook.yoga;\n\n")
f.write("import com.facebook.proguard.annotations.DoNotStrip;\n\n")
f.write("@DoNotStrip\n")
f.write("public enum Yoga%s {\n" % name)
if len(values) > 0:
for value in values:
if isinstance(value, tuple):
f.write(' %s(%d)' % (to_java_upper(value[0]), value[1]))
f.write(" %s(%d)" % (to_java_upper(value[0]), value[1]))
else:
f.write(' %s(%d)' % (to_java_upper(value), values.index(value)))
f.write(" %s(%d)" % (to_java_upper(value), values.index(value)))
if values.index(value) is len(values) - 1:
f.write(';\n')
f.write(";\n")
else:
f.write(',\n')
f.write(",\n")
else:
f.write('__EMPTY(-1);')
f.write('\n')
f.write(' private int mIntValue;\n')
f.write('\n')
f.write(' Yoga%s(int intValue) {\n' % name)
f.write(' mIntValue = intValue;\n')
f.write(' }\n')
f.write('\n')
f.write(' public int intValue() {\n')
f.write(' return mIntValue;\n')
f.write(' }\n')
f.write('\n')
f.write(' public static Yoga%s fromInt(int value) {\n' % name)
f.write(' switch (value) {\n')
f.write("__EMPTY(-1);")
f.write("\n")
f.write(" private int mIntValue;\n")
f.write("\n")
f.write(" Yoga%s(int intValue) {\n" % name)
f.write(" mIntValue = intValue;\n")
f.write(" }\n")
f.write("\n")
f.write(" public int intValue() {\n")
f.write(" return mIntValue;\n")
f.write(" }\n")
f.write("\n")
f.write(" public static Yoga%s fromInt(int value) {\n" % name)
f.write(" switch (value) {\n")
for value in values:
if isinstance(value, tuple):
f.write(' case %d: return %s;\n' % (value[1], to_java_upper(value[0])))
f.write(
" case %d: return %s;\n" % (value[1], to_java_upper(value[0]))
)
else:
f.write(' case %d: return %s;\n' % (values.index(value), to_java_upper(value)))
f.write(' default: throw new IllegalArgumentException("Unknown enum value: " + value);\n')
f.write(' }\n')
f.write(' }\n')
f.write('}\n')
f.write(
" case %d: return %s;\n"
% (values.index(value), to_java_upper(value))
)
f.write(
' default: throw new IllegalArgumentException("Unknown enum value: " + value);\n'
)
f.write(" }\n")
f.write(" }\n")
f.write("}\n")
# write out csharp files
for name, values in sorted(ENUMS.items()):
with open(root + '/csharp/Facebook.Yoga/Yoga%s.cs' % name, 'w') as f:
with open(root + "/csharp/Facebook.Yoga/Yoga%s.cs" % name, "w") as f:
f.write(LICENSE)
f.write('namespace Facebook.Yoga\n{\n')
f.write("namespace Facebook.Yoga\n{\n")
if isinstance(next(iter(values or []), None), tuple):
f.write(' [System.Flags]\n')
f.write(' public enum Yoga%s\n {\n' % name)
f.write(" [System.Flags]\n")
f.write(" public enum Yoga%s\n {\n" % name)
for value in values:
if isinstance(value, tuple):
f.write(' %s = %d,\n' % (value[0], value[1]))
f.write(" %s = %d,\n" % (value[0], value[1]))
else:
f.write(' %s,\n' % value)
f.write(' }\n')
f.write('}\n')
f.write(" %s,\n" % value)
f.write(" }\n")
f.write("}\n")
# write out javascript file
with open(root + '/javascript/sources/YGEnums.js', 'w') as f:
with open(root + "/javascript/sources/YGEnums.js", "w") as f:
f.write(LICENSE)
f.write('module.exports = {\n\n')
f.write("module.exports = {\n\n")
for name, values in sorted(ENUMS.items()):
f.write(' %s_COUNT: %s,\n' % (to_java_upper(name), len(values)))
f.write(" %s_COUNT: %s,\n" % (to_java_upper(name), len(values)))
base = 0
for value in values:
if isinstance(value, tuple):
f.write(' %s_%s: %d,\n' % (to_java_upper(name), to_java_upper(value[0]), value[1]))
f.write(
" %s_%s: %d,\n"
% (to_java_upper(name), to_java_upper(value[0]), value[1])
)
base = value[1] + 1
else:
f.write(' %s_%s: %d,\n' % (to_java_upper(name), to_java_upper(value), base))
f.write(
" %s_%s: %d,\n" % (to_java_upper(name), to_java_upper(value), base)
)
base += 1
f.write('\n')
f.write('};\n')
f.write("\n")
f.write("};\n")

View File

@@ -9,7 +9,7 @@
org.gradle.jvmargs=-Xmx1536M
VERSION_NAME=1.14.0
VERSION_NAME=1.16.0
POM_URL=https://github.com/facebook/yoga
POM_SCM_URL=https://github.com/facebook/yoga.git
POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git

84
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -3,13 +3,18 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "FBJNI_JAVA_TARGET", "FBJNI_TARGET", "INFER_ANNOTATIONS_TARGET", "JNI_TARGET", "JSR_305_TARGET", "JUNIT_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_cxx_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test")
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "FBJNI_JAVA_TARGET", "FBJNI_TARGET", "INFER_ANNOTATIONS_TARGET", "JNI_TARGET", "JSR_305_TARGET", "JUNIT_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_cxx_lib", "yoga_cxx_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test")
CXX_LIBRARY_WHITELIST_FOR_TESTS = CXX_LIBRARY_WHITELIST + [
yoga_cxx_lib("testutil:jni"),
yoga_cxx_lib("testutil:testutil"),
]
yoga_cxx_library(
name = "jni",
srcs = glob(["jni/*.cpp"]),
headers = glob(["jni/*.h"]),
header_namespace = "",
header_namespace = "yoga/java",
exported_headers = glob(["jni/*.h"]),
allow_jni_merging = True,
compiler_flags = [
"-fno-omit-frame-pointer",
@@ -18,7 +23,7 @@ yoga_cxx_library(
"-Wall",
"-Werror",
"-Os",
"-std=c++14",
"-std=c++11",
],
platforms = ANDROID,
preprocessor_flags = [
@@ -45,6 +50,7 @@ yoga_java_library(
visibility = ["PUBLIC"],
deps = [
":jni",
FBJNI_JAVA_TARGET,
INFER_ANNOTATIONS_TARGET,
JSR_305_TARGET,
PROGRUARD_ANNOTATIONS_TARGET,
@@ -55,11 +61,12 @@ yoga_java_library(
yoga_java_test(
name = "tests",
srcs = glob(["tests/**/*.java"]),
cxx_library_whitelist = CXX_LIBRARY_WHITELIST,
cxx_library_whitelist = CXX_LIBRARY_WHITELIST_FOR_TESTS,
use_cxx_libraries = True,
visibility = ["PUBLIC"],
deps = [
":java",
yoga_dep("testutil:java"),
JUNIT_TARGET,
],
)

View File

@@ -62,6 +62,7 @@ dependencies {
compileOnly project(':yoga:proguard-annotations')
implementation 'com.facebook.soloader:soloader:0.5.1'
testImplementation 'junit:junit:4.12'
testCompile project(':testutil')
}
task sourcesJar(type: Jar) {

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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;
public enum LayoutPassReason {
INITIAL(0),
ABS_LAYOUT(1),
STRETCH(2),
MULTILINE_STRETCH(3),
FLEX_LAYOUT(4),
MEASURE(5),
ABS_MEASURE(6),
FLEX_MEASURE(7);
private final int mIntValue;
LayoutPassReason(int intValue) {
mIntValue = intValue;
}
public int intValue() {
return mIntValue;
}
public static LayoutPassReason fromInt(int value) {
switch (value) {
case 0: return INITIAL;
case 1: return ABS_LAYOUT;
case 2: return STRETCH;
case 3: return MULTILINE_STRETCH;
case 4: return FLEX_LAYOUT;
case 5: return MEASURE;
case 6: return ABS_MEASURE;
case 7: return FLEX_MEASURE;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
}
}
}

View File

@@ -11,7 +11,6 @@ import com.facebook.soloader.SoLoader;
public class YogaConfig {
public static int SPACING_TYPE = 1;
public static boolean useBatchingForLayoutOutputs = false;
long mNativePointer;
private YogaLogger mLogger;

View File

@@ -0,0 +1,7 @@
package com.facebook.yoga;
public abstract class YogaConfigFactory {
public static YogaConfig create() {
return new YogaConfig();
}
}

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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;
public enum YogaLayoutType {
LAYOUT(0),
MEASURE(1),
CACHED_LAYOUT(2),
CACHED_MEASURE(3);
private final int mIntValue;
YogaLayoutType(int intValue) {
mIntValue = intValue;
}
public int intValue() {
return mIntValue;
}
public static YogaLayoutType fromInt(int value) {
switch (value) {
case 0: return LAYOUT;
case 1: return MEASURE;
case 2: return CACHED_LAYOUT;
case 3: return CACHED_MEASURE;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
}
}
}

View File

@@ -28,9 +28,8 @@ public class YogaNative {
// YGNode related
static native int jni_YGNodeGetInstanceCount();
static native long jni_YGNodeNew(boolean useBatchingForLayoutOutputs);
static native long jni_YGNodeNewWithConfig(long configPointer, boolean useBatchingForLayoutOutputs);
static native long jni_YGNodeNew();
static native long jni_YGNodeNewWithConfig(long configPointer);
static native void jni_YGNodeFree(long nativePointer);
static native void jni_YGNodeReset(long nativePointer);
static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index);

View File

@@ -10,11 +10,11 @@ import javax.annotation.Nullable;
public abstract class YogaNode {
public static YogaNode create() {
return YogaConfig.useBatchingForLayoutOutputs ? new YogaNodeJNIBatching() : new YogaNodeJNI();
return new YogaNodeJNIFinalizer();
}
public static YogaNode create(YogaConfig config) {
return YogaConfig.useBatchingForLayoutOutputs ? new YogaNodeJNIBatching(config) : new YogaNodeJNI(config);
return new YogaNodeJNIFinalizer(config);
}
public abstract void reset();

View File

@@ -0,0 +1,11 @@
package com.facebook.yoga;
public abstract class YogaNodeFactory {
public static YogaNode create() {
return new YogaNodeJNIFinalizer();
}
public static YogaNode create(YogaConfig config) {
return new YogaNodeJNIFinalizer(config);
}
}

View File

@@ -1,186 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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;
@DoNotStrip
public class YogaNodeJNI extends YogaNodeJNIBase {
@DoNotStrip
private float mWidth = YogaConstants.UNDEFINED;
@DoNotStrip
private float mHeight = YogaConstants.UNDEFINED;
@DoNotStrip
private float mTop = YogaConstants.UNDEFINED;
@DoNotStrip
private float mLeft = YogaConstants.UNDEFINED;
@DoNotStrip
private float mMarginLeft = 0;
@DoNotStrip
private float mMarginTop = 0;
@DoNotStrip
private float mMarginRight = 0;
@DoNotStrip
private float mMarginBottom = 0;
@DoNotStrip
private float mPaddingLeft = 0;
@DoNotStrip
private float mPaddingTop = 0;
@DoNotStrip
private float mPaddingRight = 0;
@DoNotStrip
private float mPaddingBottom = 0;
@DoNotStrip
private float mBorderLeft = 0;
@DoNotStrip
private float mBorderTop = 0;
@DoNotStrip
private float mBorderRight = 0;
@DoNotStrip
private float mBorderBottom = 0;
@DoNotStrip
private int mLayoutDirection = 0;
@DoNotStrip
private boolean mHasNewLayout = true;
@DoNotStrip
private boolean mDoesLegacyStretchFlagAffectsLayout = false;
public YogaNodeJNI() {
super();
}
public YogaNodeJNI(YogaConfig config) {
super(config);
}
@Override
public void reset() {
super.reset();
mHasNewLayout = true;
mWidth = YogaConstants.UNDEFINED;
mHeight = YogaConstants.UNDEFINED;
mTop = YogaConstants.UNDEFINED;
mLeft = YogaConstants.UNDEFINED;
mMarginLeft = 0;
mMarginTop = 0;
mMarginRight = 0;
mMarginBottom = 0;
mPaddingLeft = 0;
mPaddingTop = 0;
mPaddingRight = 0;
mPaddingBottom = 0;
mBorderLeft = 0;
mBorderTop = 0;
mBorderRight = 0;
mBorderBottom = 0;
mLayoutDirection = 0;
mDoesLegacyStretchFlagAffectsLayout = false;
}
@Override
public boolean hasNewLayout() {
return mHasNewLayout;
}
@Override
public void markLayoutSeen() {
mHasNewLayout = false;
}
@Override
public float getLayoutX() {
return mLeft;
}
@Override
public float getLayoutY() {
return mTop;
}
@Override
public float getLayoutWidth() {
return mWidth;
}
@Override
public float getLayoutHeight() {
return mHeight;
}
@Override
public boolean getDoesLegacyStretchFlagAffectsLayout() {
return mDoesLegacyStretchFlagAffectsLayout;
}
@Override
public float getLayoutMargin(YogaEdge edge) {
switch (edge) {
case LEFT:
return mMarginLeft;
case TOP:
return mMarginTop;
case RIGHT:
return mMarginRight;
case BOTTOM:
return mMarginBottom;
case START:
return getLayoutDirection() == YogaDirection.RTL ? mMarginRight : mMarginLeft;
case END:
return getLayoutDirection() == YogaDirection.RTL ? mMarginLeft : mMarginRight;
default:
throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands");
}
}
@Override
public float getLayoutPadding(YogaEdge edge) {
switch (edge) {
case LEFT:
return mPaddingLeft;
case TOP:
return mPaddingTop;
case RIGHT:
return mPaddingRight;
case BOTTOM:
return mPaddingBottom;
case START:
return getLayoutDirection() == YogaDirection.RTL ? mPaddingRight : mPaddingLeft;
case END:
return getLayoutDirection() == YogaDirection.RTL ? mPaddingLeft : mPaddingRight;
default:
throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands");
}
}
@Override
public float getLayoutBorder(YogaEdge edge) {
switch (edge) {
case LEFT:
return mBorderLeft;
case TOP:
return mBorderTop;
case RIGHT:
return mBorderRight;
case BOTTOM:
return mBorderBottom;
case START:
return getLayoutDirection() == YogaDirection.RTL ? mBorderRight : mBorderLeft;
case END:
return getLayoutDirection() == YogaDirection.RTL ? mBorderLeft : mBorderRight;
default:
throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands");
}
}
@Override
public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(mLayoutDirection);
}
}

View File

@@ -14,48 +14,60 @@ import javax.annotation.Nullable;
@DoNotStrip
public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
/* Those flags needs be in sync with YGJNI.cpp */
private static final byte MARGIN = 1;
private static final byte PADDING = 2;
private static final byte BORDER = 4;
private static final byte DOES_LEGACY_STRETCH_BEHAVIOUR = 8;
private static final byte HAS_NEW_LAYOUT = 16;
private static final byte LAYOUT_EDGE_SET_FLAG_INDEX = 0;
private static final byte LAYOUT_WIDTH_INDEX = 1;
private static final byte LAYOUT_HEIGHT_INDEX = 2;
private static final byte LAYOUT_LEFT_INDEX = 3;
private static final byte LAYOUT_TOP_INDEX = 4;
private static final byte LAYOUT_DIRECTION_INDEX = 5;
private static final byte LAYOUT_MARGIN_START_INDEX = 6;
private static final byte LAYOUT_PADDING_START_INDEX = 10;
private static final byte LAYOUT_BORDER_START_INDEX = 14;
@Nullable private YogaNodeJNIBase mOwner;
@Nullable private List<YogaNodeJNIBase> mChildren;
@Nullable private YogaMeasureFunction mMeasureFunction;
@Nullable private YogaBaselineFunction mBaselineFunction;
private long mNativePointer;
protected long mNativePointer;
@Nullable private Object mData;
public YogaNodeJNIBase() {
mNativePointer = YogaNative.jni_YGNodeNew(YogaConfig.useBatchingForLayoutOutputs);
if (mNativePointer == 0) {
@DoNotStrip
private @Nullable float[] arr = null;
@DoNotStrip
private int mLayoutDirection = 0;
private boolean mHasNewLayout = true;
private YogaNodeJNIBase(long nativePointer) {
if (nativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory");
}
mNativePointer = nativePointer;
}
public YogaNodeJNIBase(YogaConfig config) {
mNativePointer = YogaNative.jni_YGNodeNewWithConfig(config.mNativePointer, YogaConfig.useBatchingForLayoutOutputs);
if (mNativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory");
}
YogaNodeJNIBase() {
this(YogaNative.jni_YGNodeNew());
}
@Override
protected void finalize() throws Throwable {
try {
freeNatives();
} finally {
super.finalize();
}
YogaNodeJNIBase(YogaConfig config) {
this(YogaNative.jni_YGNodeNewWithConfig(config.mNativePointer));
}
/* frees the native underlying YGNode. Useful for testing. */
public void freeNatives() {
if (mNativePointer > 0) {
long nativePointer = mNativePointer;
mNativePointer = 0;
YogaNative.jni_YGNodeFree(nativePointer);
}
}
public void reset() {
mMeasureFunction = null;
mBaselineFunction = null;
mData = null;
arr = null;
mHasNewLayout = true;
mLayoutDirection = 0;
YogaNative.jni_YGNodeReset(mNativePointer);
}
@@ -443,8 +455,6 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio);
}
public abstract boolean getDoesLegacyStretchFlagAffectsLayout();
public void setMeasureFunction(YogaMeasureFunction measureFunction) {
mMeasureFunction = measureFunction;
YogaNative.jni_YGNodeSetHasMeasureFunc(mNativePointer, measureFunction != null);
@@ -530,4 +540,124 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
private static YogaValue valueFromLong(long raw) {
return new YogaValue(Float.intBitsToFloat((int) raw), (int) (raw >> 32));
}
@Override
public float getLayoutX() {
return arr != null ? arr[LAYOUT_LEFT_INDEX] : 0;
}
@Override
public float getLayoutY() {
return arr != null ? arr[LAYOUT_TOP_INDEX] : 0;
}
@Override
public float getLayoutWidth() {
return arr != null ? arr[LAYOUT_WIDTH_INDEX] : 0;
}
@Override
public float getLayoutHeight() {
return arr != null ? arr[LAYOUT_HEIGHT_INDEX] : 0;
}
public boolean getDoesLegacyStretchFlagAffectsLayout() {
return arr != null && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) == DOES_LEGACY_STRETCH_BEHAVIOUR);
}
@Override
public float getLayoutMargin(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) {
switch (edge) {
case LEFT:
return arr[LAYOUT_MARGIN_START_INDEX];
case TOP:
return arr[LAYOUT_MARGIN_START_INDEX + 1];
case RIGHT:
return arr[LAYOUT_MARGIN_START_INDEX + 2];
case BOTTOM:
return arr[LAYOUT_MARGIN_START_INDEX + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX + 2] : arr[LAYOUT_MARGIN_START_INDEX];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX] : arr[LAYOUT_MARGIN_START_INDEX + 2];
default:
throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public float getLayoutPadding(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) {
int paddingStartIndex = LAYOUT_PADDING_START_INDEX - ((((int)arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4);
switch (edge) {
case LEFT:
return arr[paddingStartIndex];
case TOP:
return arr[paddingStartIndex + 1];
case RIGHT:
return arr[paddingStartIndex + 2];
case BOTTOM:
return arr[paddingStartIndex + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex + 2] : arr[paddingStartIndex];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex] : arr[paddingStartIndex + 2];
default:
throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public float getLayoutBorder(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4);
switch (edge) {
case LEFT:
return arr[borderStartIndex];
case TOP:
return arr[borderStartIndex + 1];
case RIGHT:
return arr[borderStartIndex + 2];
case BOTTOM:
return arr[borderStartIndex + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex + 2] : arr[borderStartIndex];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex] : arr[borderStartIndex + 2];
default:
throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection);
}
@Override
public boolean hasNewLayout() {
if (arr != null) {
return (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & HAS_NEW_LAYOUT) == HAS_NEW_LAYOUT;
} else {
return mHasNewLayout;
}
}
@Override
public void markLayoutSeen() {
if (arr != null) {
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & ~(HAS_NEW_LAYOUT);
}
mHasNewLayout = false;
}
}

View File

@@ -1,177 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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 javax.annotation.Nullable;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public class YogaNodeJNIBatching extends YogaNodeJNIBase {
/* Those flags needs be in sync with YGJNI.cpp */
private static final byte MARGIN = 1;
private static final byte PADDING = 2;
private static final byte BORDER = 4;
private static final byte DOES_LEGACY_STRETCH_BEHAVIOUR = 8;
private static final byte HAS_NEW_LAYOUT = 16;
private static final byte LAYOUT_EDGE_SET_FLAG_INDEX = 0;
private static final byte LAYOUT_WIDTH_INDEX = 1;
private static final byte LAYOUT_HEIGHT_INDEX = 2;
private static final byte LAYOUT_LEFT_INDEX = 3;
private static final byte LAYOUT_TOP_INDEX = 4;
private static final byte LAYOUT_DIRECTION_INDEX = 5;
private static final byte LAYOUT_MARGIN_START_INDEX = 6;
private static final byte LAYOUT_PADDING_START_INDEX = 10;
private static final byte LAYOUT_BORDER_START_INDEX = 14;
@DoNotStrip
private @Nullable float[] arr = null;
@DoNotStrip
private int mLayoutDirection = 0;
private boolean mHasNewLayout = true;
public YogaNodeJNIBatching() {
super();
}
public YogaNodeJNIBatching(YogaConfig config) {
super(config);
}
@Override
public void reset() {
super.reset();
arr = null;
mHasNewLayout = true;
mLayoutDirection = 0;
}
@Override
public float getLayoutX() {
return arr != null ? arr[LAYOUT_LEFT_INDEX] : 0;
}
@Override
public float getLayoutY() {
return arr != null ? arr[LAYOUT_TOP_INDEX] : 0;
}
@Override
public float getLayoutWidth() {
return arr != null ? arr[LAYOUT_WIDTH_INDEX] : 0;
}
@Override
public float getLayoutHeight() {
return arr != null ? arr[LAYOUT_HEIGHT_INDEX] : 0;
}
@Override
public boolean getDoesLegacyStretchFlagAffectsLayout() {
return arr != null && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) == DOES_LEGACY_STRETCH_BEHAVIOUR);
}
@Override
public float getLayoutMargin(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) {
switch (edge) {
case LEFT:
return arr[LAYOUT_MARGIN_START_INDEX];
case TOP:
return arr[LAYOUT_MARGIN_START_INDEX + 1];
case RIGHT:
return arr[LAYOUT_MARGIN_START_INDEX + 2];
case BOTTOM:
return arr[LAYOUT_MARGIN_START_INDEX + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX + 2] : arr[LAYOUT_MARGIN_START_INDEX];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX] : arr[LAYOUT_MARGIN_START_INDEX + 2];
default:
throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public float getLayoutPadding(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) {
int paddingStartIndex = LAYOUT_PADDING_START_INDEX - ((((int)arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4);
switch (edge) {
case LEFT:
return arr[paddingStartIndex];
case TOP:
return arr[paddingStartIndex + 1];
case RIGHT:
return arr[paddingStartIndex + 2];
case BOTTOM:
return arr[paddingStartIndex + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex + 2] : arr[paddingStartIndex];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex] : arr[paddingStartIndex + 2];
default:
throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public float getLayoutBorder(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4);
switch (edge) {
case LEFT:
return arr[borderStartIndex];
case TOP:
return arr[borderStartIndex + 1];
case RIGHT:
return arr[borderStartIndex + 2];
case BOTTOM:
return arr[borderStartIndex + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex + 2] : arr[borderStartIndex];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex] : arr[borderStartIndex + 2];
default:
throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection);
}
@Override
public boolean hasNewLayout() {
if (arr != null) {
return (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & HAS_NEW_LAYOUT) == HAS_NEW_LAYOUT;
} else {
return mHasNewLayout;
}
}
@Override
public void markLayoutSeen() {
if (arr != null) {
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & ~(HAS_NEW_LAYOUT);
}
mHasNewLayout = false;
}
}

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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;
public class YogaNodeJNIFinalizer extends YogaNodeJNIBase {
public YogaNodeJNIFinalizer() {
super();
}
public YogaNodeJNIFinalizer(YogaConfig config) {
super(config);
}
@Override
protected void finalize() throws Throwable {
try {
freeNatives();
} finally {
super.finalize();
}
}
public void freeNatives() {
if (mNativePointer != 0) {
long nativePointer = mNativePointer;
mNativePointer = 0;
YogaNative.jni_YGNodeFree(nativePointer);
}
}
}

View File

@@ -1,10 +1,10 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#include <fb/fbjni.h>
#include <fbjni/fbjni.h>
#include <yoga/YGNode.h>
#include <yoga/Yoga.h>
#include <yoga/Yoga-internal.h>
@@ -73,36 +73,6 @@ const short int LAYOUT_MARGIN_START_INDEX = 6;
const short int LAYOUT_PADDING_START_INDEX = 10;
const short int LAYOUT_BORDER_START_INDEX = 14;
bool useBatchingForLayoutOutputs;
class PtrJNodeMap {
using JNodeArray = JArrayClass<JYogaNode::javaobject>;
std::map<YGNodeRef, size_t> ptrsToIdxs_;
alias_ref<JNodeArray> javaNodes_;
public:
PtrJNodeMap() : ptrsToIdxs_{}, javaNodes_{} {}
PtrJNodeMap(
alias_ref<JArrayLong> nativePointers,
alias_ref<JNodeArray> javaNodes)
: javaNodes_{javaNodes} {
auto pin = nativePointers->pinCritical();
auto ptrs = pin.get();
for (size_t i = 0, n = pin.size(); i < n; ++i) {
ptrsToIdxs_[(YGNodeRef) ptrs[i]] = i;
}
}
local_ref<JYogaNode> ref(YGNodeRef node) {
auto idx = ptrsToIdxs_.find(node);
if (idx == ptrsToIdxs_.end()) {
return local_ref<JYogaNode>{};
} else {
return javaNodes_->getElement(idx->second);
}
}
};
namespace {
union YGNodeContext {
@@ -135,18 +105,14 @@ public:
node->setContext(context.asVoidPtr);
}
bool has(Edge edge) {
return (edges_ & edge) == edge;
}
bool has(Edge edge) { return (edges_ & edge) == edge; }
YGNodeEdges& add(Edge edge) {
edges_ |= edge;
return *this;
}
int get() {
return edges_;
}
int get() { return edges_; }
};
struct YogaValue {
@@ -197,142 +163,57 @@ static void YGTransferLayoutOutputsRecursive(
auto edgesSet = YGNodeEdges{root};
if (useBatchingForLayoutOutputs) {
bool marginFieldSet = edgesSet.has(YGNodeEdges::MARGIN);
bool paddingFieldSet = edgesSet.has(YGNodeEdges::PADDING);
bool borderFieldSet = edgesSet.has(YGNodeEdges::BORDER);
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;
if (YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)) {
fieldFlags |= DOES_LEGACY_STRETCH_BEHAVIOUR;
}
const int arrSize = 6 + (marginFieldSet ? 4 : 0) +
(paddingFieldSet ? 4 : 0) + (borderFieldSet ? 4 : 0);
float arr[18];
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = fieldFlags;
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] =
static_cast<jint>(YGNodeLayoutGetDirection(root));
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);
}
static auto arrField = obj->getClass()->getField<jfloatArray>("arr");
local_ref<jfloatArray> arrFinal = make_float_array(arrSize);
arrFinal->setRegion(0, arrSize, arr);
obj->setFieldValue<jfloatArray>(arrField, arrFinal.get());
} else {
static auto widthField = obj->getClass()->getField<jfloat>("mWidth");
static auto heightField = obj->getClass()->getField<jfloat>("mHeight");
static auto leftField = obj->getClass()->getField<jfloat>("mLeft");
static auto topField = obj->getClass()->getField<jfloat>("mTop");
static auto marginLeftField =
obj->getClass()->getField<jfloat>("mMarginLeft");
static auto marginTopField =
obj->getClass()->getField<jfloat>("mMarginTop");
static auto marginRightField =
obj->getClass()->getField<jfloat>("mMarginRight");
static auto marginBottomField =
obj->getClass()->getField<jfloat>("mMarginBottom");
static auto paddingLeftField =
obj->getClass()->getField<jfloat>("mPaddingLeft");
static auto paddingTopField =
obj->getClass()->getField<jfloat>("mPaddingTop");
static auto paddingRightField =
obj->getClass()->getField<jfloat>("mPaddingRight");
static auto paddingBottomField =
obj->getClass()->getField<jfloat>("mPaddingBottom");
static auto borderLeftField =
obj->getClass()->getField<jfloat>("mBorderLeft");
static auto borderTopField =
obj->getClass()->getField<jfloat>("mBorderTop");
static auto borderRightField =
obj->getClass()->getField<jfloat>("mBorderRight");
static auto borderBottomField =
obj->getClass()->getField<jfloat>("mBorderBottom");
static auto hasNewLayoutField =
obj->getClass()->getField<jboolean>("mHasNewLayout");
static auto doesLegacyStretchBehaviour =
obj->getClass()->getField<jboolean>(
"mDoesLegacyStretchFlagAffectsLayout");
obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root));
obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root));
obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root));
obj->setFieldValue(topField, YGNodeLayoutGetTop(root));
obj->setFieldValue<jboolean>(
doesLegacyStretchBehaviour,
YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root));
obj->setFieldValue<jboolean>(hasNewLayoutField, true);
YGTransferLayoutDirection(root, obj);
if (edgesSet.has(YGNodeEdges::MARGIN)) {
obj->setFieldValue(
marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft));
obj->setFieldValue(
marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop));
obj->setFieldValue(
marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight));
obj->setFieldValue(
marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom));
}
if (edgesSet.has(YGNodeEdges::PADDING)) {
obj->setFieldValue(
paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft));
obj->setFieldValue(
paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop));
obj->setFieldValue(
paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight));
obj->setFieldValue(
paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom));
}
if (edgesSet.has(YGNodeEdges::BORDER)) {
obj->setFieldValue(
borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft));
obj->setFieldValue(
borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop));
obj->setFieldValue(
borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight));
obj->setFieldValue(
borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom));
}
int fieldFlags = edgesSet.get();
fieldFlags |= HAS_NEW_LAYOUT;
if (YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)) {
fieldFlags |= DOES_LEGACY_STRETCH_BEHAVIOUR;
}
const int arrSize = 6 + (marginFieldSet ? 4 : 0) + (paddingFieldSet ? 4 : 0) +
(borderFieldSet ? 4 : 0);
float arr[18];
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = fieldFlags;
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] =
static_cast<jint>(YGNodeLayoutGetDirection(root));
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);
}
static auto arrField = obj->getClass()->getField<jfloatArray>("arr");
local_ref<jfloatArray> arrFinal = make_float_array(arrSize);
arrFinal->setRegion(0, arrSize, arr);
obj->setFieldValue<jfloatArray>(arrField, arrFinal.get());
root->setHasNewLayout(false);
for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) {
@@ -442,21 +323,16 @@ static int YGJNILogFunc(
return result;
}
jlong jni_YGNodeNew(alias_ref<jobject> thiz, jboolean useBatching) {
jlong jni_YGNodeNew(alias_ref<jobject> thiz) {
const YGNodeRef node = YGNodeNew();
node->setContext(YGNodeContext{}.asVoidPtr);
node->setPrintFunc(YGPrint);
useBatchingForLayoutOutputs = useBatching;
return reinterpret_cast<jlong>(node);
}
jlong jni_YGNodeNewWithConfig(
alias_ref<jclass>,
jlong configPointer,
jboolean useBatching) {
jlong jni_YGNodeNewWithConfig(alias_ref<jclass>, jlong configPointer) {
const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer));
node->setContext(YGNodeContext{}.asVoidPtr);
useBatchingForLayoutOutputs = useBatching;
return reinterpret_cast<jlong>(node);
}
@@ -942,10 +818,6 @@ void jni_YGNodeSetStyleInputs(
YGNodeSetStyleInputs(_jlong2YGNodeRef(nativePointer), result, size);
}
jint jni_YGNodeGetInstanceCount() {
return YGNodeGetInstanceCount();
}
jlong jni_YGNodeStyleGetMargin(jlong nativePointer, jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) {
@@ -1109,7 +981,6 @@ jint JNI_OnLoad(JavaVM* vm, void*) {
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeightPercent),
YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAspectRatio),
YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAspectRatio),
YGMakeCriticalNativeMethod(jni_YGNodeGetInstanceCount),
YGMakeCriticalNativeMethod(jni_YGNodePrint),
YGMakeNativeMethod(jni_YGNodeClone),
YGMakeNativeMethod(jni_YGNodeSetStyleInputs),

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,11 +1,16 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#include <fb/fbjni.h>
#include <fbjni/fbjni.h>
#include <yoga/YGValue.h>
#include <yoga/Yoga.h>
#include <map>
using namespace facebook::jni;
using namespace std;
struct JYogaNode : public facebook::jni::JavaClass<JYogaNode> {
static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaNodeJNIBase;";
@@ -28,3 +33,31 @@ struct JYogaLogger : public facebook::jni::JavaClass<JYogaLogger> {
facebook::jni::alias_ref<JYogaLogLevel>,
jstring);
};
class PtrJNodeMap {
using JNodeArray = JArrayClass<JYogaNode::javaobject>;
std::map<YGNodeRef, size_t> ptrsToIdxs_;
alias_ref<JNodeArray> javaNodes_;
public:
PtrJNodeMap() : ptrsToIdxs_{}, javaNodes_{} {}
PtrJNodeMap(
alias_ref<JArrayLong> nativePointers,
alias_ref<JNodeArray> javaNodes)
: javaNodes_{javaNodes} {
auto pin = nativePointers->pinCritical();
auto ptrs = pin.get();
for (size_t i = 0, n = pin.size(); i < n; ++i) {
ptrsToIdxs_[(YGNodeRef) ptrs[i]] = i;
}
}
local_ref<JYogaNode> ref(YGNodeRef node) {
auto idx = ptrsToIdxs_.find(node);
if (idx == ptrsToIdxs_.end()) {
return local_ref<JYogaNode>{};
} else {
return javaNodes_->getElement(idx->second);
}
}
};

View File

@@ -6,3 +6,8 @@
*/
apply plugin: 'java'
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
apply from: rootProject.file('gradle/release.gradle')

View File

@@ -0,0 +1,12 @@
#
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the LICENSE
# file in the root directory of this source tree.
#
GROUP=com.facebook.yoga
POM_NAME=Proguard Annotations
POM_DESCRIPTION=Shared annotations for use with Proguard
POM_ARTIFACT_ID=proguard-annotations
POM_PACKAGING=jar

View File

@@ -3,13 +3,13 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library")
load("//tools/build_defs/oss:yoga_defs.bzl", "yoga_java_library")
yoga_java_library(
name = "annotations",
srcs = glob(["*.java"]),
source = "1.7",
target = "1.7",
visibility = YOGA_ROOTS,
visibility = ["PUBLIC"],
deps = [],
)

View File

@@ -31,9 +31,9 @@ public class YogaNodeTest {
@Test
public void testInit() {
final int refCount = YogaNative.jni_YGNodeGetInstanceCount();
TestUtil.startCountingNodes();
final YogaNode node = createNode();
assertEquals(refCount + 1, YogaNative.jni_YGNodeGetInstanceCount());
assertEquals(1, TestUtil.stopCountingNodes());
}
@Test
@@ -254,7 +254,7 @@ public class YogaNodeTest {
root_child0_child0_child0.setFlexShrink(1);
root_child0_child0.addChildAt(root_child0_child0_child0, 0);
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
assertFalse(((YogaNodeJNIBase) root).getDoesLegacyStretchFlagAffectsLayout());
assertTrue(((YogaNodeJNIBase) root).getDoesLegacyStretchFlagAffectsLayout());
}
@Test

View File

@@ -7,9 +7,9 @@
"sources": [
"<!@(ls -1 sources/yoga/*.cpp)",
"<!@(ls -1 sources/yoga/*/*.cpp)",
"sources/Config.cc",
"sources/Node.cc",
"sources/global.cc",
"sources/nbind.cc"
],

View File

@@ -43,7 +43,7 @@
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^4.0.0",
"flow-copy-source": "^1.2.1",
"flow-copy-source": "^2.0.7",
"mocha": "^3.2.0"
}
}

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE

View File

@@ -350,9 +350,6 @@ module.exports = (bind: any, lib: any): Yoga => {
Layout: bind('Layout', Layout),
Size: bind('Size', Size),
Value: bind('Value', Value),
getInstanceCount(...args) {
return lib.getInstanceCount(...args);
},
...CONSTANTS,
};
};

View File

@@ -1,9 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
unsigned getInstanceCount(void);

View File

@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
@@ -11,14 +11,9 @@
#include "./Size.hh"
#include "./Value.hh"
#include "./Config.hh"
#include "./global.hh"
#include <nbind/nbind.h>
NBIND_GLOBAL() {
function(getInstanceCount);
}
NBIND_CLASS(Size) {
construct<>();
construct<double, double>();

View File

@@ -27,5 +27,5 @@ it("border_start", function () {
root.freeRecursive();
(typeof gc !== "undefined") && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});

View File

@@ -27,5 +27,5 @@ it("margin_start", function () {
root.freeRecursive();
(typeof gc !== "undefined") && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});

View File

@@ -27,5 +27,5 @@ it("padding_start", function () {
root.freeRecursive();
(typeof gc !== "undefined") && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});

View File

@@ -34,7 +34,7 @@ it("dirtied", function() {
root.freeRecursive();
typeof gc !== "undefined" && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});
it("dirtied_propagation", function() {
@@ -75,7 +75,7 @@ it("dirtied_propagation", function() {
root.freeRecursive();
typeof gc !== "undefined" && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});
it("dirtied_hierarchy", function() {
@@ -122,7 +122,7 @@ it("dirtied_hierarchy", function() {
root.freeRecursive();
typeof gc !== "undefined" && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});
it("dirtied_reset", function() {
@@ -164,5 +164,5 @@ it("dirtied_reset", function() {
root.freeRecursive();
typeof gc !== "undefined" && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});

View File

@@ -29,5 +29,5 @@ it("measure_once_single_flexible_child", function () {
root.freeRecursive();
(typeof gc !== "undefined") && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});

View File

@@ -27,5 +27,5 @@ it("dont_measure_single_grow_shrink_child", function () {
root.freeRecursive();
(typeof gc !== "undefined") && gc();
console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")");
// TODO Add event support in js and check instace allocation and de allocation using that
});

View File

@@ -10,14 +10,22 @@ ansi-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107"
ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
ansi-regex@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
ansi-styles@^3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
anymatch@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@@ -25,6 +33,14 @@ anymatch@^1.3.0:
arrify "^1.0.0"
micromatch "^2.1.5"
anymatch@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.0.3.tgz#2fb624fe0e84bccab00afee3d0006ed310f22f09"
integrity sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
aproba@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0"
@@ -687,6 +703,11 @@ binary-extensions@^1.0.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
binary-extensions@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
block-stream@*:
version "0.0.9"
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
@@ -718,6 +739,13 @@ braces@^1.8.2:
preserve "^0.2.0"
repeat-element "^1.1.2"
braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
browser-stdout@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
@@ -726,13 +754,10 @@ buffer-shims@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
camelcase@^5.0.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
caseless@~0.11.0:
version "0.11.0"
@@ -763,33 +788,46 @@ chokidar@^1.6.1:
optionalDependencies:
fsevents "^1.0.0"
chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
chokidar@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.0.2.tgz#0d1cd6d04eb2df0327446188cd13736a3367d681"
integrity sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==
dependencies:
anymatch "^1.3.0"
async-each "^1.0.0"
glob-parent "^2.0.0"
inherits "^2.0.1"
is-binary-path "^1.0.0"
is-glob "^2.0.0"
path-is-absolute "^1.0.0"
readdirp "^2.0.0"
anymatch "^3.0.1"
braces "^3.0.2"
glob-parent "^5.0.0"
is-binary-path "^2.1.0"
is-glob "^4.0.1"
normalize-path "^3.0.0"
readdirp "^3.1.1"
optionalDependencies:
fsevents "^1.0.0"
fsevents "^2.0.6"
cliui@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi "^2.0.0"
string-width "^3.1.0"
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
color-name "1.1.3"
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
@@ -829,7 +867,7 @@ cross-env@^4.0.0:
cross-spawn "^5.1.0"
is-windows "^1.0.0"
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
cross-spawn@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
dependencies:
@@ -861,9 +899,10 @@ debug@^2.6.8:
dependencies:
ms "2.0.0"
decamelize@^1.1.1:
decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
deep-extend@~0.4.0:
version "0.4.1"
@@ -893,16 +932,15 @@ ecc-jsbn@~0.1.1:
dependencies:
jsbn "~0.1.0"
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
emscripten-library-decorator@~0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/emscripten-library-decorator/-/emscripten-library-decorator-0.2.2.tgz#d035f023e2a84c68305cc842cdeea38e67683c40"
error-ex@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
dependencies:
is-arrayish "^0.2.1"
escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
@@ -911,18 +949,6 @@ esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
dependencies:
cross-spawn "^5.0.1"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
expand-brackets@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -963,21 +989,30 @@ fill-range@^2.1.0:
repeat-element "^1.1.2"
repeat-string "^1.5.2"
find-up@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
locate-path "^2.0.0"
to-regex-range "^5.0.1"
flow-copy-source@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/flow-copy-source/-/flow-copy-source-1.2.1.tgz#705c2fa8fb29a281118e1c4b66218dec24b745ec"
find-up@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
dependencies:
chokidar "^1.7.0"
fs-extra "^3.0.1"
locate-path "^3.0.0"
flow-copy-source@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/flow-copy-source/-/flow-copy-source-2.0.7.tgz#3b5634ac552c539a40093ed09d9e645e67f95212"
integrity sha512-/9oYivwSRgIyRMWqRkzJgulUCRPqMA8JSt7l0uoW0Xmtp8ItJpURnBczJUvnAKnHp0TNttNILCeuqW2w9cwTFg==
dependencies:
chokidar "^3.0.0"
fs-extra "^8.1.0"
glob "^7.0.0"
kefir "^3.7.3"
yargs "^8.0.2"
yargs "^13.1.0"
for-in@^0.1.5:
version "0.1.6"
@@ -1001,12 +1036,13 @@ form-data@~2.1.1:
combined-stream "^1.0.5"
mime-types "^2.1.12"
fs-extra@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291"
fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
dependencies:
graceful-fs "^4.1.2"
jsonfile "^3.0.0"
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-readdir-recursive@^1.0.0:
@@ -1024,6 +1060,11 @@ fsevents@^1.0.0:
nan "^2.3.0"
node-pre-gyp "^0.6.29"
fsevents@^2.0.6:
version "2.0.7"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a"
integrity sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==
fstream-ignore@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
@@ -1078,13 +1119,10 @@ generate-object-property@^1.1.0:
dependencies:
is-property "^1.0.0"
get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
getpass@^0.1.1:
version "0.1.6"
@@ -1105,6 +1143,13 @@ glob-parent@^2.0.0:
dependencies:
is-glob "^2.0.0"
glob-parent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954"
integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
dependencies:
is-glob "^4.0.1"
glob@7.0.5:
version "7.0.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95"
@@ -1135,6 +1180,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
graceful-fs@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b"
integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==
"graceful-readlink@>= 1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
@@ -1186,10 +1236,6 @@ home-or-tmp@^2.0.0:
os-homedir "^1.0.0"
os-tmpdir "^1.0.1"
hosted-git-info@^2.1.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
http-signature@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
@@ -1219,30 +1265,23 @@ invariant@^2.2.0, invariant@^2.2.2:
dependencies:
loose-envify "^1.0.0"
invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
is-binary-path@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
dependencies:
binary-extensions "^1.0.0"
is-binary-path@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-buffer@^1.0.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b"
is-builtin-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
dependencies:
builtin-modules "^1.0.0"
is-dotfile@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d"
@@ -1261,6 +1300,11 @@ is-extglob@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-finite@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
@@ -1283,6 +1327,13 @@ is-glob@^2.0.0, is-glob@^2.0.1:
dependencies:
is-extglob "^1.0.0"
is-glob@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
dependencies:
is-extglob "^2.1.1"
is-my-json-valid@^2.12.4:
version "2.15.0"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"
@@ -1298,6 +1349,11 @@ is-number@^2.0.2, is-number@^2.1.0:
dependencies:
kind-of "^3.0.2"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-posix-bracket@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
@@ -1310,10 +1366,6 @@ is-property@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@@ -1382,9 +1434,10 @@ json5@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
jsonfile@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
optionalDependencies:
graceful-fs "^4.1.6"
@@ -1412,26 +1465,12 @@ kind-of@^3.0.2:
dependencies:
is-buffer "^1.0.2"
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
dependencies:
invert-kv "^1.0.0"
load-json-file@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
dependencies:
graceful-fs "^4.1.2"
parse-json "^2.2.0"
pify "^2.0.0"
strip-bom "^3.0.0"
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
dependencies:
p-locate "^2.0.0"
p-locate "^3.0.0"
path-exists "^3.0.0"
lodash._baseassign@^3.0.0:
@@ -1502,12 +1541,6 @@ lru-cache@^4.0.1:
pseudomap "^1.0.2"
yallist "^2.1.2"
mem@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
dependencies:
mimic-fn "^1.0.0"
micromatch@^2.1.5:
version "2.3.11"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
@@ -1536,10 +1569,6 @@ mime-types@^2.1.12, mime-types@~2.1.7:
dependencies:
mime-db "~1.25.0"
mimic-fn@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
minimatch@^3.0.0, minimatch@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
@@ -1638,24 +1667,14 @@ node-pre-gyp@^0.6.29:
dependencies:
abbrev "1"
normalize-package-data@^2.3.2:
version "2.4.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
dependencies:
hosted-git-info "^2.1.4"
is-builtin-module "^1.0.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
normalize-path@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
dependencies:
path-key "^2.0.0"
normalize-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
"npmlog@0 || 1 || 2 || 3 || 4":
version "4.1.2"
@@ -1710,14 +1729,6 @@ os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
os-locale@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
dependencies:
execa "^0.7.0"
lcid "^1.0.0"
mem "^1.1.0"
os-tmpdir@^1.0.0, os-tmpdir@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
@@ -1737,25 +1748,24 @@ output-file-sync@^1.1.0:
mkdirp "^0.5.1"
object-assign "^4.1.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
p-limit@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2"
integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==
dependencies:
p-try "^1.0.0"
p-try "^2.0.0"
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
dependencies:
p-limit "^1.1.0"
p-limit "^2.0.0"
p-try@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
p-try@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
parse-glob@^3.0.4:
version "3.0.4"
@@ -1766,12 +1776,6 @@ parse-glob@^3.0.4:
is-extglob "^1.0.0"
is-glob "^2.0.0"
parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
dependencies:
error-ex "^1.2.0"
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -1780,19 +1784,10 @@ path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
path-key@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
path-type@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
dependencies:
pify "^2.0.0"
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
picomatch@^2.0.4:
version "2.0.7"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
pinkie-promise@^2.0.0:
version "2.0.1"
@@ -1844,21 +1839,6 @@ rc@~1.1.6:
minimist "^1.2.0"
strip-json-comments "~1.0.4"
read-pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
dependencies:
find-up "^2.0.0"
read-pkg "^2.0.0"
read-pkg@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
dependencies:
load-json-file "^2.0.0"
normalize-package-data "^2.3.2"
path-type "^2.0.0"
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
@@ -1892,6 +1872,13 @@ readdirp@^2.0.0:
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
readdirp@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.1.1.tgz#b158123ac343c8b0f31d65680269cc0fc1025db1"
integrity sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==
dependencies:
picomatch "^2.0.4"
regenerate@^1.2.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f"
@@ -1980,9 +1967,10 @@ require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
require-main-filename@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
resolve@~1.1.7:
version "1.1.7"
@@ -1994,10 +1982,6 @@ rimraf@2, rimraf@~2.5.1, rimraf@~2.5.4:
dependencies:
glob "^7.0.5"
"semver@2 || 3 || 4 || 5":
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
semver@~5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
@@ -2044,20 +2028,6 @@ source-map@^0.5.0, source-map@^0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
spdx-correct@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
dependencies:
spdx-license-ids "^1.0.2"
spdx-expression-parse@~1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
spdx-license-ids@^1.0.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
sshpk@^1.7.0:
version "1.10.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.1.tgz#30e1a5d329244974a1af61511339d595af6638b0"
@@ -2081,12 +2051,14 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
string-width@^3.0.0, string-width@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
dependencies:
emoji-regex "^7.0.1"
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
strip-ansi "^5.1.0"
string_decoder@~0.10.x:
version "0.10.31"
@@ -2102,19 +2074,12 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
dependencies:
ansi-regex "^2.0.0"
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
dependencies:
ansi-regex "^3.0.0"
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
ansi-regex "^4.1.0"
strip-json-comments@~1.0.4:
version "1.0.4"
@@ -2163,6 +2128,13 @@ to-fast-properties@^1.0.1, to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
tough-cookie@~2.3.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
@@ -2207,13 +2179,6 @@ v8flags@^2.0.10:
dependencies:
user-home "^1.1.1"
validate-npm-package-license@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
dependencies:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
verror@1.3.6:
version "1.3.6"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
@@ -2236,12 +2201,14 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.1"
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
wrap-ansi@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
ansi-styles "^3.2.0"
string-width "^3.0.0"
strip-ansi "^5.0.0"
wrappy@1:
version "1.0.2"
@@ -2251,34 +2218,35 @@ xtend@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
yargs-parser@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"
yargs-parser@^13.1.1:
version "13.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
dependencies:
camelcase "^4.1.0"
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360"
yargs@^13.1.0:
version "13.3.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83"
integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==
dependencies:
camelcase "^4.1.0"
cliui "^3.2.0"
decamelize "^1.1.1"
get-caller-file "^1.0.1"
os-locale "^2.0.0"
read-pkg-up "^2.0.0"
cliui "^5.0.0"
find-up "^3.0.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^2.0.0"
string-width "^3.0.0"
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^7.0.0"
y18n "^4.0.0"
yargs-parser "^13.1.1"

View File

@@ -2,7 +2,7 @@
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "FBJNI_JAVA_TARGET", "JNI_TARGET", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library", "yoga_prebuilt_cxx_library")
load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID", "JNI_TARGET", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library", "yoga_prebuilt_cxx_library")
yoga_prebuilt_cxx_library(
name = "ndklog",
@@ -32,13 +32,14 @@ yoga_cxx_library(
"-Wall",
"-Werror",
"-Wno-unused-parameter",
"-std=c++14",
"-Wno-unused-variable",
"-std=c++11",
],
platforms = (ANDROID,),
soname = "libfbjni.$(ext)",
visibility = ["PUBLIC"],
deps = [
":ndklog",
FBJNI_JAVA_TARGET,
JNI_TARGET,
],
)

View File

@@ -20,6 +20,7 @@ add_compile_options(
file(GLOB fb_SRC
*.cpp
jni/*.cpp
jni/detail/*.cpp
lyra/*.cpp)
add_library(fb SHARED

View File

@@ -1,38 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#include <cstdarg>
#include <stdio.h>
#include <fb/assert.h>
#include <fb/log.h>
namespace facebook {
#define ASSERT_BUF_SIZE 4096
static char sAssertBuf[ASSERT_BUF_SIZE];
static AssertHandler gAssertHandler;
void assertInternal(const char* formatstr ...) {
va_list va_args;
va_start(va_args, formatstr);
vsnprintf(sAssertBuf, sizeof(sAssertBuf), formatstr, va_args);
va_end(va_args);
if (gAssertHandler != NULL) {
gAssertHandler(sAssertBuf);
}
FBLOG(LOG_FATAL, "fbassert", "%s", sAssertBuf);
// crash at this specific address so that we can find our crashes easier
*(int*)0xdeadb00c = 0;
// let the compiler know we won't reach the end of the function
__builtin_unreachable();
}
void setAssertHandler(AssertHandler assertHandler) {
gAssertHandler = assertHandler;
}
} // namespace facebook

View File

@@ -1,80 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
/** @file ALog.h
*
* Very simple android only logging. Define LOG_TAG to enable the macros.
*/
#pragma once
#ifdef __ANDROID__
#include <android/log.h>
namespace facebook {
namespace alog {
template<typename... ARGS>
inline void log(int level, const char* tag, const char* msg, ARGS... args) noexcept {
__android_log_print(level, tag, msg, args...);
}
template<typename... ARGS>
inline void log(int level, const char* tag, const char* msg) noexcept {
__android_log_write(level, tag, msg);
}
template<typename... ARGS>
inline void logv(const char* tag, const char* msg, ARGS... args) noexcept {
log(ANDROID_LOG_VERBOSE, tag, msg, args...);
}
template<typename... ARGS>
inline void logd(const char* tag, const char* msg, ARGS... args) noexcept {
log(ANDROID_LOG_DEBUG, tag, msg, args...);
}
template<typename... ARGS>
inline void logi(const char* tag, const char* msg, ARGS... args) noexcept {
log(ANDROID_LOG_INFO, tag, msg, args...);
}
template<typename... ARGS>
inline void logw(const char* tag, const char* msg, ARGS... args) noexcept {
log(ANDROID_LOG_WARN, tag, msg, args...);
}
template<typename... ARGS>
inline void loge(const char* tag, const char* msg, ARGS... args) noexcept {
log(ANDROID_LOG_ERROR, tag, msg, args...);
}
template<typename... ARGS>
inline void logf(const char* tag, const char* msg, ARGS... args) noexcept {
log(ANDROID_LOG_FATAL, tag, msg, args...);
}
#ifdef LOG_TAG
# define ALOGV(...) ::facebook::alog::logv(LOG_TAG, __VA_ARGS__)
# define ALOGD(...) ::facebook::alog::logd(LOG_TAG, __VA_ARGS__)
# define ALOGI(...) ::facebook::alog::logi(LOG_TAG, __VA_ARGS__)
# define ALOGW(...) ::facebook::alog::logw(LOG_TAG, __VA_ARGS__)
# define ALOGE(...) ::facebook::alog::loge(LOG_TAG, __VA_ARGS__)
# define ALOGF(...) ::facebook::alog::logf(LOG_TAG, __VA_ARGS__)
#endif
}}
#else
# define ALOGV(...) ((void)0)
# define ALOGD(...) ((void)0)
# define ALOGI(...) ((void)0)
# define ALOGW(...) ((void)0)
# define ALOGE(...) ((void)0)
# define ALOGF(...) ((void)0)
#endif

View File

@@ -1,44 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <atomic>
#include <fb/assert.h>
#include <fb/noncopyable.h>
#include <fb/nonmovable.h>
#include <fb/RefPtr.h>
namespace facebook {
class Countable : public noncopyable, public nonmovable {
public:
// RefPtr expects refcount to start at 0
Countable() : m_refcount(0) {}
virtual ~Countable()
{
FBASSERT(m_refcount == 0);
}
private:
void ref() {
++m_refcount;
}
void unref() {
if (0 == --m_refcount) {
delete this;
}
}
bool hasOnlyOneRef() const {
return m_refcount == 1;
}
template <typename T> friend class RefPtr;
std::atomic<int> m_refcount;
};
}

View File

@@ -1,47 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <cstring>
#include <string>
#include <sstream>
namespace facebook {
#define FROM_HERE facebook::ProgramLocation(__FUNCTION__, __FILE__, __LINE__)
class ProgramLocation {
public:
ProgramLocation() : m_functionName("Unspecified"), m_fileName("Unspecified"), m_lineNumber(0) {}
ProgramLocation(const char* functionName, const char* fileName, int line) :
m_functionName(functionName),
m_fileName(fileName),
m_lineNumber(line)
{}
const char* functionName() const { return m_functionName; }
const char* fileName() const { return m_fileName; }
int lineNumber() const { return m_lineNumber; }
std::string asFormattedString() const {
std::stringstream str;
str << "Function " << m_functionName << " in file " << m_fileName << ":" << m_lineNumber;
return str.str();
}
bool operator==(const ProgramLocation& other) const {
// Assumes that the strings are static
return (m_functionName == other.m_functionName) && (m_fileName == other.m_fileName) && m_lineNumber == other.m_lineNumber;
}
private:
const char* m_functionName;
const char* m_fileName;
int m_lineNumber;
};
}

View File

@@ -1,271 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <utility>
#include <fb/assert.h>
namespace facebook {
// Reference counting smart pointer. This is designed to work with the
// Countable class or other implementations in the future. It is designed in a
// way to be both efficient and difficult to misuse. Typical usage is very
// simple once you learn the patterns (and the compiler will help!):
//
// By default, the internal pointer is null.
// RefPtr<Foo> ref;
//
// Object creation requires explicit construction:
// RefPtr<Foo> ref = createNew<Foo>(...);
//
// Or if the constructor is not public:
// RefPtr<Foo> ref = adoptRef(new Foo(...));
//
// But you can implicitly create from nullptr:
// RefPtr<Foo> maybeRef = cond ? ref : nullptr;
//
// Move/Copy Construction/Assignment are straightforward:
// RefPtr<Foo> ref2 = ref;
// ref = std::move(ref2);
//
// Destruction automatically drops the RefPtr's reference as expected.
//
// Upcasting is implicit but downcasting requires an explicit cast:
// struct Bar : public Foo {};
// RefPtr<Bar> barRef = static_cast<RefPtr<Bar>>(ref);
// ref = barRef;
//
template <class T>
class RefPtr {
public:
constexpr RefPtr() :
m_ptr(nullptr)
{}
// Allow implicit construction from a pointer only from nullptr
constexpr RefPtr(std::nullptr_t ptr) :
m_ptr(nullptr)
{}
RefPtr(const RefPtr<T>& ref) :
m_ptr(ref.m_ptr)
{
refIfNecessary(m_ptr);
}
// Only allow implicit upcasts. A downcast will result in a compile error
// unless you use static_cast (which will end up invoking the explicit
// operator below).
template <typename U>
RefPtr(const RefPtr<U>& ref, typename std::enable_if<std::is_base_of<T,U>::value, U>::type* = nullptr) :
m_ptr(ref.get())
{
refIfNecessary(m_ptr);
}
RefPtr(RefPtr<T>&& ref) :
m_ptr(nullptr)
{
*this = std::move(ref);
}
// Only allow implicit upcasts. A downcast will result in a compile error
// unless you use static_cast (which will end up invoking the explicit
// operator below).
template <typename U>
RefPtr(RefPtr<U>&& ref, typename std::enable_if<std::is_base_of<T,U>::value, U>::type* = nullptr) :
m_ptr(nullptr)
{
*this = std::move(ref);
}
~RefPtr() {
unrefIfNecessary(m_ptr);
m_ptr = nullptr;
}
RefPtr<T>& operator=(const RefPtr<T>& ref) {
if (m_ptr != ref.m_ptr) {
unrefIfNecessary(m_ptr);
m_ptr = ref.m_ptr;
refIfNecessary(m_ptr);
}
return *this;
}
// The STL assumes rvalue references are unique and for simplicity's sake, we
// make the same assumption here, that &ref != this.
RefPtr<T>& operator=(RefPtr<T>&& ref) {
unrefIfNecessary(m_ptr);
m_ptr = ref.m_ptr;
ref.m_ptr = nullptr;
return *this;
}
template <typename U>
RefPtr<T>& operator=(RefPtr<U>&& ref) {
unrefIfNecessary(m_ptr);
m_ptr = ref.m_ptr;
ref.m_ptr = nullptr;
return *this;
}
void reset() {
unrefIfNecessary(m_ptr);
m_ptr = nullptr;
}
T* get() const {
return m_ptr;
}
T* operator->() const {
return m_ptr;
}
T& operator*() const {
return *m_ptr;
}
template <typename U>
explicit operator RefPtr<U> () const;
explicit operator bool() const {
return m_ptr ? true : false;
}
bool isTheLastRef() const {
FBASSERT(m_ptr);
return m_ptr->hasOnlyOneRef();
}
// Creates a strong reference from a raw pointer, assuming that is already
// referenced from some other RefPtr. This should be used sparingly.
static inline RefPtr<T> assumeAlreadyReffed(T* ptr) {
return RefPtr<T>(ptr, ConstructionMode::External);
}
// Creates a strong reference from a raw pointer, assuming that it points to a
// freshly-created object. See the documentation for RefPtr for usage.
static inline RefPtr<T> adoptRef(T* ptr) {
return RefPtr<T>(ptr, ConstructionMode::Adopted);
}
private:
enum class ConstructionMode {
Adopted,
External
};
RefPtr(T* ptr, ConstructionMode mode) :
m_ptr(ptr)
{
FBASSERTMSGF(ptr, "Got null pointer in %s construction mode", mode == ConstructionMode::Adopted ? "adopted" : "external");
ptr->ref();
if (mode == ConstructionMode::Adopted) {
FBASSERT(ptr->hasOnlyOneRef());
}
}
static inline void refIfNecessary(T* ptr) {
if (ptr) {
ptr->ref();
}
}
static inline void unrefIfNecessary(T* ptr) {
if (ptr) {
ptr->unref();
}
}
template <typename U> friend class RefPtr;
T* m_ptr;
};
// Creates a strong reference from a raw pointer, assuming that is already
// referenced from some other RefPtr and that it is non-null. This should be
// used sparingly.
template <typename T>
static inline RefPtr<T> assumeAlreadyReffed(T* ptr) {
return RefPtr<T>::assumeAlreadyReffed(ptr);
}
// As above, but tolerant of nullptr.
template <typename T>
static inline RefPtr<T> assumeAlreadyReffedOrNull(T* ptr) {
return ptr ? RefPtr<T>::assumeAlreadyReffed(ptr) : nullptr;
}
// Creates a strong reference from a raw pointer, assuming that it points to a
// freshly-created object. See the documentation for RefPtr for usage.
template <typename T>
static inline RefPtr<T> adoptRef(T* ptr) {
return RefPtr<T>::adoptRef(ptr);
}
template <typename T, typename ...Args>
static inline RefPtr<T> createNew(Args&&... arguments) {
return RefPtr<T>::adoptRef(new T(std::forward<Args>(arguments)...));
}
template <typename T> template <typename U>
RefPtr<T>::operator RefPtr<U>() const {
static_assert(std::is_base_of<T, U>::value, "Invalid static cast");
return assumeAlreadyReffedOrNull<U>(static_cast<U*>(m_ptr));
}
template <typename T, typename U>
inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) {
return a.get() == b.get();
}
template <typename T, typename U>
inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) {
return a.get() != b.get();
}
template <typename T, typename U>
inline bool operator==(const RefPtr<T>& ref, U* ptr) {
return ref.get() == ptr;
}
template <typename T, typename U>
inline bool operator!=(const RefPtr<T>& ref, U* ptr) {
return ref.get() != ptr;
}
template <typename T, typename U>
inline bool operator==(U* ptr, const RefPtr<T>& ref) {
return ref.get() == ptr;
}
template <typename T, typename U>
inline bool operator!=(U* ptr, const RefPtr<T>& ref) {
return ref.get() != ptr;
}
template <typename T>
inline bool operator==(const RefPtr<T>& ref, std::nullptr_t ptr) {
return ref.get() == ptr;
}
template <typename T>
inline bool operator!=(const RefPtr<T>& ref, std::nullptr_t ptr) {
return ref.get() != ptr;
}
template <typename T>
inline bool operator==(std::nullptr_t ptr, const RefPtr<T>& ref) {
return ref.get() == ptr;
}
template <typename T>
inline bool operator!=(std::nullptr_t ptr, const RefPtr<T>& ref) {
return ref.get() != ptr;
}
}

View File

@@ -1,37 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <fb/assert.h>
#include <utility>
namespace facebook {
// Class that lets you declare a global but does not add a static constructor
// to the binary. Eventually I'd like to have this auto-initialize in a
// multithreaded environment but for now it's easiest just to use manual
// initialization.
template <typename T>
class StaticInitialized {
public:
constexpr StaticInitialized() :
m_instance(nullptr)
{}
template <typename ...Args>
void initialize(Args&&... arguments) {
FBASSERT(!m_instance);
m_instance = new T(std::forward<Args>(arguments)...);
}
T* operator->() const {
return m_instance;
}
private:
T* m_instance;
};
}

View File

@@ -1,115 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <pthread.h>
#include <errno.h>
#include <fb/assert.h>
namespace facebook {
///////////////////////////////////////////////////////////////////////////////
/**
* A thread-local object is a "global" object within a thread. This is useful
* for writing apartment-threaded code, where nothing is actullay shared
* between different threads (hence no locking) but those variables are not
* on stack in local scope. To use it, just do something like this,
*
* ThreadLocal<MyClass> static_object;
* static_object->data_ = ...;
* static_object->doSomething();
*
* ThreadLocal<int> static_number;
* int value = *static_number;
*
* So, syntax-wise it's similar to pointers. T can be primitive types, and if
* it's a class, there has to be a default constructor.
*/
template<typename T>
class ThreadLocal {
public:
/**
* Constructor that has to be called from a thread-neutral place.
*/
ThreadLocal() :
m_key(0),
m_cleanup(OnThreadExit) {
initialize();
}
/**
* As above but with a custom cleanup function
*/
typedef void (*CleanupFunction)(void* obj);
explicit ThreadLocal(CleanupFunction cleanup) :
m_key(0),
m_cleanup(cleanup) {
FBASSERT(cleanup);
initialize();
}
/**
* Access object's member or method through this operator overload.
*/
T *operator->() const {
return get();
}
T &operator*() const {
return *get();
}
T *get() const {
return (T*)pthread_getspecific(m_key);
}
T* release() {
T* obj = get();
pthread_setspecific(m_key, NULL);
return obj;
}
void reset(T* other = NULL) {
T* old = (T*)pthread_getspecific(m_key);
if (old != other) {
FBASSERT(m_cleanup);
m_cleanup(old);
pthread_setspecific(m_key, other);
}
}
private:
void initialize() {
int ret = pthread_key_create(&m_key, m_cleanup);
if (ret != 0) {
const char *msg = "(unknown error)";
switch (ret) {
case EAGAIN:
msg = "PTHREAD_KEYS_MAX (1024) is exceeded";
break;
case ENOMEM:
msg = "Out-of-memory";
break;
}
(void) msg;
FBASSERTMSGF(0, "pthread_key_create failed: %d %s", ret, msg);
}
}
static void OnThreadExit(void *obj) {
if (NULL != obj) {
delete (T*)obj;
}
}
pthread_key_t m_key;
CleanupFunction m_cleanup;
};
}

View File

@@ -1,33 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#ifndef FBASSERT_H
#define FBASSERT_H
#include <fb/visibility.h>
namespace facebook {
#define ENABLE_FBASSERT 1
#if ENABLE_FBASSERT
#define FBASSERTMSGF(expr, msg, ...) !(expr) ? facebook::assertInternal("Assert (%s:%d): " msg, __FILE__, __LINE__, ##__VA_ARGS__) : (void) 0
#else
#define FBASSERTMSGF(expr, msg, ...)
#endif // ENABLE_FBASSERT
#define FBASSERT(expr) FBASSERTMSGF(expr, "%s", #expr)
#define FBCRASH(msg, ...) facebook::assertInternal("Fatal error (%s:%d): " msg, __FILE__, __LINE__, ##__VA_ARGS__)
#define FBUNREACHABLE() facebook::assertInternal("This code should be unreachable (%s:%d)", __FILE__, __LINE__)
FBEXPORT void assertInternal(const char* formatstr, ...) __attribute__((noreturn));
// This allows storing the assert message before the current process terminates due to a crash
typedef void (*AssertHandler)(const char* message);
void setAssertHandler(AssertHandler assertHandler);
} // namespace facebook
#endif // FBASSERT_H

View File

@@ -1,21 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <jni.h>
#include <fb/Environment.h>
#include <fb/ALog.h>
#include <fb/fbjni/Common.h>
#include <fb/fbjni/Exceptions.h>
#include <fb/fbjni/ReferenceAllocators.h>
#include <fb/fbjni/References.h>
#include <fb/fbjni/Meta.h>
#include <fb/fbjni/CoreClasses.h>
#include <fb/fbjni/Iterator.h>
#include <fb/fbjni/Hybrid.h>
#include <fb/fbjni/Registration.h>

View File

@@ -1,36 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include "CoreClasses.h"
#include "NativeRunnable.h"
namespace facebook {
namespace jni {
class JThread : public JavaClass<JThread> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/lang/Thread;";
void start() {
static auto method = javaClassStatic()->getMethod<void()>("start");
method(self());
}
void join() {
static auto method = javaClassStatic()->getMethod<void()>("join");
method(self());
}
static local_ref<JThread> create(std::function<void()>&& runnable) {
auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(runnable));
return newInstance(static_ref_cast<JRunnable::javaobject>(jrunnable));
}
};
}
}

View File

@@ -1,206 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include "Exceptions.h"
#include "Hybrid.h"
namespace facebook {
namespace jni {
namespace detail {
#ifdef __i386__
// X86 ABI forces 16 byte stack allignment on calls. Unfortunately
// sometimes Dalvik chooses not to obey the ABI:
// - https://code.google.com/p/android/issues/detail?id=61012
// - https://android.googlesource.com/platform/ndk/+/81696d2%5E!/
// Therefore, we tell the compiler to re-align the stack on entry
// to our JNI functions.
#define JNI_ENTRY_POINT __attribute__((force_align_arg_pointer))
#else
#define JNI_ENTRY_POINT
#endif
// registration wrapper for legacy JNI-style functions
template<typename F, F func, typename C, typename... Args>
inline NativeMethodWrapper* exceptionWrapJNIMethod(void (*)(JNIEnv*, C, Args... args)) {
struct funcWrapper {
JNI_ENTRY_POINT static void call(JNIEnv* env, jobject obj, Args... args) {
// Note that if func was declared noexcept, then both gcc and clang are smart
// enough to elide the try/catch.
try {
(*func)(env, static_cast<C>(obj), args...);
} catch (...) {
translatePendingCppExceptionToJavaException();
}
}
};
// This intentionally erases the real type; JNI will do it anyway
return reinterpret_cast<NativeMethodWrapper*>(&(funcWrapper::call));
}
template<typename F, F func, typename C, typename R, typename... Args>
inline NativeMethodWrapper* exceptionWrapJNIMethod(R (*)(JNIEnv*, C, Args... args)) {
struct funcWrapper {
JNI_ENTRY_POINT static R call(JNIEnv* env, jobject obj, Args... args) {
try {
return (*func)(env, static_cast<JniType<C>>(obj), args...);
} catch (...) {
translatePendingCppExceptionToJavaException();
return R{};
}
}
};
// This intentionally erases the real type; JNI will do it anyway
return reinterpret_cast<NativeMethodWrapper*>(&(funcWrapper::call));
}
// registration wrappers for functions, with autoconversion of arguments.
template<typename F, F func, typename C, typename... Args>
inline NativeMethodWrapper* exceptionWrapJNIMethod(void (*)(alias_ref<C>, Args... args)) {
struct funcWrapper {
JNI_ENTRY_POINT static void call(JNIEnv*, jobject obj,
typename Convert<typename std::decay<Args>::type>::jniType... args) {
try {
(*func)(static_cast<JniType<C>>(obj), Convert<typename std::decay<Args>::type>::fromJni(args)...);
} catch (...) {
translatePendingCppExceptionToJavaException();
}
}
};
// This intentionally erases the real type; JNI will do it anyway
return reinterpret_cast<NativeMethodWrapper*>(&(funcWrapper::call));
}
template<typename F, F func, typename C, typename R, typename... Args>
inline NativeMethodWrapper* exceptionWrapJNIMethod(R (*)(alias_ref<C>, Args... args)) {
struct funcWrapper {
JNI_ENTRY_POINT static typename Convert<typename std::decay<R>::type>::jniType call(JNIEnv*, jobject obj,
typename Convert<typename std::decay<Args>::type>::jniType... args) {
try {
return Convert<typename std::decay<R>::type>::toJniRet(
(*func)(static_cast<JniType<C>>(obj), Convert<typename std::decay<Args>::type>::fromJni(args)...));
} catch (...) {
using jniRet = typename Convert<typename std::decay<R>::type>::jniType;
translatePendingCppExceptionToJavaException();
return jniRet{};
}
}
};
// This intentionally erases the real type; JNI will do it anyway
return reinterpret_cast<NativeMethodWrapper*>(&(funcWrapper::call));
}
// registration wrappers for non-static methods, with autoconvertion of arguments.
template <typename M, M method, typename C, typename... Args>
inline NativeMethodWrapper* exceptionWrapJNIMethod(
void (C::*method0)(Args... args)) {
(void)method0;
struct funcWrapper {
JNI_ENTRY_POINT static void call(JNIEnv* env, jobject obj,
typename Convert<typename std::decay<Args>::type>::jniType... args) {
try {
try {
auto aref = wrap_alias(static_cast<typename C::jhybridobject>(obj));
// This is usually a noop, but if the hybrid object is a
// base class of other classes which register JNI methods,
// this will get the right type for the registered method.
auto cobj = static_cast<C*>(facebook::jni::cthis(aref));
(cobj->*method)(Convert<typename std::decay<Args>::type>::fromJni(args)...);
} catch (const std::exception& ex) {
C::mapException(ex);
throw;
}
} catch (...) {
translatePendingCppExceptionToJavaException();
}
}
};
// This intentionally erases the real type; JNI will do it anyway
return reinterpret_cast<NativeMethodWrapper*>(&(funcWrapper::call));
}
template<typename M, M method, typename C, typename R, typename... Args>
inline NativeMethodWrapper* exceptionWrapJNIMethod(R (C::*method0)(Args... args)) {
struct funcWrapper {
JNI_ENTRY_POINT static typename Convert<typename std::decay<R>::type>::jniType call(JNIEnv* env, jobject obj,
typename Convert<typename std::decay<Args>::type>::jniType... args) {
try {
try {
auto aref = wrap_alias(static_cast<typename C::jhybridobject>(obj));
// This is usually a noop, but if the hybrid object is a
// base class of other classes which register JNI methods,
// this will get the right type for the registered method.
auto cobj = static_cast<C*>(facebook::jni::cthis(aref));
return Convert<typename std::decay<R>::type>::toJniRet(
(cobj->*method)(Convert<typename std::decay<Args>::type>::fromJni(args)...));
} catch (const std::exception& ex) {
C::mapException(ex);
throw;
}
} catch (...) {
using jniRet = typename Convert<typename std::decay<R>::type>::jniType;
translatePendingCppExceptionToJavaException();
return jniRet{};
}
}
};
// This intentionally erases the real type; JNI will do it anyway
return reinterpret_cast<NativeMethodWrapper*>(&(funcWrapper::call));
}
template<typename R, typename C, typename... Args>
inline std::string makeDescriptor(R (*)(JNIEnv*, C, Args... args)) {
return jmethod_traits<R(Args...)>::descriptor();
}
template<typename R, typename C, typename... Args>
inline std::string makeDescriptor(R (*)(alias_ref<C>, Args... args)) {
return jmethod_traits_from_cxx<R(Args...)>::descriptor();
}
template<typename R, typename C, typename... Args>
inline std::string makeDescriptor(R (C::*)(Args... args)) {
return jmethod_traits_from_cxx<R(Args...)>::descriptor();
}
template <typename R, typename... Args>
template <R (*func)(Args...)>
JNI_ENTRY_POINT R CriticalMethod<R (*)(Args...)>::call(
alias_ref<jclass>,
Args... args) noexcept {
static_assert(
IsJniPrimitive<R>() || std::is_void<R>(),
"Critical Native Methods may only return primitive JNI types, or void.");
static_assert(
AreJniPrimitives<Args...>(),
"Critical Native Methods may only use primitive JNI types as parameters");
return func(std::forward<Args>(args)...);
}
template <typename R, typename... Args>
template <R (*func)(Args...)>
inline std::string CriticalMethod<R (*)(Args...)>::desc() {
return makeDescriptor(call<func>);
}
}
}}

View File

@@ -1,346 +0,0 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* FB Wrapper for logging functions.
*
* The android logging API uses the macro "LOG()" for its logic, which means
* that it conflicts with random other places that use LOG for their own
* purposes and doesn't work right half the places you include it
*
* FBLOG uses exactly the same semantics (FBLOGD for debug etc) but because of
* the FB prefix it's strictly better. FBLOGV also gets stripped out based on
* whether NDEBUG is set, but can be overridden by FBLOG_NDEBUG
*
* Most of the rest is a copy of <cutils/log.h> with minor changes.
*/
//
// C/C++ logging functions. See the logging documentation for API details.
//
// We'd like these to be available from C code (in case we import some from
// somewhere), so this has a C interface.
//
// The output will be correct when the log file is shared between multiple
// threads and/or multiple processes so long as the operating system
// supports O_APPEND. These calls have mutex-protected data structures
// and so are NOT reentrant. Do not use LOG in a signal handler.
//
#pragma once
#include <fb/visibility.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ANDROID
#include <android/log.h>
#else
// These declarations are needed for our internal use even on non-Android
// builds.
// (they are borrowed from <android/log.h>)
/*
* Android log priority values, in ascending priority order.
*/
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
} android_LogPriority;
/*
* Send a simple string to the log.
*/
int __android_log_write(int prio, const char *tag, const char *text);
/*
* Send a formatted string to the log, used like printf(fmt,...)
*/
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
#if defined(__GNUC__)
__attribute__((format(printf, 3, 4)))
#endif
;
#endif
// ---------------------------------------------------------------------
/*
* Normally we strip FBLOGV (VERBOSE messages) from release builds.
* You can modify this (for example with "#define FBLOG_NDEBUG 0"
* at the top of your source file) to change that behavior.
*/
#ifndef FBLOG_NDEBUG
#ifdef NDEBUG
#define FBLOG_NDEBUG 1
#else
#define FBLOG_NDEBUG 0
#endif
#endif
/*
* This is the local tag used for the following simplified
* logging macros. You can change this preprocessor definition
* before using the other macros to change the tag.
*/
#ifndef LOG_TAG
#define LOG_TAG NULL
#endif
// ---------------------------------------------------------------------
/*
* Simplified macro to send a verbose log message using the current LOG_TAG.
*/
#ifndef FBLOGV
#if FBLOG_NDEBUG
#define FBLOGV(...) ((void)0)
#else
#define FBLOGV(...) ((void)FBLOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#endif
#endif
#define CONDITION(cond) (__builtin_expect((cond) != 0, 0))
#ifndef FBLOGV_IF
#if FBLOG_NDEBUG
#define FBLOGV_IF(cond, ...) ((void)0)
#else
#define FBLOGV_IF(cond, ...) \
((CONDITION(cond)) ? ((void)FBLOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif
#endif
/*
* Simplified macro to send a debug log message using the current LOG_TAG.
*/
#ifndef FBLOGD
#define FBLOGD(...) ((void)FBLOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#endif
#ifndef FBLOGD_IF
#define FBLOGD_IF(cond, ...) \
((CONDITION(cond)) ? ((void)FBLOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) : (void)0)
#endif
/*
* Simplified macro to send an info log message using the current LOG_TAG.
*/
#ifndef FBLOGI
#define FBLOGI(...) ((void)FBLOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
#endif
#ifndef FBLOGI_IF
#define FBLOGI_IF(cond, ...) \
((CONDITION(cond)) ? ((void)FBLOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) : (void)0)
#endif
/*
* Simplified macro to send a warning log message using the current LOG_TAG.
*/
#ifndef FBLOGW
#define FBLOGW(...) ((void)FBLOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
#endif
#ifndef FBLOGW_IF
#define FBLOGW_IF(cond, ...) \
((CONDITION(cond)) ? ((void)FBLOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) : (void)0)
#endif
/*
* Simplified macro to send an error log message using the current LOG_TAG.
*/
#ifndef FBLOGE
#define FBLOGE(...) ((void)FBLOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
#endif
#ifndef FBLOGE_IF
#define FBLOGE_IF(cond, ...) \
((CONDITION(cond)) ? ((void)FBLOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) : (void)0)
#endif
// ---------------------------------------------------------------------
/*
* Conditional based on whether the current LOG_TAG is enabled at
* verbose priority.
*/
#ifndef IF_FBLOGV
#if FBLOG_NDEBUG
#define IF_FBLOGV() if (false)
#else
#define IF_FBLOGV() IF_FBLOG(LOG_VERBOSE, LOG_TAG)
#endif
#endif
/*
* Conditional based on whether the current LOG_TAG is enabled at
* debug priority.
*/
#ifndef IF_FBLOGD
#define IF_FBLOGD() IF_FBLOG(LOG_DEBUG, LOG_TAG)
#endif
/*
* Conditional based on whether the current LOG_TAG is enabled at
* info priority.
*/
#ifndef IF_FBLOGI
#define IF_FBLOGI() IF_FBLOG(LOG_INFO, LOG_TAG)
#endif
/*
* Conditional based on whether the current LOG_TAG is enabled at
* warn priority.
*/
#ifndef IF_FBLOGW
#define IF_FBLOGW() IF_FBLOG(LOG_WARN, LOG_TAG)
#endif
/*
* Conditional based on whether the current LOG_TAG is enabled at
* error priority.
*/
#ifndef IF_FBLOGE
#define IF_FBLOGE() IF_FBLOG(LOG_ERROR, LOG_TAG)
#endif
// ---------------------------------------------------------------------
/*
* Log a fatal error. If the given condition fails, this stops program
* execution like a normal assertion, but also generating the given message.
* It is NOT stripped from release builds. Note that the condition test
* is -inverted- from the normal assert() semantics.
*/
#define FBLOG_ALWAYS_FATAL_IF(cond, ...) \
((CONDITION(cond)) ? ((void)fb_printAssert(#cond, LOG_TAG, __VA_ARGS__)) \
: (void)0)
#define FBLOG_ALWAYS_FATAL(...) \
(((void)fb_printAssert(NULL, LOG_TAG, __VA_ARGS__)))
/*
* Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
* are stripped out of release builds.
*/
#if FBLOG_NDEBUG
#define FBLOG_FATAL_IF(cond, ...) ((void)0)
#define FBLOG_FATAL(...) ((void)0)
#else
#define FBLOG_FATAL_IF(cond, ...) FBLOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__)
#define FBLOG_FATAL(...) FBLOG_ALWAYS_FATAL(__VA_ARGS__)
#endif
/*
* Assertion that generates a log message when the assertion fails.
* Stripped out of release builds. Uses the current LOG_TAG.
*/
#define FBLOG_ASSERT(cond, ...) FBLOG_FATAL_IF(!(cond), __VA_ARGS__)
//#define LOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
// ---------------------------------------------------------------------
/*
* Basic log message macro.
*
* Example:
* FBLOG(LOG_WARN, NULL, "Failed with error %d", errno);
*
* The second argument may be NULL or "" to indicate the "global" tag.
*/
#ifndef FBLOG
#define FBLOG(priority, tag, ...) \
FBLOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
#endif
#ifndef FBLOG_BY_DELIMS
#define FBLOG_BY_DELIMS(priority, tag, delims, msg, ...) \
logPrintByDelims(ANDROID_##priority, tag, delims, msg, ##__VA_ARGS__)
#endif
/*
* Log macro that allows you to specify a number for the priority.
*/
#ifndef FBLOG_PRI
#define FBLOG_PRI(priority, tag, ...) fb_printLog(priority, tag, __VA_ARGS__)
#endif
/*
* Log macro that allows you to pass in a varargs ("args" is a va_list).
*/
#ifndef FBLOG_PRI_VA
#define FBLOG_PRI_VA(priority, tag, fmt, args) \
fb_vprintLog(priority, NULL, tag, fmt, args)
#endif
/*
* Conditional given a desired logging priority and tag.
*/
#ifndef IF_FBLOG
#define IF_FBLOG(priority, tag) if (fb_testLog(ANDROID_##priority, tag))
#endif
typedef void (*LogHandler)(int priority, const char* tag, const char* message);
FBEXPORT void setLogHandler(LogHandler logHandler);
/*
* ===========================================================================
*
* The stuff in the rest of this file should not be used directly.
*/
FBEXPORT int fb_printLog(int prio, const char* tag, const char* fmt, ...)
#if defined(__GNUC__)
__attribute__((format(printf, 3, 4)))
#endif
;
#define fb_vprintLog(prio, cond, tag, fmt...) \
__android_log_vprint(prio, tag, fmt)
#define fb_printAssert(cond, tag, fmt...) __android_log_assert(cond, tag, fmt)
#define fb_writeLog(prio, tag, text) __android_log_write(prio, tag, text)
#define fb_bWriteLog(tag, payload, len) __android_log_bwrite(tag, payload, len)
#define fb_btWriteLog(tag, type, payload, len) \
__android_log_btwrite(tag, type, payload, len)
#define fb_testLog(prio, tag) (1)
/*
* FB extensions
*/
void logPrintByDelims(int priority, const char* tag, const char* delims,
const char* msg, ...);
#ifdef __cplusplus
}
#endif

View File

@@ -1,18 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
namespace facebook {
struct noncopyable {
noncopyable(const noncopyable&) = delete;
noncopyable& operator=(const noncopyable&) = delete;
protected:
noncopyable() = default;
};
}

View File

@@ -1,18 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
namespace facebook {
struct nonmovable {
nonmovable(nonmovable&&) = delete;
nonmovable& operator=(nonmovable&&) = delete;
protected:
nonmovable() = default;
};
}

View File

@@ -1,9 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#define FBEXPORT __attribute__((visibility("default")))

View File

@@ -6,26 +6,37 @@
*/
#pragma once
#include <fb/visibility.h>
#include "CoreClasses.h"
#include "References-forward.h"
#include <fbjni/fbjni.h>
namespace facebook {
namespace jni {
class JBuffer : public JavaClass<JBuffer> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/nio/Buffer;";
void rewind() const;
bool isDirect() const;
void* getDirectAddress() const;
size_t getDirectCapacity() const;
};
// JNI's NIO support has some awkward preconditions and error reporting. This
// class provides much more user-friendly access.
class FBEXPORT JByteBuffer : public JavaClass<JByteBuffer> {
class JByteBuffer : public JavaClass<JByteBuffer, JBuffer> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/nio/ByteBuffer;";
static local_ref<JByteBuffer> wrapBytes(uint8_t* data, size_t size);
static local_ref<JByteBuffer> allocateDirect(jint size);
bool isDirect() const;
uint8_t* getDirectBytes() const {
return static_cast<uint8_t*>(getDirectAddress());
}
uint8_t* getDirectBytes() const;
size_t getDirectSize() const;
size_t getDirectSize() const {
return getDirectCapacity();
}
};
}}

View File

@@ -6,8 +6,8 @@
*/
#pragma once
#include "CoreClasses.h"
#include "File.h"
#include <fbjni/fbjni.h>
#include <fbjni/File.h>
namespace facebook {
namespace jni {
@@ -18,12 +18,12 @@ class AContext : public JavaClass<AContext> {
// Define a method that calls into the represented Java class
local_ref<JFile::javaobject> getCacheDir() {
static auto method = getClass()->getMethod<JFile::javaobject()>("getCacheDir");
static const auto method = getClass()->getMethod<JFile::javaobject()>("getCacheDir");
return method(self());
}
local_ref<JFile::javaobject> getFilesDir() {
static auto method = getClass()->getMethod<JFile::javaobject()>("getFilesDir");
static const auto method = getClass()->getMethod<JFile::javaobject()>("getFilesDir");
return method(self());
}
};

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "CoreClasses.h"
#include <fbjni/fbjni.h>
namespace facebook {
namespace jni {
@@ -17,7 +17,7 @@ class JFile : public JavaClass<JFile> {
// Define a method that calls into the represented Java class
std::string getAbsolutePath() {
static auto method = getClass()->getMethod<jstring()>("getAbsolutePath");
static const auto method = getClass()->getMethod<jstring()>("getAbsolutePath");
return method(self())->toStdString();
}

View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <fbjni/fbjni.h>
#include <fbjni/NativeRunnable.h>
namespace facebook {
namespace jni {
class JThread : public JavaClass<JThread> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/lang/Thread;";
void start() {
static const auto method = javaClassStatic()->getMethod<void()>("start");
method(self());
}
void join() {
static const auto method = javaClassStatic()->getMethod<void()>("join");
method(self());
}
static local_ref<JThread> create(std::function<void()>&& runnable) {
auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(runnable));
return newInstance(static_ref_cast<JRunnable::javaobject>(jrunnable));
}
static local_ref<JThread> create(std::function<void()>&& runnable, std::string&& name) {
auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(runnable));
return newInstance(static_ref_cast<JRunnable::javaobject>(jrunnable), make_jstring(std::move(name)));
}
static local_ref<JThread> getCurrent() {
static const auto method = javaClassStatic()->getStaticMethod<local_ref<JThread>()>("currentThread");
return method(javaClassStatic());
}
int getPriority() {
static const auto method = getClass()->getMethod<jint()>("getPriority");
return method(self());
}
void setPriority(int priority) {
static const auto method = getClass()->getMethod<void(int)>("setPriority");
method(self(), priority);
}
};
}
}

View File

@@ -6,9 +6,7 @@
*/
#pragma once
#include "CoreClasses.h"
#include "Hybrid.h"
#include "Registration.h"
#include <fbjni/fbjni.h>
#include <functional>

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include <fbjni/fbjni.h>
#include <fbjni/ByteBuffer.h>
namespace facebook {
namespace jni {
class JReadableByteChannel : public JavaClass<JReadableByteChannel> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/nio/channels/ReadableByteChannel;";
int read(alias_ref<JByteBuffer> dest) const;
};
}}

View File

@@ -17,13 +17,13 @@ struct JPrimitive : JavaClass<T> {
using typename JavaClass<T>::javaobject;
using JavaClass<T>::javaClassStatic;
static local_ref<javaobject> valueOf(jprim val) {
static auto cls = javaClassStatic();
static auto method =
static const auto cls = javaClassStatic();
static const auto method =
cls->template getStaticMethod<javaobject(jprim)>("valueOf");
return method(cls, val);
}
jprim value() const {
static auto method =
static const auto method =
javaClassStatic()->template getMethod<jprim()>(T::kValueMethod);
return method(this->self());
}
@@ -55,9 +55,20 @@ DEFINE_BOXED_PRIMITIVE(double, Double)
#undef DEFINE_BOXED_PRIMITIVE
template<typename T>
inline typename std::enable_if<
(std::is_same<T, long long>::value || std::is_same<T, int64_t>::value) && !std::is_same<T, jlong>::value,
local_ref<jobject>
>::type autobox(T val) {
return JLong::valueOf(val);
}
struct JVoid : public jni::JavaClass<JVoid> {
static auto constexpr kJavaDescriptor = "Ljava/lang/Void;";
};
inline local_ref<jobject> autobox(alias_ref<jobject> val) {
return make_local(val);
}
}}

View File

@@ -15,9 +15,6 @@
#include <jni.h>
#include <fb/visibility.h>
#include <fb/Environment.h>
#ifdef FBJNI_DEBUG_REFS
# ifdef __ANDROID__
# include <android/log.h>
@@ -42,11 +39,11 @@
namespace facebook {
namespace jni {
FBEXPORT void throwPendingJniExceptionAsCppException();
FBEXPORT void throwCppExceptionIf(bool condition);
void throwPendingJniExceptionAsCppException();
void throwCppExceptionIf(bool condition);
[[noreturn]] FBEXPORT void throwNewJavaException(jthrowable);
[[noreturn]] FBEXPORT void throwNewJavaException(const char* throwableName, const char* msg);
[[noreturn]] void throwNewJavaException(jthrowable);
[[noreturn]] void throwNewJavaException(const char* throwableName, const char* msg);
template<typename... Args>
[[noreturn]] void throwNewJavaException(const char* throwableName, const char* fmt, Args... args);
@@ -65,20 +62,10 @@ template<typename... Args>
* unhelpful way (typically a segfault) while trying to handle an exception
* which occurs later.
*/
FBEXPORT jint initialize(JavaVM*, std::function<void()>&&) noexcept;
jint initialize(JavaVM*, std::function<void()>&&) noexcept;
namespace internal {
/**
* Retrieve a pointer the JNI environment of the current thread.
*
* @pre The current thread must be attached to the VM
*/
inline JNIEnv* getEnv() noexcept {
// TODO(T6594868) Benchmark against raw JNI access
return Environment::current();
}
// Define to get extremely verbose logging of references and to enable reference stats
#ifdef FBJNI_DEBUG_REFS
template<typename... Args>

View File

@@ -21,15 +21,15 @@ namespace jni {
// jobject /////////////////////////////////////////////////////////////////////////////////////////
inline bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept {
return internal::getEnv()->IsSameObject(lhs.get(), rhs.get()) != JNI_FALSE;
return Environment::current()->IsSameObject(lhs.get(), rhs.get()) != JNI_FALSE;
}
inline local_ref<JClass> JObject::getClass() const noexcept {
return adopt_local(internal::getEnv()->GetObjectClass(self()));
return adopt_local(Environment::current()->GetObjectClass(self()));
}
inline bool JObject::isInstanceOf(alias_ref<JClass> cls) const noexcept {
return internal::getEnv()->IsInstanceOf(self(), cls.get()) != JNI_FALSE;
return Environment::current()->IsInstanceOf(self(), cls.get()) != JNI_FALSE;
}
template<typename T>
@@ -47,8 +47,13 @@ inline void JObject::setFieldValue(JField<T> field, T value) noexcept {
field.set(self(), value);
}
template<typename T, typename>
inline void JObject::setFieldValue(JField<T> field, alias_ref<T> value) noexcept {
setFieldValue(field, value.get());
}
inline std::string JObject::toString() const {
static auto method = findClassLocal("java/lang/Object")->getMethod<jstring()>("toString");
static const auto method = findClassLocal("java/lang/Object")->getMethod<jstring()>("toString");
return method(self())->toStdString();
}
@@ -77,13 +82,13 @@ MonitorLock::MonitorLock() noexcept : owned_(nullptr) {}
MonitorLock::MonitorLock(alias_ref<JObject> object) noexcept
: owned_(object) {
internal::getEnv()->MonitorEnter(object.get());
Environment::current()->MonitorEnter(object.get());
}
void MonitorLock::reset() noexcept {
if (owned_) {
internal::getEnv()->MonitorExit(owned_.get());
if (internal::getEnv()->ExceptionCheck()) {
Environment::current()->MonitorExit(owned_.get());
if (Environment::current()->ExceptionCheck()) {
abort(); // Lock mismatch
}
owned_ = nullptr;
@@ -126,7 +131,7 @@ namespace detail {
template<typename JC, typename... Args>
static local_ref<JC> newInstance(Args... args) {
static auto cls = JC::javaClassStatic();
static auto constructor = cls->template getConstructor<typename JC::javaobject(Args...)>();
static const auto constructor = cls->template getConstructor<typename JC::javaobject(Args...)>();
return cls->newObject(constructor, args...);
}
}
@@ -154,17 +159,18 @@ struct NativeMethod {
};
inline local_ref<JClass> JClass::getSuperclass() const noexcept {
return adopt_local(internal::getEnv()->GetSuperclass(self()));
return adopt_local(Environment::current()->GetSuperclass(self()));
}
inline void JClass::registerNatives(std::initializer_list<NativeMethod> methods) {
const auto env = internal::getEnv();
const auto env = Environment::current();
JNINativeMethod jnimethods[methods.size()];
size_t i = 0;
for (auto it = methods.begin(); it < methods.end(); ++it, ++i) {
jnimethods[i].name = it->name;
jnimethods[i].signature = it->descriptor.c_str();
// The JNI struct members are unnecessarily non-const.
jnimethods[i].name = const_cast<char*>(it->name);
jnimethods[i].signature = const_cast<char*>(it->descriptor.c_str());
jnimethods[i].fnPtr = reinterpret_cast<void*>(it->wrapper);
}
@@ -173,8 +179,13 @@ inline void JClass::registerNatives(std::initializer_list<NativeMethod> methods)
}
inline bool JClass::isAssignableFrom(alias_ref<JClass> other) const noexcept {
const auto env = internal::getEnv();
const auto result = env->IsAssignableFrom(self(), other.get());
const auto env = Environment::current();
// Ths method has behavior compatible with the
// java.lang.Class#isAssignableFrom method. The order of the
// arguments to the JNI IsAssignableFrom C function is "opposite"
// from what some might expect, which makes this code look a little
// odd, but it is correct.
const auto result = env->IsAssignableFrom(other.get(), self());
return result;
}
@@ -198,7 +209,7 @@ template<typename F>
inline JMethod<F> JClass::getMethod(
const char* name,
const char* descriptor) const {
const auto env = internal::getEnv();
const auto env = Environment::current();
const auto method = env->GetMethodID(self(), name, descriptor);
FACEBOOK_JNI_THROW_EXCEPTION_IF(!method);
return JMethod<F>{method};
@@ -213,7 +224,7 @@ template<typename F>
inline JStaticMethod<F> JClass::getStaticMethod(
const char* name,
const char* descriptor) const {
const auto env = internal::getEnv();
const auto env = Environment::current();
const auto method = env->GetStaticMethodID(self(), name, descriptor);
FACEBOOK_JNI_THROW_EXCEPTION_IF(!method);
return JStaticMethod<F>{method};
@@ -228,7 +239,7 @@ template<typename F>
inline JNonvirtualMethod<F> JClass::getNonvirtualMethod(
const char* name,
const char* descriptor) const {
const auto env = internal::getEnv();
const auto env = Environment::current();
const auto method = env->GetMethodID(self(), name, descriptor);
FACEBOOK_JNI_THROW_EXCEPTION_IF(!method);
return JNonvirtualMethod<F>{method};
@@ -244,7 +255,7 @@ template<typename T>
inline JField<enable_if_t<IsJniScalar<T>(), T>> JClass::getField(
const char* name,
const char* descriptor) const {
const auto env = internal::getEnv();
const auto env = Environment::current();
auto field = env->GetFieldID(self(), name, descriptor);
FACEBOOK_JNI_THROW_EXCEPTION_IF(!field);
return JField<T>{field};
@@ -260,7 +271,7 @@ template<typename T>
inline JStaticField<enable_if_t<IsJniScalar<T>(), T>> JClass::getStaticField(
const char* name,
const char* descriptor) const {
const auto env = internal::getEnv();
const auto env = Environment::current();
auto field = env->GetStaticFieldID(self(), name, descriptor);
FACEBOOK_JNI_THROW_EXCEPTION_IF(!field);
return JStaticField<T>{field};
@@ -281,11 +292,16 @@ inline void JClass::setStaticFieldValue(JStaticField<T> field, T value) noexcept
field.set(self(), value);
}
template<typename T, typename>
inline void JClass::setStaticFieldValue(JStaticField<T> field, alias_ref<T> value) noexcept {
setStaticFieldValue(field, value.get());
}
template<typename R, typename... Args>
inline local_ref<R> JClass::newObject(
JConstructor<R(Args...)> constructor,
Args... args) const {
const auto env = internal::getEnv();
const auto env = Environment::current();
auto object = env->NewObject(self(), constructor.getId(),
detail::callToJni(
detail::Convert<typename std::decay<Args>::type>::toCall(args))...);
@@ -338,18 +354,11 @@ struct Convert<const char*> {
};
}
// jthrowable //////////////////////////////////////////////////////////////////////////////////////
inline local_ref<JThrowable> JThrowable::initCause(alias_ref<JThrowable> cause) {
static auto meth = javaClassStatic()->getMethod<javaobject(javaobject)>("initCause");
return meth(self(), cause.get());
}
// jtypeArray //////////////////////////////////////////////////////////////////////////////////////
namespace detail {
inline size_t JArray::size() const noexcept {
const auto env = internal::getEnv();
const auto env = Environment::current();
return env->GetArrayLength(self());
}
}
@@ -409,8 +418,8 @@ std::string JArrayClass<T>::get_instantiated_base_name() {
template<typename T>
auto JArrayClass<T>::newArray(size_t size) -> local_ref<javaobject> {
static auto elementClass = findClassStatic(jtype_traits<T>::base_name().c_str());
const auto env = internal::getEnv();
static const auto elementClass = findClassStatic(jtype_traits<T>::base_name().c_str());
const auto env = Environment::current();
auto rawArray = env->NewObjectArray(size, elementClass.get(), nullptr);
FACEBOOK_JNI_THROW_EXCEPTION_IF(!rawArray);
return adopt_local(static_cast<javaobject>(rawArray));
@@ -418,13 +427,13 @@ auto JArrayClass<T>::newArray(size_t size) -> local_ref<javaobject> {
template<typename T>
inline void JArrayClass<T>::setElement(size_t idx, const T& value) {
const auto env = internal::getEnv();
const auto env = Environment::current();
env->SetObjectArrayElement(this->self(), idx, value);
}
template<typename T>
inline local_ref<T> JArrayClass<T>::getElement(size_t idx) {
const auto env = internal::getEnv();
const auto env = Environment::current();
auto rawElement = env->GetObjectArrayElement(this->self(), idx);
return adopt_local(static_cast<T>(rawElement));
}
@@ -434,12 +443,16 @@ inline detail::ElementProxy<JArrayClass<T>> JArrayClass<T>::operator[](size_t in
return detail::ElementProxy<JArrayClass<T>>(this, index);
}
template<typename T>
local_ref<typename JArrayClass<T>::javaobject> adopt_local_array(jobjectArray ref) {
return adopt_local(static_cast<typename JArrayClass<T>::javaobject>(ref));
}
// jarray /////////////////////////////////////////////////////////////////////////////////////////
template <typename JArrayType>
auto JPrimitiveArray<JArrayType>::getRegion(jsize start, jsize length)
-> std::unique_ptr<T[]> {
using T = typename jtype_traits<JArrayType>::entry_type;
auto buf = std::unique_ptr<T[]>{new T[length]};
getRegion(start, length, buf.get());
return buf;
@@ -510,7 +523,7 @@ class PinnedCriticalAlloc {
jboolean* isCopy) {
(void)start;
(void)length;
const auto env = internal::getEnv();
const auto env = Environment::current();
*elements = static_cast<T*>(env->GetPrimitiveArrayCritical(array.get(), isCopy));
FACEBOOK_JNI_THROW_EXCEPTION_IF(!elements);
*size = array->size();
@@ -523,7 +536,7 @@ class PinnedCriticalAlloc {
jint mode) {
(void)start;
(void)size;
const auto env = internal::getEnv();
const auto env = Environment::current();
env->ReleasePrimitiveArrayCritical(array.get(), elements, mode);
}
};

View File

@@ -20,14 +20,19 @@
#include <jni.h>
#include <fb/visibility.h>
namespace facebook {
namespace jni {
class JClass;
class JObject;
namespace detail {
/// Lookup a class by name. This should only be used internally.
jclass findClass(JNIEnv* env, const char* name);
}
/// Lookup a class by name. Note this functions returns an alias_ref that
/// points to a leaked global reference. This is appropriate for classes
/// that are never unloaded (which is any class in an Android app and most
@@ -37,7 +42,7 @@ class JObject;
/// in a "static auto" variable, or a static global.
///
/// @return Returns a leaked global reference to the class
FBEXPORT alias_ref<JClass> findClassStatic(const char* name);
alias_ref<JClass> findClassStatic(const char* name);
/// Lookup a class by name. Note this functions returns a local reference,
/// which means that it must not be stored in a static variable.
@@ -46,12 +51,12 @@ FBEXPORT alias_ref<JClass> findClassStatic(const char* name);
/// (like caching method ids).
///
/// @return Returns a global reference to the class
FBEXPORT local_ref<JClass> findClassLocal(const char* name);
local_ref<JClass> findClassLocal(const char* name);
/// Check to see if two references refer to the same object. Comparison with nullptr
/// returns true if and only if compared to another nullptr. A weak reference that
/// refers to a reclaimed object count as nullptr.
FBEXPORT bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept;
bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept;
// Together, these classes allow convenient use of any class with the fbjni
// helpers. To use:
@@ -70,7 +75,7 @@ FBEXPORT bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexc
// constexpr static auto kJavaDescriptor = "Lcom/example/package/MyClass;";
//
// void foo() {
// static auto method = javaClassStatic()->getMethod<void()>("foo");
// static const auto method = javaClassStatic()->getMethod<void()>("foo");
// method(self());
// }
//
@@ -94,7 +99,7 @@ static local_ref<JC> newInstance(Args... args);
class MonitorLock;
class FBEXPORT JObject : detail::JObjectBase {
class JObject : detail::JObjectBase {
public:
static constexpr auto kJavaDescriptor = "Ljava/lang/Object;";
@@ -115,10 +120,12 @@ public:
template<typename T>
local_ref<T*> getFieldValue(JField<T*> field) const noexcept;
/// Set the value of field. Any Java type is accepted, including the primitive types
/// and raw reference types.
/// Set the value of field. Any Java type is accepted.
template<typename T>
void setFieldValue(JField<T> field, T value) noexcept;
template<typename T,
typename = typename std::enable_if<IsPlainJniReference<T>(), T>::type>
void setFieldValue(JField<T> field, alias_ref<T> value) noexcept;
/// Convenience method to create a std::string representing the object
std::string toString() const;
@@ -190,7 +197,7 @@ struct JTypeFor<T, Base, void> {
// jthrowable) to be used as javaobject. This should only be necessary for
// built-in jni types and not user-defined ones.
template <typename T, typename Base = JObject, typename JType = void>
class FBEXPORT JavaClass : public Base {
class JavaClass : public Base {
using JObjType = typename detail::JTypeFor<T, Base, JType>;
public:
using _javaobject = typename JObjType::_javaobject;
@@ -218,7 +225,7 @@ protected:
/// Wrapper to provide functionality to jclass references
struct NativeMethod;
class FBEXPORT JClass : public JavaClass<JClass, JObject, jclass> {
class JClass : public JavaClass<JClass, JObject, jclass> {
public:
/// Java type descriptor
static constexpr const char* kJavaDescriptor = "Ljava/lang/Class;";
@@ -295,10 +302,12 @@ class FBEXPORT JClass : public JavaClass<JClass, JObject, jclass> {
template<typename T>
local_ref<T*> getStaticFieldValue(JStaticField<T*> field) noexcept;
/// Set the value of field. Any Java type is accepted, including the primitive types
/// and raw reference types.
/// Set the value of field. Any Java type is accepted.
template<typename T>
void setStaticFieldValue(JStaticField<T> field, T value) noexcept;
template<typename T,
typename = typename std::enable_if<IsPlainJniReference<T>(), T>::type>
void setStaticFieldValue(JStaticField<T> field, alias_ref<T> value) noexcept;
/// Allocates a new object and invokes the specified constructor
template<typename R, typename... Args>
@@ -330,27 +339,23 @@ private:
void registerNatives(const char* name, std::initializer_list<NativeMethod> methods);
/// Wrapper to provide functionality to jstring references
class FBEXPORT JString : public JavaClass<JString, JObject, jstring> {
class JString : public JavaClass<JString, JObject, jstring> {
public:
/// Java type descriptor
static constexpr const char* kJavaDescriptor = "Ljava/lang/String;";
/// Convenience method to convert a jstring object to a std::string
std::string toStdString() const;
/// Convenience method to convert a jstring object to a std::u16string
std::u16string toU16String() const;
};
/// Convenience functions to convert a std::string or const char* into a @ref local_ref to a
/// jstring
FBEXPORT local_ref<JString> make_jstring(const char* modifiedUtf8);
FBEXPORT local_ref<JString> make_jstring(const std::string& modifiedUtf8);
/// Wrapper to provide functionality to jthrowable references
class FBEXPORT JThrowable : public JavaClass<JThrowable, JObject, jthrowable> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/lang/Throwable;";
local_ref<JThrowable> initCause(alias_ref<JThrowable> cause);
};
/// Convenience functions to convert a const char*, std::string, or std::u16string
/// into a @ref local_ref to a jstring.
local_ref<JString> make_jstring(const char* modifiedUtf8);
local_ref<JString> make_jstring(const std::string& modifiedUtf8);
local_ref<JString> make_jstring(const std::u16string& utf16);
namespace detail {
template<typename Target>
@@ -378,7 +383,7 @@ class ElementProxy {
}
namespace detail {
class FBEXPORT JArray : public JavaClass<JArray, JObject, jarray> {
class JArray : public JavaClass<JArray, JObject, jarray> {
public:
// This cannot be used in a scope that derives a descriptor (like in a method
// signature). Use a more derived type instead (like JArrayInt or
@@ -390,7 +395,7 @@ class FBEXPORT JArray : public JavaClass<JArray, JObject, jarray> {
// This is used so that the JArrayClass<T> javaobject extends jni's
// jobjectArray. This class should not be used directly. A general Object[]
// should use JArrayClass<jobject>.
class FBEXPORT JTypeArray : public JavaClass<JTypeArray, JArray, jobjectArray> {
class JTypeArray : public JavaClass<JTypeArray, JArray, jobjectArray> {
// This cannot be used in a scope that derives a descriptor (like in a method
// signature).
static constexpr const char* kJavaDescriptor = nullptr;
@@ -440,9 +445,7 @@ template <typename T>
using jtypeArray = typename JArrayClass<T>::javaobject;
template<typename T>
local_ref<typename JArrayClass<T>::javaobject> adopt_local_array(jobjectArray ref) {
return adopt_local(static_cast<typename JArrayClass<T>::javaobject>(ref));
}
local_ref<typename JArrayClass<T>::javaobject> adopt_local_array(jobjectArray ref);
template<typename Target>
local_ref<typename Target::javaentry> adopt_local(detail::ElementProxy<Target> elementProxy) {
@@ -460,7 +463,7 @@ template <typename T> class PinnedCriticalAlloc;
/// This is an empty holder by itself. Construct a PinnedPrimitiveArray to actually interact with
/// the elements of the array.
template <typename JArrayType>
class FBEXPORT JPrimitiveArray :
class JPrimitiveArray :
public JavaClass<JPrimitiveArray<JArrayType>, detail::JArray, JArrayType> {
static_assert(is_jni_primitive_array<JArrayType>(), "");
public:
@@ -500,14 +503,14 @@ private:
void releaseElements(T* elements, jint mode);
};
FBEXPORT local_ref<jbooleanArray> make_boolean_array(jsize size);
FBEXPORT local_ref<jbyteArray> make_byte_array(jsize size);
FBEXPORT local_ref<jcharArray> make_char_array(jsize size);
FBEXPORT local_ref<jshortArray> make_short_array(jsize size);
FBEXPORT local_ref<jintArray> make_int_array(jsize size);
FBEXPORT local_ref<jlongArray> make_long_array(jsize size);
FBEXPORT local_ref<jfloatArray> make_float_array(jsize size);
FBEXPORT local_ref<jdoubleArray> make_double_array(jsize size);
local_ref<jbooleanArray> make_boolean_array(jsize size);
local_ref<jbyteArray> make_byte_array(jsize size);
local_ref<jcharArray> make_char_array(jsize size);
local_ref<jshortArray> make_short_array(jsize size);
local_ref<jintArray> make_int_array(jsize size);
local_ref<jlongArray> make_long_array(jsize size);
local_ref<jfloatArray> make_float_array(jsize size);
local_ref<jdoubleArray> make_double_array(jsize size);
using JArrayBoolean = JPrimitiveArray<jbooleanArray>;
using JArrayByte = JPrimitiveArray<jbyteArray>;
@@ -569,6 +572,29 @@ class PinnedPrimitiveArray {
friend class JPrimitiveArray<typename jtype_traits<T>::array_type>;
};
struct JStackTraceElement : JavaClass<JStackTraceElement> {
static auto constexpr kJavaDescriptor = "Ljava/lang/StackTraceElement;";
static local_ref<javaobject> create(const std::string& declaringClass, const std::string& methodName, const std::string& file, int line);
std::string getClassName() const;
std::string getMethodName() const;
std::string getFileName() const;
int getLineNumber() const;
};
/// Wrapper to provide functionality to jthrowable references
class JThrowable : public JavaClass<JThrowable, JObject, jthrowable> {
public:
static constexpr const char* kJavaDescriptor = "Ljava/lang/Throwable;";
using JStackTrace = JArrayClass<JStackTraceElement::javaobject>;
local_ref<JThrowable> initCause(alias_ref<JThrowable> cause);
local_ref<JStackTrace> getStackTrace();
void setStackTrace(alias_ref<JArrayClass<JStackTraceElement::javaobject>>);
};
#pragma push_macro("PlainJniRefMap")
#undef PlainJniRefMap
#define PlainJniRefMap(rtype, jtype) \

View File

@@ -9,24 +9,69 @@
#include <string>
#include <jni.h>
#include <fb/visibility.h>
namespace facebook {
namespace jni {
// Keeps a thread-local reference to the current thread's JNIEnv.
struct Environment {
// May be null if this thread isn't attached to the JVM
FBEXPORT static JNIEnv* current();
// Throws a std::runtime_error if this thread isn't attached to the JVM
// TODO(T6594868) Benchmark against raw JNI access
static JNIEnv* current();
static void initialize(JavaVM* vm);
// There are subtle issues with calling the next functions directly. It is
// much better to always use a ThreadScope to manage attaching/detaching for
// you.
FBEXPORT static JNIEnv* ensureCurrentThreadIsAttached();
FBEXPORT static void detachCurrentThread();
static JNIEnv* ensureCurrentThreadIsAttached();
};
namespace detail {
// This will return null the thread isn't attached to the VM, or if
// fbjni has never been initialized with a VM at all. You probably
// shouldn't be using this.
JNIEnv* currentOrNull();
/**
* If there's thread-local data, it's a pointer to one of these. The
* instance is a member of JniEnvCacher or ThreadScope, and lives on
* the stack.
*/
struct TLData {
// This is modified only by JniEnvCacher, and is guaranteed to be
// valid if set, and refer to an env which originated from a JNI
// call into C++.
JNIEnv* env;
// This is modified only by ThreadScope, and is set only if an
// instance of ThreadScope which attached is on the stack.
bool attached;
};
/**
* RAII object which manages a cached JNIEnv* value. A Value is only
* cached if it is guaranteed safe, which means when C++ is called
* from a registered fbjni function.
*/
class JniEnvCacher {
public:
JniEnvCacher(JNIEnv* env);
JniEnvCacher(JniEnvCacher&) = delete;
JniEnvCacher(JniEnvCacher&&) = default;
JniEnvCacher& operator=(JniEnvCacher&) = delete;
JniEnvCacher& operator=(JniEnvCacher&&) = delete;
~JniEnvCacher();
private:
// If this flag is set, then, this object needs to clear the cache.
bool thisCached_;
// The thread local pointer may point here.
detail::TLData data_;
};
}
/**
* RAII Object that attaches a thread to the JVM. Failing to detach from a thread before it
* exits will cause a crash, as will calling Detach an extra time, and this guard class helps
@@ -48,8 +93,11 @@ struct Environment {
* class or instance to the new thread; this bypasses the need for the class loader.
* (See http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html#attach_current_thread)
* If you need access to the application's classes, you can use ThreadScope::WithClassLoader.
* - If fbjni has never been initialized, there will be no JavaVM object to attach with.
* In that case, a std::runtime_error will be thrown. This is only likely to happen in a
* standalone C++ application, or if Environment::initialize is not used.
*/
class FBEXPORT ThreadScope {
class ThreadScope {
public:
ThreadScope();
ThreadScope(ThreadScope&) = delete;
@@ -67,8 +115,14 @@ class FBEXPORT ThreadScope {
static void WithClassLoader(std::function<void()>&& runnable);
static void OnLoad();
private:
bool attachedWithThisScope_;
// If this flag is set, then this object needs to detach.
bool thisAttached_;
// The thread local pointer may point here.
detail::TLData data_;
};
}
}

View File

@@ -23,12 +23,15 @@
#include <jni.h>
#include <fb/visibility.h>
#include "Common.h"
#include "References.h"
#include "CoreClasses.h"
#if defined(__ANDROID__) && defined(__ARM_ARCH_5TE__) && !defined(FBJNI_NO_EXCEPTION_PTR)
// ARMv5 NDK does not support exception_ptr so we cannot use that when building for it.
#define FBJNI_NO_EXCEPTION_PTR
#endif
namespace facebook {
namespace jni {
@@ -57,10 +60,10 @@ class JCppException : public JavaClass<JCppException, JThrowable> {
*
* Note: the what() method of this class is not thread-safe (t6900503).
*/
class FBEXPORT JniException : public std::exception {
class JniException : public std::exception {
public:
JniException();
~JniException();
~JniException() override;
explicit JniException(alias_ref<jthrowable> throwable);
@@ -70,7 +73,7 @@ class FBEXPORT JniException : public std::exception {
local_ref<JThrowable> getThrowable() const noexcept;
virtual const char* what() const noexcept;
const char* what() const noexcept override;
void setJavaException() const noexcept;
@@ -105,11 +108,23 @@ template<typename... Args>
}
// Identifies any pending C++ exception and throws it as a Java exception. If the exception can't
// be thrown, it aborts the program. This is a noexcept function at C++ level.
FBEXPORT void translatePendingCppExceptionToJavaException() noexcept;
// be thrown, it aborts the program.
void translatePendingCppExceptionToJavaException();
#ifndef FBJNI_NO_EXCEPTION_PTR
local_ref<JThrowable> getJavaExceptionForCppException(std::exception_ptr ptr);
#endif
/***
* The stack returned may include build ids. It may be beneficial to
* call lyra::setLibraryIdentifierFunction before calling this if
* build ids are desirable.
*/
local_ref<JThrowable> getJavaExceptionForCppBackTrace();
local_ref<JThrowable> getJavaExceptionForCppBackTrace(const char* msg);
// For convenience, some exception names in java.lang are available here.
const char* const gJavaLangIllegalArgumentException = "java/lang/IllegalArgumentException";
}}

View File

@@ -9,9 +9,6 @@
#include <memory>
#include <type_traits>
#include <fb/assert.h>
#include <fb/visibility.h>
#include "CoreClasses.h"
namespace facebook {
@@ -24,13 +21,45 @@ public:
virtual ~BaseHybridClass() {}
};
struct FBEXPORT HybridData : public JavaClass<HybridData> {
struct HybridData : public JavaClass<HybridData> {
constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/HybridData;";
void setNativePointer(std::unique_ptr<BaseHybridClass> new_value);
BaseHybridClass* getNativePointer();
static local_ref<HybridData> create();
};
class HybridDestructor : public JavaClass<HybridDestructor> {
public:
static auto constexpr kJavaDescriptor = "Lcom/facebook/jni/HybridData$Destructor;";
detail::BaseHybridClass* getNativePointer();
void setNativePointer(std::unique_ptr<detail::BaseHybridClass> new_value);
};
template<typename T>
detail::BaseHybridClass* getNativePointer(T t) {
return getHolder(t)->getNativePointer();
}
template<typename T>
void setNativePointer(T t, std::unique_ptr<detail::BaseHybridClass> new_value) {
getHolder(t)->setNativePointer(std::move(new_value));
}
template<typename T>
local_ref<HybridDestructor> getHolder(T t) {
static auto holderField = t->getClass()->template getField<HybridDestructor::javaobject>("mDestructor");
return t->getFieldValue(holderField);
}
// JavaClass for HybridClassBase
struct HybridClassBase : public JavaClass<HybridClassBase> {
constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/HybridClassBase;";
static bool isHybridClassBase(alias_ref<jclass> jclass) {
return HybridClassBase::javaClassStatic()->isAssignableFrom(jclass);
}
};
template <typename Base, typename Enabled = void>
struct HybridTraits {
// This static assert should actually always fail if we don't use one of the
@@ -65,7 +94,7 @@ struct HybridTraits<
// convert to HybridClass* from jhybridobject
template <typename T>
struct FBEXPORT Convert<
struct Convert<
T, typename std::enable_if<
std::is_base_of<BaseHybridClass, typename std::remove_pointer<T>::type>::value>::type> {
typedef typename std::remove_pointer<T>::type::jhybridobject jniType;
@@ -90,7 +119,7 @@ struct RefReprType<T, typename std::enable_if<std::is_base_of<BaseHybridClass, T
}
template <typename T, typename Base = detail::BaseHybridClass>
class FBEXPORT HybridClass : public detail::HybridTraits<Base>::CxxBase {
class HybridClass : public detail::HybridTraits<Base>::CxxBase {
public:
struct JavaPart : JavaClass<JavaPart, typename detail::HybridTraits<Base>::JavaBase> {
// At this point, T is incomplete, and so we cannot access
@@ -107,6 +136,7 @@ public:
T* cthis();
friend class HybridClass;
friend T;
};
using jhybridobject = typename JavaPart::javaobject;
@@ -136,7 +166,7 @@ protected:
static local_ref<detail::HybridData> makeHybridData(std::unique_ptr<T> cxxPart) {
auto hybridData = detail::HybridData::create();
hybridData->setNativePointer(std::move(cxxPart));
setNativePointer(hybridData, std::move(cxxPart));
return hybridData;
}
@@ -145,6 +175,11 @@ protected:
return makeHybridData(std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
}
template <typename... Args>
static void setCxxInstance(alias_ref<jhybridobject> o, Args&&... args) {
setNativePointer(o, std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
}
public:
// Factory method for creating a hybrid object where the arguments
// are used to initialize the C++ part directly without passing them
@@ -158,11 +193,23 @@ public:
// C++ object fails, or any JNI methods throw.
template <typename... Args>
static local_ref<JavaPart> newObjectCxxArgs(Args&&... args) {
auto hybridData = makeCxxInstance(std::forward<Args>(args)...);
return JavaPart::newInstance(hybridData);
static bool isHybrid = detail::HybridClassBase::isHybridClassBase(javaClassStatic());
auto cxxPart = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
local_ref<JavaPart> result;
if (isHybrid) {
result = JavaPart::newInstance();
setNativePointer(result, std::move(cxxPart));
}
else {
auto hybridData = makeHybridData(std::move(cxxPart));
result = JavaPart::newInstance(hybridData);
}
return result;
}
// TODO? Create reusable interface for Allocatable classes and use it to
// TODO? Create reusable interface for Allocatable classes and use it to
// strengthen type-checking (and possibly provide a default
// implementation of allocate().)
template <typename... Args>
@@ -194,17 +241,23 @@ public:
template <typename T, typename B>
inline T* HybridClass<T, B>::JavaPart::cthis() {
static auto field =
HybridClass<T, B>::JavaPart::javaClassStatic()->template getField<detail::HybridData::javaobject>("mHybridData");
auto hybridData = this->getFieldValue(field);
if (!hybridData) {
throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException");
detail::BaseHybridClass* result = 0;
static bool isHybrid = detail::HybridClassBase::isHybridClassBase(this->getClass());
if (isHybrid) {
result = getNativePointer(this);
} else {
static auto field =
HybridClass<T, B>::JavaPart::javaClassStatic()->template getField<detail::HybridData::javaobject>("mHybridData");
auto hybridData = this->getFieldValue(field);
if (!hybridData) {
throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException");
}
result = getNativePointer(hybridData);
}
// I'd like to use dynamic_cast here, but -fno-rtti is the default.
T* value = static_cast<T*>(hybridData->getNativePointer());
// This would require some serious programmer error.
FBASSERTMSGF(value != 0, "Incorrect C++ type in hybrid field");
return value;
return static_cast<T*>(result);
};
template <typename T, typename B>

View File

@@ -32,7 +32,7 @@ struct IteratorHelper : public JavaClass<IteratorHelper<E>> {
value_type next() {
static auto elementField =
JavaBase_::javaClassStatic()->template getField<jobject>("mElement");
return dynamic_ref_cast<E>(JavaBase_::getFieldValue(elementField));
return dynamic_ref_cast<JniType<E>>(JavaBase_::getFieldValue(elementField));
}
static void reset(value_type& v) {

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
#pragma once
#include "CoreClasses.h"
namespace facebook {
namespace jni {
/**
* Wrap Java's WeakReference instead of using JNI WeakGlobalRefs.
* A WeakGlobalRef can yield a strong reference even after the object has been
* finalized. See comment in the djinni library.
* https://github.com/dropbox/djinni/blob/master/support-lib/jni/djinni_support.hpp
*/
template<typename T = jobject>
class JWeakReference : public JavaClass<JWeakReference<T>> {
typedef JavaClass<JWeakReference<T>> JavaBase_;
public:
static constexpr const char* kJavaDescriptor = "Ljava/lang/ref/WeakReference;";
static local_ref<JWeakReference<T>> newInstance(alias_ref<T> object) {
return JavaBase_::newInstance(static_ref_cast<jobject>(object));
}
local_ref<T> get() const {
static const auto method = JavaBase_::javaClassStatic()->template getMethod<jobject()>("get");
return static_ref_cast<T>(method(JavaBase_::self()));
}
};
}
}

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
/** @file ALog.h
*
* Very simple (android only) logging. Define LOG_TAG to enable the macros.
*/
#pragma once
#ifdef __ANDROID__
#include <android/log.h>
namespace facebook {
namespace jni {
namespace log_ {
// the weird name of this namespace is to avoid a conflict with the
// function named log.
inline void loge(const char* tag, const char* msg) noexcept {
__android_log_write(ANDROID_LOG_ERROR, tag, msg);
}
template<typename... ARGS>
inline void loge(const char* tag, const char* msg, ARGS... args) noexcept {
__android_log_print(ANDROID_LOG_ERROR, tag, msg, args...);
}
inline void logf(const char* tag, const char* msg) noexcept {
__android_log_write(ANDROID_LOG_FATAL, tag, msg);
}
template<typename... ARGS>
inline void logf(const char* tag, const char* msg, ARGS... args) noexcept {
__android_log_print(ANDROID_LOG_FATAL, tag, msg, args...);
}
template<typename... ARGS>
[[noreturn]]
inline void logassert(const char* tag, const char* msg, ARGS... args) noexcept {
__android_log_assert(0, tag, msg, args...);
}
#ifdef LOG_TAG
# define FBJNI_LOGE(...) ::facebook::jni::log_::loge(LOG_TAG, __VA_ARGS__)
# define FBJNI_LOGF(...) ::facebook::jni::log_::logf(LOG_TAG, __VA_ARGS__)
# define FBJNI_ASSERT(cond) do { if (!(cond)) ::facebook::jni::log_::logassert(LOG_TAG, "%s", #cond); } while(0)
#else
# define FBJNI_LOGE(...) ::facebook::jni::log_::loge("log", __VA_ARGS__)
# define FBJNI_LOGF(...) ::facebook::jni::log_::logf("log", __VA_ARGS__)
# define FBJNI_ASSERT(cond) do { if (!(cond)) ::facebook::jni::log_::logassert("log", "%s", #cond); } while(0)
#endif
}}}
#else
#include <stdlib.h>
# define FBJNI_LOGE(...) ((void)0)
# define FBJNI_LOGF(...) (abort())
# define FBJNI_ASSERT(cond) ((void)0)
#endif

View File

@@ -14,10 +14,6 @@
#include "References.h"
#include "Boxed.h"
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#endif
namespace facebook {
namespace jni {
@@ -63,31 +59,10 @@ local_ref<JArrayClass<jobject>::javaobject> makeArgsArray(Args... args) {
return arr;
}
inline bool needsSlowPath(alias_ref<jobject> obj) {
#if defined(__ANDROID__)
// On Android 6.0, art crashes when attempting to call a function on a Proxy.
// So, when we detect that case we must use the safe, slow workaround. That is,
// we resolve the method id to the corresponding java.lang.reflect.Method object
// and make the call via it's invoke() method.
static auto android_sdk = ([] {
char sdk_version_str[PROP_VALUE_MAX];
__system_property_get("ro.build.version.sdk", sdk_version_str);
return atoi(sdk_version_str);
})();
static auto is_bad_android = android_sdk == 23;
if (!is_bad_android) return false;
static auto proxy_class = findClassStatic("java/lang/reflect/Proxy");
return obj->isInstanceOf(proxy_class);
#else
return false;
#endif
}
}
template<typename... Args>
inline void JMethod<void(Args...)>::operator()(alias_ref<jobject> self, Args... args) {
inline void JMethod<void(Args...)>::operator()(alias_ref<jobject> self, Args... args) const {
const auto env = Environment::current();
env->CallVoidMethod(
self.get(),
@@ -98,10 +73,10 @@ inline void JMethod<void(Args...)>::operator()(alias_ref<jobject> self, Args...
#pragma push_macro("DEFINE_PRIMITIVE_CALL")
#undef DEFINE_PRIMITIVE_CALL
#define DEFINE_PRIMITIVE_CALL(TYPE, METHOD, CLASS) \
#define DEFINE_PRIMITIVE_CALL(TYPE, METHOD) \
template<typename... Args> \
inline TYPE JMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, Args... args) { \
const auto env = internal::getEnv(); \
inline TYPE JMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, Args... args) const { \
const auto env = Environment::current(); \
auto result = env->Call ## METHOD ## Method( \
self.get(), \
getId(), \
@@ -110,14 +85,14 @@ inline TYPE JMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, Args...
return result; \
}
DEFINE_PRIMITIVE_CALL(jboolean, Boolean, JBoolean)
DEFINE_PRIMITIVE_CALL(jbyte, Byte, JByte)
DEFINE_PRIMITIVE_CALL(jchar, Char, JCharacter)
DEFINE_PRIMITIVE_CALL(jshort, Short, JShort)
DEFINE_PRIMITIVE_CALL(jint, Int, JInteger)
DEFINE_PRIMITIVE_CALL(jlong, Long, JLong)
DEFINE_PRIMITIVE_CALL(jfloat, Float, JFloat)
DEFINE_PRIMITIVE_CALL(jdouble, Double, JDouble)
DEFINE_PRIMITIVE_CALL(jboolean, Boolean)
DEFINE_PRIMITIVE_CALL(jbyte, Byte)
DEFINE_PRIMITIVE_CALL(jchar, Char)
DEFINE_PRIMITIVE_CALL(jshort, Short)
DEFINE_PRIMITIVE_CALL(jint, Int)
DEFINE_PRIMITIVE_CALL(jlong, Long)
DEFINE_PRIMITIVE_CALL(jfloat, Float)
DEFINE_PRIMITIVE_CALL(jdouble, Double)
#pragma pop_macro("DEFINE_PRIMITIVE_CALL")
/// JMethod specialization for references that wraps the return value in a @ref local_ref
@@ -132,13 +107,13 @@ class JMethod<R(Args...)> : public JMethodBase {
JMethod(const JMethod& other) noexcept = default;
/// Invoke a method and return a local reference wrapping the result
local_ref<JniRet> operator()(alias_ref<jobject> self, Args... args);
local_ref<JniRet> operator()(alias_ref<jobject> self, Args... args) const;
friend class JClass;
};
template<typename R, typename... Args>
inline auto JMethod<R(Args...)>::operator()(alias_ref<jobject> self, Args... args) -> local_ref<JniRet> {
inline auto JMethod<R(Args...)>::operator()(alias_ref<jobject> self, Args... args) const -> local_ref<JniRet> {
const auto env = Environment::current();
auto result = env->CallObjectMethod(
self.get(),
@@ -149,8 +124,8 @@ inline auto JMethod<R(Args...)>::operator()(alias_ref<jobject> self, Args... arg
}
template<typename... Args>
inline void JStaticMethod<void(Args...)>::operator()(alias_ref<jclass> cls, Args... args) {
const auto env = internal::getEnv();
inline void JStaticMethod<void(Args...)>::operator()(alias_ref<jclass> cls, Args... args) const {
const auto env = Environment::current();
env->CallStaticVoidMethod(
cls.get(),
getId(),
@@ -162,8 +137,8 @@ inline void JStaticMethod<void(Args...)>::operator()(alias_ref<jclass> cls, Args
#undef DEFINE_PRIMITIVE_STATIC_CALL
#define DEFINE_PRIMITIVE_STATIC_CALL(TYPE, METHOD) \
template<typename... Args> \
inline TYPE JStaticMethod<TYPE(Args...)>::operator()(alias_ref<jclass> cls, Args... args) { \
const auto env = internal::getEnv(); \
inline TYPE JStaticMethod<TYPE(Args...)>::operator()(alias_ref<jclass> cls, Args... args) const { \
const auto env = Environment::current(); \
auto result = env->CallStatic ## METHOD ## Method( \
cls.get(), \
getId(), \
@@ -194,8 +169,8 @@ class JStaticMethod<R(Args...)> : public JMethodBase {
JStaticMethod(const JStaticMethod& other) noexcept = default;
/// Invoke a method and return a local reference wrapping the result
local_ref<JniRet> operator()(alias_ref<jclass> cls, Args... args) {
const auto env = internal::getEnv();
local_ref<JniRet> operator()(alias_ref<jclass> cls, Args... args) const {
const auto env = Environment::current();
auto result = env->CallStaticObjectMethod(
cls.get(),
getId(),
@@ -209,8 +184,8 @@ class JStaticMethod<R(Args...)> : public JMethodBase {
template<typename... Args>
inline void
JNonvirtualMethod<void(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) {
const auto env = internal::getEnv();
JNonvirtualMethod<void(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const {
const auto env = Environment::current();
env->CallNonvirtualVoidMethod(
self.get(),
cls.get(),
@@ -224,8 +199,8 @@ JNonvirtualMethod<void(Args...)>::operator()(alias_ref<jobject> self, alias_ref<
#define DEFINE_PRIMITIVE_NON_VIRTUAL_CALL(TYPE, METHOD) \
template<typename... Args> \
inline TYPE \
JNonvirtualMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) { \
const auto env = internal::getEnv(); \
JNonvirtualMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const { \
const auto env = Environment::current(); \
auto result = env->CallNonvirtual ## METHOD ## Method( \
self.get(), \
cls.get(), \
@@ -256,8 +231,8 @@ class JNonvirtualMethod<R(Args...)> : public JMethodBase {
JNonvirtualMethod(const JNonvirtualMethod& other) noexcept = default;
/// Invoke a method and return a local reference wrapping the result
local_ref<JniRet> operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args){
const auto env = internal::getEnv();
local_ref<JniRet> operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const {
const auto env = Environment::current();
auto result = env->CallNonvirtualObjectMethod(
self.get(),
cls.get(),
@@ -306,13 +281,13 @@ inline jfieldID JField<T>::getId() const noexcept {
#define DEFINE_FIELD_PRIMITIVE_GET_SET(TYPE, METHOD) \
template<> \
inline TYPE JField<TYPE>::get(jobject object) const noexcept { \
const auto env = internal::getEnv(); \
const auto env = Environment::current(); \
return env->Get ## METHOD ## Field(object, field_id_); \
} \
\
template<> \
inline void JField<TYPE>::set(jobject object, TYPE value) noexcept { \
const auto env = internal::getEnv(); \
const auto env = Environment::current(); \
env->Set ## METHOD ## Field(object, field_id_, value); \
}
@@ -328,12 +303,12 @@ DEFINE_FIELD_PRIMITIVE_GET_SET(jdouble, Double)
template<typename T>
inline T JField<T>::get(jobject object) const noexcept {
return static_cast<T>(internal::getEnv()->GetObjectField(object, field_id_));
return static_cast<T>(Environment::current()->GetObjectField(object, field_id_));
}
template<typename T>
inline void JField<T>::set(jobject object, T value) noexcept {
internal::getEnv()->SetObjectField(object, field_id_, static_cast<jobject>(value));
Environment::current()->SetObjectField(object, field_id_, static_cast<jobject>(value));
}
// JStaticField<T> /////////////////////////////////////////////////////////////////////////////////
@@ -358,13 +333,13 @@ inline jfieldID JStaticField<T>::getId() const noexcept {
#define DEFINE_STATIC_FIELD_PRIMITIVE_GET_SET(TYPE, METHOD) \
template<> \
inline TYPE JStaticField<TYPE>::get(jclass jcls) const noexcept { \
const auto env = internal::getEnv(); \
const auto env = Environment::current(); \
return env->GetStatic ## METHOD ## Field(jcls, field_id_); \
} \
\
template<> \
inline void JStaticField<TYPE>::set(jclass jcls, TYPE value) noexcept { \
const auto env = internal::getEnv(); \
const auto env = Environment::current(); \
env->SetStatic ## METHOD ## Field(jcls, field_id_, value); \
}
@@ -380,13 +355,13 @@ DEFINE_STATIC_FIELD_PRIMITIVE_GET_SET(jdouble, Double)
template<typename T>
inline T JStaticField<T>::get(jclass jcls) const noexcept {
const auto env = internal::getEnv();
const auto env = Environment::current();
return static_cast<T>(env->GetStaticObjectField(jcls, field_id_));
}
template<typename T>
inline void JStaticField<T>::set(jclass jcls, T value) noexcept {
internal::getEnv()->SetStaticObjectField(jcls, field_id_, value);
Environment::current()->SetStaticObjectField(jcls, field_id_, value);
}

Some files were not shown because too many files have changed in this diff Show More