From 2ce219ef429663069cc8bbe6474191ddc1fb9a22 Mon Sep 17 00:00:00 2001 From: Oleksii Dykan Date: Mon, 18 Jun 2018 09:11:16 -0700 Subject: [PATCH 001/189] Fix componentkit generator (#785) Summary: Fixes some inconsistencies in yoga playground Closes https://github.com/facebook/yoga/pull/785 Reviewed By: danielbuechele Differential Revision: D8480993 Pulled By: alickbass fbshipit-source-id: 395d77bae28462d3e03d666287bdc64137b84c68 --- website/src/components/Playground/CodeComponentKit.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/src/components/Playground/CodeComponentKit.js b/website/src/components/Playground/CodeComponentKit.js index fea711af..9dd71a2f 100644 --- a/website/src/components/Playground/CodeComponentKit.js +++ b/website/src/components/Playground/CodeComponentKit.js @@ -137,9 +137,9 @@ function getLayoutCode( )}\n${indent}\t},`, ), ); - lines.push(indent + `}]${isRoot ? ';' : ''}`); + lines.push(indent + `}]${isRoot ? ';' : ','}`); } else { - lines[lines.length - 1] += ']'; + lines[lines.length - 1] += '],'; CKFlexboxComponentChild.forEach(key => { let line = renderKey(node, key, indent); if (line) { @@ -165,7 +165,7 @@ function renderKey(node: Yoga$Node, key: string, indent: string): ?string { ); } - ['top', 'left', 'right', 'bottom'].forEach(pKey => { + ['top', 'start', 'end', 'bottom'].forEach(pKey => { if (node[key][pKey]) { lines.push(indent + `\t.${pKey} = ${getValue(node[key][pKey])},`); } From cdb1ee21a04fcf587843df651d95b523a7b896a8 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 22 Jun 2018 11:29:05 -0700 Subject: [PATCH 002/189] Clean-up parent / owner reference of children during clonning Summary: This diff cleans up the parent / owner references for children of ReactShadowNode / YogaNode during cloning. The reason of this behavior is to avoid retaining every generation of trees during cloning. This fixes a memory leak detected when running the ProgressBarExample.android.js in catalyst app Reviewed By: fkgozali Differential Revision: D8019894 fbshipit-source-id: b0d38f0c836ffec534f64fa1adbd7511ecf3473d --- java/com/facebook/yoga/YogaNode.java | 12 +++++++++--- yoga/Yoga.cpp | 12 ++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 90caf8f8..f8b895b1 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -1,8 +1,9 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; @@ -185,6 +186,11 @@ public class YogaNode implements Cloneable { clonedYogaNode.mOwner = null; clonedYogaNode.mChildren = mChildren != null ? (List) ((ArrayList) mChildren).clone() : null; + if (clonedYogaNode.mChildren != null) { + for (YogaNode child : clonedYogaNode.mChildren) { + child.mOwner = null; + } + } return clonedYogaNode; } catch (CloneNotSupportedException ex) { // This class implements Cloneable, this should not happen diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index c6a8ffd2..3c83ce08 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1,8 +1,9 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ #include "Yoga.h" @@ -243,6 +244,9 @@ YGNodeRef YGNodeClone(YGNodeRef oldNode) { oldNode->getConfig(), node != nullptr, "Could not allocate memory for node"); + for (auto &item : oldNode->getChildren()) { + item->setOwner(nullptr); + } gNodeInstanceCount++; node->setOwner(nullptr); return node; From a67c55532076e64f78d1897c39e0f91e709dbc1e Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sat, 23 Jun 2018 18:23:21 -0700 Subject: [PATCH 003/189] Fix deprecated glob usage. Summary: https://our.intern.facebook.com/intern/wiki/Buck/python-to-skylark/ Differential Revision: D8595731 fbshipit-source-id: 0e3046a7fd2a25e9b13462713ae9a008ad546770 --- BUCK | 3 +- YogaKit/BUCK | 3 +- benchmark/BUCK | 3 +- lib/fb/BUCK | 3 +- lib/gtest/BUCK | 3 +- yoga_defs.bzl | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 10 deletions(-) diff --git a/BUCK b/BUCK index fd87a83b..4b809f69 100644 --- a/BUCK +++ b/BUCK @@ -2,8 +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("//:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep") +load("//:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "subdir_glob", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep") GMOCK_OVERRIDE_FLAGS = [ # gmock does not mark mocked methods as override, ignore the warnings in tests diff --git a/YogaKit/BUCK b/YogaKit/BUCK index 14198edb..9675d049 100644 --- a/YogaKit/BUCK +++ b/YogaKit/BUCK @@ -2,8 +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("//:yoga_defs.bzl", "yoga_apple_library", "yoga_apple_test", "yoga_dep") +load("//:yoga_defs.bzl", "subdir_glob", "yoga_apple_library", "yoga_apple_test", "yoga_dep") COMPILER_FLAGS = [ "-fobjc-arc", diff --git a/benchmark/BUCK b/benchmark/BUCK index 2b30af78..82864373 100644 --- a/benchmark/BUCK +++ b/benchmark/BUCK @@ -2,8 +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("//:yoga_defs.bzl", "yoga_cxx_binary", "yoga_dep") +load("//:yoga_defs.bzl", "subdir_glob", "yoga_cxx_binary", "yoga_dep") yoga_cxx_binary( name = "benchmark", diff --git a/lib/fb/BUCK b/lib/fb/BUCK index e72c3cb6..cc2502ec 100644 --- a/lib/fb/BUCK +++ b/lib/fb/BUCK @@ -2,8 +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("//:yoga_defs.bzl", "ANDROID", "FBJNI_JAVA_TARGET", "JNI_TARGET", "YOGA_ROOTS", "yoga_cxx_library", "yoga_prebuilt_cxx_library") +load("//:yoga_defs.bzl", "ANDROID", "FBJNI_JAVA_TARGET", "JNI_TARGET", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library", "yoga_prebuilt_cxx_library") yoga_prebuilt_cxx_library( name = "ndklog", diff --git a/lib/gtest/BUCK b/lib/gtest/BUCK index 167d70eb..e489c69c 100644 --- a/lib/gtest/BUCK +++ b/lib/gtest/BUCK @@ -2,8 +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("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_cxx_library") +load("//:yoga_defs.bzl", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library") COMPILER_FLAGS = [ "-std=c++11", diff --git a/yoga_defs.bzl b/yoga_defs.bzl index c6d7120a..9f33a825 100644 --- a/yoga_defs.bzl +++ b/yoga_defs.bzl @@ -59,6 +59,87 @@ LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [ "-fPIC", ] +def _paths_join(path, *others): + """Joins one or more path components.""" + result = path + + for p in others: + if p.startswith("/"): # absolute + result = p + elif not result or result.endswith("/"): + result += p + else: + result += "/" + p + + return result + +def subdir_glob(glob_specs, exclude = None, prefix = ""): + """Returns a dict of sub-directory relative paths to full paths. + + The subdir_glob() function is useful for defining header maps for C/C++ + libraries which should be relative the given sub-directory. + Given a list of tuples, the form of (relative-sub-directory, glob-pattern), + it returns a dict of sub-directory relative paths to full paths. + + Please refer to native.glob() for explanations and examples of the pattern. + + Args: + glob_specs: The array of tuples in form of + (relative-sub-directory, glob-pattern inside relative-sub-directory). + type: List[Tuple[str, str]] + exclude: A list of patterns to identify files that should be removed + from the set specified by the first argument. Defaults to []. + type: Optional[List[str]] + prefix: If is not None, prepends it to each key in the dictionary. + Defaults to None. + type: Optional[str] + + Returns: + A dict of sub-directory relative paths to full paths. + """ + if exclude == None: + exclude = [] + + results = [] + + for dirpath, glob_pattern in glob_specs: + results.append( + _single_subdir_glob(dirpath, glob_pattern, exclude, prefix), + ) + + return _merge_maps(*results) + +def _merge_maps(*file_maps): + result = {} + for file_map in file_maps: + for key in file_map: + if key in result and result[key] != file_map[key]: + fail( + "Conflicting files in file search paths. " + + "\"%s\" maps to both \"%s\" and \"%s\"." % + (key, result[key], file_map[key]), + ) + + result[key] = file_map[key] + + return result + +def _single_subdir_glob(dirpath, glob_pattern, exclude = None, prefix = None): + if exclude == None: + exclude = [] + results = {} + files = native.glob([_paths_join(dirpath, glob_pattern)], exclude = exclude) + for f in files: + if dirpath: + key = f[len(dirpath) + 1:] + else: + key = f + if prefix: + key = _paths_join(prefix, key) + results[key] = f + + return results + def yoga_dep(dep): return "//" + dep From 46c96ee2cbc6260a1ef9398dd750973e427b9984 Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Tue, 26 Jun 2018 04:57:04 -0700 Subject: [PATCH 004/189] Upgrade fbjni Summary: Sync fbjni with `libaries/fbjni`. This includes a hack to fix a deadlock we found for cmake-debug variants only. This still gets us back in sync with other fbjni consumers which is going to save us trouble in the future if Yoga ever wants to make use of a newer feature. Manual changes made in addition to the hand-crafted CMakeLists and cxx buck rules: - `jni::isObjectRefType` has SDK lookup disabled. - `fbjni/` path is changed back to `fb/` to retain compatibility with Yoga. Reviewed By: priteshrnandgaonkar Differential Revision: D8531991 fbshipit-source-id: 776f519e2e5f9bea37f55990348f7ed81c4860b4 --- java/jni/YGJNI.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 69cbb381..2bc0ee8b 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include #include #include From 77ea79490f245e67c1b255b155b6ed66ee2ca05f Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Wed, 27 Jun 2018 03:22:49 -0700 Subject: [PATCH 005/189] Upgrade Prettier to 1.13.6 on fbsource Reviewed By: zertosh Differential Revision: D8638504 fbshipit-source-id: c6991b2e884e14868ddc1d9047a78191219d673f --- website/package.json | 2 +- website/yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/website/package.json b/website/package.json index ef18bb57..e112591c 100644 --- a/website/package.json +++ b/website/package.json @@ -31,6 +31,6 @@ "develop": "gatsby develop" }, "devDependencies": { - "prettier": "1.13.4" + "prettier": "1.13.6" } } diff --git a/website/yarn.lock b/website/yarn.lock index 31fa92be..68a93f6c 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -6862,9 +6862,9 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@1.13.4: - version "1.13.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.4.tgz#31bbae6990f13b1093187c731766a14036fa72e6" +prettier@1.13.6: + version "1.13.6" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.6.tgz#00ae0b777ad92f81a9e7a1df2f0470b6dab0cb44" pretty-bytes@^4.0.2: version "4.0.2" From f4d29e6f11486540b9efddf0d7cd16c903de7132 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Thu, 28 Jun 2018 22:38:42 -0700 Subject: [PATCH 006/189] Avoid cleaning up Owner of YGNode during clonning Summary: This diff refactors the cloning mechanism for YogaNode used from Fabric UI renderer and RN iOS graphs. Previously, we were cleaning the owner of the child's cloned node inside the C++ implementation of YogaNode. This was a mistake because this modified the last commited YogaTree, causing side effect in RN iOS graphs. Reviewed By: shergin Differential Revision: D8672627 fbshipit-source-id: c9902d00690e0361fd58aed84b506c42258bd995 --- java/com/facebook/yoga/YogaNode.java | 10 ++++++++++ java/jni/YGJNI.cpp | 11 +++++++++++ yoga/Yoga.cpp | 3 --- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index f8b895b1..1565d4bb 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -175,6 +175,8 @@ public class YogaNode implements Cloneable { jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i); } + private native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); + private native long jni_YGNodeClone(long nativePointer, Object newNode); @Override @@ -182,6 +184,14 @@ public class YogaNode implements Cloneable { try { YogaNode clonedYogaNode = (YogaNode) super.clone(); long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); + + if (mChildren != null) { + for (YogaNode child : mChildren) { + child.jni_YGNodeSetOwner(child.mNativePointer, 0); + child.mOwner = null; + } + } + clonedYogaNode.mNativePointer = clonedNativePointer; clonedYogaNode.mOwner = null; clonedYogaNode.mChildren = diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 2bc0ee8b..5649ef7e 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -268,6 +268,16 @@ jlong jni_YGNodeNewWithConfig(alias_ref thiz, jlong configPointer) { return reinterpret_cast(node); } +void jni_YGNodeSetOwner( + alias_ref thiz, + jlong nativePointer, + jlong newOwnerNativePointer) { + const YGNodeRef node = _jlong2YGNodeRef(nativePointer); + const YGNodeRef newOwnerNode = _jlong2YGNodeRef(newOwnerNativePointer); + + node->setOwner(newOwnerNode); +} + jlong jni_YGNodeClone( alias_ref thiz, jlong nativePointer, @@ -667,6 +677,7 @@ jint JNI_OnLoad(JavaVM *vm, void *) { YGMakeNativeMethod(jni_YGNodeGetInstanceCount), YGMakeNativeMethod(jni_YGNodePrint), YGMakeNativeMethod(jni_YGNodeClone), + YGMakeNativeMethod(jni_YGNodeSetOwner), }); registerNatives( "com/facebook/yoga/YogaConfig", diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 3c83ce08..e5d1aabb 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -244,9 +244,6 @@ YGNodeRef YGNodeClone(YGNodeRef oldNode) { oldNode->getConfig(), node != nullptr, "Could not allocate memory for node"); - for (auto &item : oldNode->getChildren()) { - item->setOwner(nullptr); - } gNodeInstanceCount++; node->setOwner(nullptr); return node; From 7c4319181bc86442019321cbf9246dd284d654fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=BCchele?= Date: Tue, 3 Jul 2018 10:05:28 -0700 Subject: [PATCH 007/189] fixing landing page layout on server render Summary: On the first render the landing page was missing a CSS class. This ls probably related to https://github.com/gatsbyjs/gatsby/issues/5136 It is fixed by wrapping the page in a
Reviewed By: priteshrnandgaonkar Differential Revision: D8660801 fbshipit-source-id: dd1ac4145831f2556e2c7ceeaddb2a423447f833 --- website/package.json | 1 + website/src/components/Playground/index.js | 1 + website/src/pages/index.js | 18 ++++++++++-------- website/yarn.lock | 4 ++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/website/package.json b/website/package.json index e112591c..33ba8cd0 100644 --- a/website/package.json +++ b/website/package.json @@ -6,6 +6,7 @@ "dependencies": { "antd": "^3.2.0", "atob": "^2.0.3", + "btoa": "^1.2.1", "gatsby": "^1.9.158", "gatsby-link": "^1.6.34", "gatsby-plugin-antd": "^1.0.10", diff --git a/website/src/components/Playground/index.js b/website/src/components/Playground/index.js index 26e1734e..ec8c4cf8 100644 --- a/website/src/components/Playground/index.js +++ b/website/src/components/Playground/index.js @@ -19,6 +19,7 @@ import PositionRecord from './PositionRecord'; import LayoutRecord from './LayoutRecord'; import Sidebar from './Sidebar'; import {Row, Col, Button} from 'antd'; +import btoa from 'btoa'; import type {LayoutRecordT} from './LayoutRecord'; import type {Yoga$Direction} from 'yoga-layout'; import './index.css'; diff --git a/website/src/pages/index.js b/website/src/pages/index.js index 334bcaa5..c8b6287a 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -183,12 +183,14 @@ const AboutSectionTwo = () => ( ); export default () => ( - - - - -
- -
- +
+ + + + +
+ +
+ +
); diff --git a/website/yarn.lock b/website/yarn.lock index 68a93f6c..4f7f2c84 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -1578,6 +1578,10 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + buffer-alloc-unsafe@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz#ffe1f67551dd055737de253337bfe853dfab1a6a" From 2eda444bbf246ec3c3b12f687e9c11080af8d100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=BCchele?= Date: Thu, 5 Jul 2018 08:40:52 -0700 Subject: [PATCH 008/189] update dependencies Summary: Updates all dependencies of the website to their latest version. This is made due to CVE-2018-3728 and a vunerable version of `hoek` used in s transitive dependency of the website. This updates `hoek` to v 4.2.1 which is not affected. allow-large-files Reviewed By: astreet Differential Revision: D8734272 fbshipit-source-id: 3e96ea5890190f7d7b83cc4c18121fc925411f69 --- website/package-lock.json | 12381 ------------------------------------ website/package.json | 28 +- website/yarn.lock | 2577 ++++---- 3 files changed, 1401 insertions(+), 13585 deletions(-) delete mode 100644 website/package-lock.json diff --git a/website/package-lock.json b/website/package-lock.json deleted file mode 100644 index a15e0074..00000000 --- a/website/package-lock.json +++ /dev/null @@ -1,12381 +0,0 @@ -{ - "name": "gatsby-starter-default", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@zeit/check-updates": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@zeit/check-updates/-/check-updates-1.0.5.tgz", - "integrity": "sha512-QIfayr2IgDzqDiTL2PaOc1aZzVJ0WAwl3Nh1bfnWZDfNIuVq2zLYGVOkr+Mb8VvvLR8rOeyU3zKjPeXNbRVI1A==", - "requires": { - "chalk": "2.3.0", - "ms": "2.1.1", - "update-notifier": "2.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" - }, - "address": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", - "integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==" - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, - "ansi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" - }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "requires": { - "string-width": "2.1.1" - } - }, - "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "any-promise": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-0.1.0.tgz", - "integrity": "sha1-gwtoCqflbzNFHUsEnzvYBESY7ic=" - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" - } - }, - "arch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.0.tgz", - "integrity": "sha1-NhOqRhSQZLPB8GB5Gb8dR4boKIk=" - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.3" - } - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "requires": { - "sprintf-js": "1.0.3" - } - }, - "args": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/args/-/args-3.0.8.tgz", - "integrity": "sha512-yZ9pTP1UzoR04R2iusf2H3UG70O7mo55O5DjOS/MPKMTvxAFZenVCgi+JP8Q/dI+18qiM/m4r8En9j5/WlsBjQ==", - "requires": { - "camelcase": "4.1.0", - "chalk": "2.1.0", - "mri": "1.1.0", - "pkginfo": "0.4.1", - "string-similarity": "1.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "requires": { - "arr-flatten": "1.1.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "optional": true - }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "optional": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "asn1.js": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", - "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", - "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "requires": { - "util": "0.10.3" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "requires": { - "lodash": "4.17.4" - } - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=" - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000793", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "requires": { - "caniuse-db": "1.0.30000793", - "electron-to-chromium": "1.3.31" - } - } - } - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.4", - "source-map": "0.5.7", - "trim-right": "1.0.1" - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "esutils": "2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.4" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-loader": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.4.1.tgz", - "integrity": "sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo=", - "requires": { - "find-cache-dir": "0.1.1", - "loader-utils": "0.2.17", - "mkdirp": "0.5.1", - "object-assign": "4.1.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-add-module-exports": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", - "integrity": "sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=" - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" - }, - "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" - }, - "babel-plugin-syntax-do-expressions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=" - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" - }, - "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" - }, - "babel-plugin-syntax-function-bind": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=" - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" - }, - "babel-plugin-transform-amd-system-wrapper": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-amd-system-wrapper/-/babel-plugin-transform-amd-system-wrapper-0.3.7.tgz", - "integrity": "sha1-Uhx4LTVkRJHJeepoPopeHK/wukI=", - "optional": true, - "requires": { - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-cjs-system-wrapper": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-cjs-system-wrapper/-/babel-plugin-transform-cjs-system-wrapper-0.6.2.tgz", - "integrity": "sha1-vXSUd1KJQk/0k7btRV3klb1xuh0=", - "optional": true, - "requires": { - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "requires": { - "babel-plugin-syntax-class-constructor-call": "6.18.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-do-expressions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "requires": { - "babel-plugin-syntax-do-expressions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" - } - }, - "babel-plugin-transform-es3-member-expression-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", - "integrity": "sha1-cz00RPPsxBvvjtGmpOCWV7iWnrs=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es3-property-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz", - "integrity": "sha1-sgeNWELiKr9A9z6M3pzTcRq9V1g=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "requires": { - "babel-plugin-syntax-export-extensions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-function-bind": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "requires": { - "babel-plugin-syntax-function-bind": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-global-system-wrapper": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-global-system-wrapper/-/babel-plugin-transform-global-system-wrapper-0.3.4.tgz", - "integrity": "sha1-lI3X0p/CFEfjm9NEfy3rx/L3Oqw=", - "optional": true, - "requires": { - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-object-assign": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "requires": { - "babel-helper-builder-react-jsx": "6.26.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "requires": { - "regenerator-transform": "0.10.1" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-system-register": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-system-register/-/babel-plugin-transform-system-register-0.0.1.tgz", - "integrity": "sha1-nf9AOQwnY6xRjwsq18XqT2WlviU=", - "optional": true - }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "requires": { - "babel-runtime": "6.26.0", - "core-js": "2.5.1", - "regenerator-runtime": "0.10.5" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" - } - } - }, - "babel-preset-env": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "2.11.3", - "invariant": "2.2.2", - "semver": "5.5.0" - } - }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0" - } - }, - "babel-preset-fbjs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-2.1.4.tgz", - "integrity": "sha512-6XVQwlO26V5/0P9s2Eje8Epqkv/ihaMJ798+W98ktOA8fCn2IFM6wEi7CDW3fTbKFZ/8fDGvGZH01B6GSuNiWA==", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-plugin-syntax-flow": "6.18.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es3-member-expression-literals": "6.22.0", - "babel-plugin-transform-es3-property-literals": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-self": "6.22.0", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-preset-flow": "6.23.0" - } - }, - "babel-preset-stage-0": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", - "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "requires": { - "babel-plugin-transform-do-expressions": "6.22.0", - "babel-plugin-transform-function-bind": "6.22.0", - "babel-preset-stage-1": "6.24.1" - } - }, - "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "requires": { - "babel-plugin-transform-class-constructor-call": "6.24.1", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-preset-stage-2": "6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.26.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.1", - "home-or-tmp": "2.0.0", - "lodash": "4.17.4", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.0", - "pascalcase": "0.1.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "base-64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", - "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=" - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==" - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" - }, - "basename": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/basename/-/basename-0.1.2.tgz", - "integrity": "sha1-1gOb75OYYxYMeASMztPF5/iMsmE=" - }, - "bash-glob": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bash-glob/-/bash-glob-1.0.2.tgz", - "integrity": "sha512-E0TTxH9T/tklSXt5R5X0zwxjW56su2VIE+sAruXbd8AtMjYZxtvioybVdptbRk0/0Nvdz0TVVShKhN9sH5dMpg==", - "requires": { - "async-each": "1.0.1", - "bash-path": "1.0.3", - "component-emitter": "1.2.1", - "cross-spawn": "5.1.0", - "extend-shallow": "2.0.1", - "is-extglob": "2.1.1", - "is-glob": "4.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "bash-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bash-path/-/bash-path-1.0.3.tgz", - "integrity": "sha512-mGrYvOa6yTY/qNCiZkPFJqWmODK68y6kmVRAJ1NNbWlNoJrUrsFxu7FU2EKg7gbrer6ttrKkF2s/E/lhRy7/OA==", - "requires": { - "arr-union": "3.1.0", - "is-windows": "1.0.1" - } - }, - "basic-auth": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", - "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } - }, - "better-queue": { - "version": "3.8.6", - "resolved": "https://registry.npmjs.org/better-queue/-/better-queue-3.8.6.tgz", - "integrity": "sha1-cyIL36tAOSTP+nSXIg3Th6u3OmM=", - "requires": { - "better-queue-memory": "1.0.2", - "node-eta": "0.9.0", - "uuid": "3.2.1" - } - }, - "better-queue-memory": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-queue-memory/-/better-queue-memory-1.0.2.tgz", - "integrity": "sha1-qm0WmqHQzHdAkYXLnLXH3CUbzUE=" - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" - }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" - }, - "bl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", - "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", - "requires": { - "readable-stream": "2.3.3" - } - }, - "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.15" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.2.0" - } - }, - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "requires": { - "ansi-align": "2.0.0", - "camelcase": "4.1.0", - "chalk": "2.3.0", - "cli-boxes": "1.0.0", - "string-width": "2.1.1", - "term-size": "1.2.0", - "widest-line": "2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browserify-aes": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", - "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "browserify-cipher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "requires": { - "browserify-aes": "1.1.1", - "browserify-des": "1.0.0", - "evp_bytestokey": "1.0.3" - } - }, - "browserify-des": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "requires": { - "pako": "1.0.6" - } - }, - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "requires": { - "caniuse-lite": "1.0.30000792", - "electron-to-chromium": "1.3.31" - } - }, - "bser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", - "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", - "requires": { - "node-int64": "0.4.0" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "requires": { - "base64-js": "1.2.1", - "ieee754": "1.1.8", - "isarray": "1.0.0" - } - }, - "buffer-alloc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", - "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", - "requires": { - "buffer-alloc-unsafe": "0.1.1", - "buffer-fill": "0.1.0" - } - }, - "buffer-alloc-unsafe": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", - "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=" - }, - "buffer-fill": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.0.tgz", - "integrity": "sha1-ypRw6NTRuXf9dUP04qtqfclRAag=" - }, - "buffer-peek-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-peek-stream/-/buffer-peek-stream-1.0.1.tgz", - "integrity": "sha1-U7R1cKE0d4fFutTKLKMCH52LPP0=", - "optional": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" - }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000793", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "requires": { - "caniuse-db": "1.0.30000793", - "electron-to-chromium": "1.3.31" - } - } - } - }, - "caniuse-db": { - "version": "1.0.30000793", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000793.tgz", - "integrity": "sha1-PADGbkI6ehkHx92Wdpp4sq+opy4=" - }, - "caniuse-lite": { - "version": "1.0.30000792", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz", - "integrity": "sha1-0M6pgfgRjzlhRxr7tDyaHlu/AzI=" - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - }, - "dependencies": { - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" - } - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" - }, - "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", - "lodash.assignin": "4.2.0", - "lodash.bind": "4.2.1", - "lodash.defaults": "4.2.0", - "lodash.filter": "4.6.0", - "lodash.flatten": "4.4.0", - "lodash.foreach": "4.5.0", - "lodash.map": "4.6.0", - "lodash.merge": "4.6.0", - "lodash.pick": "4.4.0", - "lodash.reduce": "4.6.0", - "lodash.reject": "4.6.0", - "lodash.some": "4.6.0" - }, - "dependencies": { - "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "requires": { - "domelementtype": "1.3.0" - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.5.1", - "entities": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.3.3" - } - } - } - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" - } - }, - "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" - }, - "chunk-manifest-webpack-plugin": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chunk-manifest-webpack-plugin/-/chunk-manifest-webpack-plugin-0.1.0.tgz", - "integrity": "sha1-YThIj8Id2rTM+3wcEdUbuAqUMYY=", - "requires": { - "webpack-core": "0.4.8" - } - }, - "ci-info": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz", - "integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==" - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", - "requires": { - "chalk": "1.1.3" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, - "clipboardy": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", - "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", - "requires": { - "arch": "2.1.0", - "execa": "0.8.0" - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=" - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "requires": { - "q": "1.5.1" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "requires": { - "clone": "1.0.3", - "color-convert": "1.9.1", - "color-string": "0.3.0" - } - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "requires": { - "color-name": "1.1.3" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "requires": { - "color": "0.11.4", - "css-color-names": "0.0.4", - "has": "1.0.1" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "common-tags": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz", - "integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, - "compressible": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", - "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", - "requires": { - "mime-db": "1.30.0" - } - }, - "compression": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz", - "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", - "requires": { - "accepts": "1.3.4", - "bytes": "3.0.0", - "compressible": "2.0.12", - "debug": "2.6.9", - "on-headers": "1.0.1", - "safe-buffer": "5.1.1", - "vary": "1.1.2" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "configstore": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", - "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", - "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.1.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" - } - }, - "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=" - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "requires": { - "date-now": "0.1.4" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "convert-hrtime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-2.0.0.tgz", - "integrity": "sha1-Gb+yyRYvnhHC8Ewsed4rfoCVxic=" - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copyfiles": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-1.2.0.tgz", - "integrity": "sha1-qNo6xBqiIgrim9PFi2mEKU8sWTw=", - "requires": { - "glob": "7.1.2", - "ltcdr": "2.2.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "noms": "0.0.0", - "through2": "2.0.3" - } - }, - "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" - } - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "requires": { - "capture-stack-trace": "1.0.0" - } - }, - "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "sha.js": "2.4.9" - } - }, - "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.9" - } - }, - "create-react-class": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.2.tgz", - "integrity": "sha1-zx7RXxKq1/FO9fLf4F5sQvke8Co=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "cross-env": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-3.2.4.tgz", - "integrity": "sha1-ngWF8neGTtQhznVvgamA/w1piro=", - "requires": { - "cross-spawn": "5.1.0", - "is-windows": "1.0.1" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.2.0" - } - } - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "1.0.0", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.0", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "diffie-hellman": "5.0.2", - "inherits": "2.0.3", - "pbkdf2": "3.0.14", - "public-encrypt": "4.0.0", - "randombytes": "2.0.6", - "randomfill": "1.0.3" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" - }, - "css-color-function": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz", - "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=", - "requires": { - "balanced-match": "0.1.0", - "color": "0.11.4", - "debug": "3.1.0", - "rgb": "0.1.0" - }, - "dependencies": { - "balanced-match": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz", - "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" - }, - "css-loader": { - "version": "0.26.4", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.26.4.tgz", - "integrity": "sha1-th6eMNuUMD5v/IkvEOzQmtAlof0=", - "requires": { - "babel-code-frame": "6.26.0", - "css-selector-tokenizer": "0.7.0", - "cssnano": "3.10.0", - "loader-utils": "1.1.0", - "lodash.camelcase": "4.3.0", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-modules-extract-imports": "1.1.0", - "postcss-modules-local-by-default": "1.2.0", - "postcss-modules-scope": "1.1.0", - "postcss-modules-values": "1.3.0", - "source-list-map": "0.1.8" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - } - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1", - "regexpu-core": "1.0.0" - }, - "dependencies": { - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - } - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=" - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" - }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "requires": { - "clap": "1.2.3", - "source-map": "0.5.7" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "1.0.2" - } - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "0.10.38" - } - }, - "dargs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "data-uri-to-buffer": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.4.tgz", - "integrity": "sha1-RuE6udqOMJdFyNAc5UchPr2y/j8=", - "optional": true - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, - "death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" - }, - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "1.0.2" - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "requires": { - "globby": "6.1.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "p-map": "1.2.0", - "pify": "3.0.0", - "rimraf": "2.6.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "optional": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "2.0.1" - } - }, - "detect-port": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.2.2.tgz", - "integrity": "sha512-06H99JMCwgbYbA+codm97aBhFLAjABftetp+v+Z88Pvvlkawp2N+1bP/9J24+mihrvk9yBvUYTyIj3NixG1CsA==", - "requires": { - "address": "1.0.3", - "debug": "2.6.9" - } - }, - "diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" - } - }, - "dom-converter": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", - "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", - "requires": { - "utila": "0.3.3" - }, - "dependencies": { - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=" - } - } - }, - "dom-helpers": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz", - "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg==" - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" - } - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" - }, - "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=" - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" - }, - "domhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", - "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", - "requires": { - "domelementtype": "1.3.0" - } - }, - "domready": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/domready/-/domready-1.0.8.tgz", - "integrity": "sha1-kfJS5Ze2Wvd+dFriTdAYXV4m1Yw=" - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "requires": { - "is-obj": "1.0.1" - } - }, - "dotenv": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", - "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "electron-to-chromium": { - "version": "1.3.31", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz", - "integrity": "sha512-XE4CLbswkZgZFn34cKFy1xaX+F5LHxeDLjY1+rsK9asDzknhbrd9g/n/01/acbU25KTsUSiLKwvlLyA+6XLUOA==" - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" - }, - "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "0.4.19" - } - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "requires": { - "once": "1.4.0" - } - }, - "engine.io": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.4.tgz", - "integrity": "sha1-PQIRtwpVLOhB/8fahiezAamkFi4=", - "requires": { - "accepts": "1.3.3", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "2.6.9", - "engine.io-parser": "2.1.2", - "uws": "0.14.5", - "ws": "3.3.3" - }, - "dependencies": { - "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.1", - "ultron": "1.1.1" - } - } - } - }, - "engine.io-client": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.4.tgz", - "integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=", - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "2.6.9", - "engine.io-parser": "2.1.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "3.3.3", - "xmlhttprequest-ssl": "1.5.5", - "yeast": "0.1.2" - }, - "dependencies": { - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.1", - "ultron": "1.1.1" - } - } - } - }, - "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary2": "1.0.2" - } - }, - "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.2.0", - "tapable": "0.1.10" - }, - "dependencies": { - "memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=" - } - } - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" - }, - "err-code": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", - "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", - "optional": true - }, - "errno": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", - "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", - "requires": { - "prr": "1.0.1" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "requires": { - "is-arrayish": "0.2.1" - } - }, - "error-stack-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.1.tgz", - "integrity": "sha1-oyArj7AxFKqbQKDjZp5IsrZaAQo=", - "requires": { - "stackframe": "1.0.4" - } - }, - "es5-ext": { - "version": "0.10.38", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", - "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38", - "es6-symbol": "3.1.1" - } - }, - "es6-promise": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.2.tgz", - "integrity": "sha512-LSas5vsuA6Q4nEdf9wokY5/AJYXry98i0IzXsv49rYsgDGDNDPbqAYR1Pe23iFxygfbGZNR/5VrHXBCh2BhvUQ==" - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38" - } - }, - "es6-template-strings": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-template-strings/-/es6-template-strings-2.0.1.tgz", - "integrity": "sha1-sWbGpiVi9Hi7d3X2ypYQOlmbSyw=", - "optional": true, - "requires": { - "es5-ext": "0.10.38", - "esniff": "1.1.0" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "esniff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-1.1.0.tgz", - "integrity": "sha1-xmhJIp+RRk3t4uDUAgHtar9l8qw=", - "optional": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "eval": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.2.tgz", - "integrity": "sha1-n3EDKEwQWmbfQDCysycxZYNwE9o=", - "requires": { - "require-like": "0.1.2" - } - }, - "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=" - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" - }, - "eventsource": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", - "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", - "requires": { - "original": "1.0.0" - } - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.1" - } - }, - "exec-sh": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", - "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", - "optional": true, - "requires": { - "merge": "1.2.0" - } - }, - "execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "exenv": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", - "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "requires": { - "os-homedir": "1.0.2" - } - }, - "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", - "requires": { - "accepts": "1.3.4", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.0", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", - "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", - "utils-merge": "1.0.1", - "vary": "1.1.2" - } - }, - "express-graphql": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/express-graphql/-/express-graphql-0.6.11.tgz", - "integrity": "sha512-dC/FAun5rqcRxhDe78047hqc048mo3xZpBDS0Z7RZOw9UleO9mZE0rHMS9yrVSaYzsLiz+q4PldKu6Oaqop+CA==", - "requires": { - "accepts": "1.3.4", - "content-type": "1.0.4", - "http-errors": "1.6.2", - "raw-body": "2.3.2" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - }, - "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.19", - "tmp": "0.0.33" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "requires": { - "is-extglob": "1.0.0" - } - }, - "extract-text-webpack-plugin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-1.0.1.tgz", - "integrity": "sha1-yVvzy6rEnclvHcbgclSfu2VMzSw=", - "requires": { - "async": "1.5.2", - "loader-utils": "0.2.17", - "webpack-sources": "0.1.5" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" - }, - "fast-glob": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-1.0.1.tgz", - "integrity": "sha512-C2VHbdBwSkaQDyavjQZDflZzmZKrsUK3fTdJtsOnED0L0vtHCw+NL0h8pRcydbpRHlNJLZ4/LbOfEdJKspK91A==", - "requires": { - "bash-glob": "1.0.2", - "glob-parent": "3.1.0", - "micromatch": "3.1.5", - "readdir-enhanced": "1.5.2" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", - "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.1", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "micromatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz", - "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.0", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.7", - "object.pick": "1.3.0", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fastparse": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", - "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=" - }, - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "requires": { - "websocket-driver": "0.7.0" - } - }, - "fb-watchman": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", - "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", - "requires": { - "bser": "2.0.0" - } - }, - "fbjs": { - "version": "0.8.16", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", - "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", - "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.17" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" - } - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "file-loader": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.9.0.tgz", - "integrity": "sha1-HS2t3UJM5tGwfP4/eXMb7TYXq0I=", - "requires": { - "loader-utils": "0.2.17" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" - }, - "filesize": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.11.tgz", - "integrity": "sha512-ZH7loueKBoDb7yG9esn1U+fgq7BzlzW6NRi5/rMdxIZ05dj7GFD/Xc5rq2CDt5Yq86CyfSYVyx4242QQNZbx1g==" - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" - } - }, - "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "requires": { - "commondir": "1.0.1", - "mkdirp": "0.5.1", - "pkg-dir": "1.0.0" - } - }, - "find-node-modules": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-1.0.4.tgz", - "integrity": "sha1-tt6zzMtpnIcDdne87eLF9YYrJVA=", - "requires": { - "findup-sync": "0.4.2", - "merge": "1.2.0" - }, - "dependencies": { - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "requires": { - "fs-exists-sync": "0.1.0" - } - }, - "findup-sync": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.2.tgz", - "integrity": "sha1-qBF9D3MST1pFRoOVef5S1xKfteU=", - "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "0.2.0", - "which": "1.3.0" - } - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" - }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" - } - } - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "2.0.1" - } - } - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "optional": true, - "requires": { - "detect-file": "1.0.0", - "is-glob": "3.1.0", - "micromatch": "3.1.5", - "resolve-dir": "1.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "optional": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", - "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", - "optional": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.1", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "optional": true, - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "optional": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "optional": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "optional": true, - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "optional": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "optional": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "optional": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "optional": true - } - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "optional": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "optional": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "optional": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "optional": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "optional": true - }, - "micromatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz", - "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", - "optional": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.0", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.7", - "object.pick": "1.3.0", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - } - } - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "optional": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.2" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "optional": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "optional": true - }, - "flat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-2.0.1.tgz", - "integrity": "sha1-cOKRiKdL4MPIlAnu0fqVd5B64y8=", - "requires": { - "is-buffer": "1.1.6" - } - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "requires": { - "for-in": "1.0.2" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "friendly-errors-webpack-plugin": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.6.1.tgz", - "integrity": "sha1-4yeBxHIvVGoGqbXXp8+ihSA3XXA=", - "requires": { - "chalk": "1.1.3", - "error-stack-parser": "2.0.1", - "string-length": "1.0.1" - } - }, - "front-matter": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-2.3.0.tgz", - "integrity": "sha1-cgOviWzjV+4E4qpFFp6pHtf2dQQ=", - "requires": { - "js-yaml": "3.10.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" - }, - "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - } - } - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=" - }, - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", - "optional": true, - "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.39", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gatsby": { - "version": "1.9.158", - "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-1.9.158.tgz", - "integrity": "sha512-5/2gx8k2uVUnCk6I6wJuWCfm9wLpKmBaBYHimk1bPdHknguR3au9ZL1tW+FM7zzadzbuwQbcFtUWQ+/Vjh4S4g==", - "requires": { - "async": "2.6.0", - "babel-code-frame": "6.26.0", - "babel-core": "6.26.0", - "babel-loader": "6.4.1", - "babel-plugin-add-module-exports": "0.2.1", - "babel-plugin-transform-object-assign": "6.22.0", - "babel-polyfill": "6.26.0", - "babel-preset-env": "1.6.1", - "babel-preset-es2015": "6.24.1", - "babel-preset-react": "6.24.1", - "babel-preset-stage-0": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babylon": "6.18.0", - "better-queue": "3.8.6", - "bluebird": "3.5.1", - "chalk": "1.1.3", - "chokidar": "1.7.0", - "chunk-manifest-webpack-plugin": "0.1.0", - "common-tags": "1.7.2", - "convert-hrtime": "2.0.0", - "copyfiles": "1.2.0", - "core-js": "2.5.1", - "css-loader": "0.26.4", - "debug": "2.6.9", - "del": "3.0.0", - "detect-port": "1.2.2", - "domready": "1.0.8", - "dotenv": "4.0.0", - "express": "4.16.2", - "express-graphql": "0.6.11", - "extract-text-webpack-plugin": "1.0.1", - "file-loader": "0.9.0", - "flat": "2.0.1", - "friendly-errors-webpack-plugin": "1.6.1", - "front-matter": "2.3.0", - "fs-extra": "4.0.3", - "gatsby-1-config-css-modules": "1.0.8", - "gatsby-cli": "1.1.28", - "gatsby-link": "1.6.34", - "gatsby-module-loader": "1.0.9", - "gatsby-react-router-scroll": "1.0.8", - "glob": "7.1.2", - "graphql": "0.11.7", - "graphql-relay": "0.5.4", - "graphql-skip-limit": "1.0.9", - "history": "4.7.2", - "invariant": "2.2.2", - "is-relative": "0.2.1", - "is-relative-url": "2.0.0", - "joi": "12.0.0", - "json-loader": "0.5.7", - "json-stringify-safe": "5.0.1", - "json5": "0.5.1", - "lodash": "4.17.4", - "lodash-id": "0.14.0", - "lowdb": "0.16.2", - "md5": "2.2.1", - "md5-file": "3.2.3", - "mime": "1.6.0", - "mitt": "1.1.3", - "mkdirp": "0.5.1", - "moment": "2.20.1", - "node-libs-browser": "2.1.0", - "normalize-path": "2.1.1", - "null-loader": "0.1.1", - "opn": "5.2.0", - "parse-filepath": "1.0.2", - "path-exists": "3.0.0", - "postcss-browser-reporter": "0.5.0", - "postcss-cssnext": "2.11.0", - "postcss-import": "8.2.0", - "postcss-loader": "0.13.0", - "postcss-reporter": "1.4.1", - "raw-loader": "0.5.1", - "react": "15.6.2", - "react-dev-utils": "4.2.1", - "react-dom": "15.6.2", - "react-error-overlay": "3.0.0", - "react-hot-loader": "3.1.3", - "react-router": "4.2.0", - "react-router-dom": "4.2.2", - "redux": "3.7.2", - "relay-compiler": "1.4.1", - "remote-redux-devtools": "0.5.12", - "serve": "6.4.8", - "sift": "3.3.12", - "signal-exit": "3.0.2", - "slash": "1.0.0", - "socket.io": "2.0.4", - "static-site-generator-webpack-plugin": "3.4.1", - "string-similarity": "1.2.0", - "style-loader": "0.13.2", - "type-of": "2.0.1", - "url-loader": "0.5.9", - "v8-compile-cache": "1.1.0", - "webpack": "1.15.0", - "webpack-configurator": "0.3.1", - "webpack-dev-middleware": "1.12.2", - "webpack-dev-server": "1.16.5", - "webpack-hot-middleware": "2.21.0", - "webpack-md5-hash": "0.0.5", - "webpack-stats-plugin": "0.1.5", - "webpack-validator": "2.3.0", - "yaml-loader": "0.4.0" - }, - "dependencies": { - "gatsby-cli": { - "version": "1.1.28", - "resolved": "https://registry.npmjs.org/gatsby-cli/-/gatsby-cli-1.1.28.tgz", - "integrity": "sha512-v65Iu0TM3zysztuc8Zq54tHnLW5JBl7Y4f/b0Q5W/1JxEWTGgcuSwvP8KOmRXtjf5ZzBhMFmvklz+eymKU7EjA==", - "requires": { - "babel-code-frame": "6.26.0", - "babel-runtime": "6.26.0", - "bluebird": "3.5.1", - "common-tags": "1.7.2", - "convert-hrtime": "2.0.0", - "core-js": "2.5.1", - "execa": "0.8.0", - "fs-extra": "4.0.3", - "hosted-git-info": "2.5.0", - "lodash": "4.17.4", - "pretty-error": "2.1.1", - "resolve-cwd": "2.0.0", - "source-map": "0.5.7", - "stack-trace": "0.0.10", - "update-notifier": "2.3.0", - "yargs": "8.0.2", - "yurnalist": "0.2.1" - } - } - } - }, - "gatsby-1-config-css-modules": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/gatsby-1-config-css-modules/-/gatsby-1-config-css-modules-1.0.8.tgz", - "integrity": "sha512-eZoNmkk3Am9eAmTi3fCRN+pMklVjUnOn9YneM3WLtYatn0ByqbpiFD1CLZVosWNcD/to2wkri546zULRLMD55Q==", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "gatsby-link": { - "version": "1.6.34", - "resolved": "https://registry.npmjs.org/gatsby-link/-/gatsby-link-1.6.34.tgz", - "integrity": "sha512-v7jvHlPkgcEWp8G0lfC7DyJBbP2mShAUryNUeskgBeWeDSOWn0nsnCkU1ecc0WUX8kr2LOVOJDbyBjNiieVLMg==", - "requires": { - "babel-runtime": "6.26.0", - "prop-types": "15.6.0", - "ric": "1.3.0" - } - }, - "gatsby-module-loader": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/gatsby-module-loader/-/gatsby-module-loader-1.0.9.tgz", - "integrity": "sha512-PVq20rxDYAZVXBDgQzp5aNC0s9r4Je/UNVQUHE89N+CihY+POm+jp9eIHWLDzeGgMHGcSOg8Zn5MaHpngXL+5Q==", - "requires": { - "babel-runtime": "6.26.0", - "loader-utils": "0.2.17" - } - }, - "gatsby-plugin-react-helmet": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-2.0.3.tgz", - "integrity": "sha512-PmkIElOL7jajobwRg7hjmecBWPAs5b2GpyYbBgmFNIyWpgYkHmnJtY8svZAfsjclyLmq4xGwVPTPZHzNxHNo7w==", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "gatsby-react-router-scroll": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/gatsby-react-router-scroll/-/gatsby-react-router-scroll-1.0.8.tgz", - "integrity": "sha512-+5YZGosGlgUV51FBNPZ+IhzOe8OIwyh738hDtk5eiCMNrbTjCliNN2MFtCe9PIbATfMe0A0LoXAcvRktRb5zJg==", - "requires": { - "babel-runtime": "6.26.0", - "scroll-behavior": "0.9.5", - "warning": "3.0.0" - } - }, - "gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "requires": { - "ansi": "0.3.1", - "has-unicode": "2.0.1", - "lodash.pad": "4.5.1", - "lodash.padend": "4.6.1", - "lodash.padstart": "4.6.1" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-params": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/get-params/-/get-params-0.1.2.tgz", - "integrity": "sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "requires": { - "is-glob": "2.0.1" - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "requires": { - "min-document": "2.19.0", - "process": "0.5.2" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" - } - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "requires": { - "ini": "1.3.5" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.1", - "resolve-dir": "1.0.1" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.1", - "which": "1.3.0" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "requires": { - "create-error-class": "3.0.2", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "unzip-response": "2.0.1", - "url-parse-lax": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" - }, - "graphql": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", - "integrity": "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==", - "requires": { - "iterall": "1.1.3" - } - }, - "graphql-relay": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.5.4.tgz", - "integrity": "sha1-WAUM/hYRhZX4KrOqv8l0VGznVag=" - }, - "graphql-skip-limit": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/graphql-skip-limit/-/graphql-skip-limit-1.0.9.tgz", - "integrity": "sha512-xe02XZBG8HW4Oa0rr5X1r0/8kJ95Fq8ZCNaadiivqmES97bmaUjTGT2+q67VvwsaTkJT4eyhyjoh/4/7DJwF/Q==", - "requires": { - "babel-runtime": "6.26.0", - "graphql": "0.11.7" - } - }, - "gzip-size": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", - "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", - "requires": { - "duplexer": "0.1.1" - } - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "requires": { - "function-bind": "1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-binary2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", - "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "requires": { - "inherits": "2.0.3" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.0", - "sntp": "2.1.0" - } - }, - "history": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", - "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", - "requires": { - "invariant": "2.2.2", - "loose-envify": "1.3.1", - "resolve-pathname": "2.2.0", - "value-equal": "0.4.0", - "warning": "3.0.0" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" - }, - "hoist-non-react-statics": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz", - "integrity": "sha1-ND24TGAYxlB3iJgkATWhQg7iLOA=" - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "requires": { - "parse-passwd": "1.0.0" - } - }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" - }, - "html-comment-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", - "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=" - }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" - }, - "htmlparser2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", - "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.1.0", - "domutils": "1.1.6", - "readable-stream": "1.0.34" - }, - "dependencies": { - "domutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", - "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", - "requires": { - "domelementtype": "1.3.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.3.1" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } - } - }, - "http-parser-js": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", - "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=" - }, - "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", - "requires": { - "eventemitter3": "1.2.0", - "requires-port": "1.0.0" - } - }, - "http-proxy-middleware": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", - "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", - "requires": { - "http-proxy": "1.16.2", - "is-glob": "3.1.0", - "lodash": "4.17.4", - "micromatch": "2.3.11" - }, - "dependencies": { - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" - }, - "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" - }, - "immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.4", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "interpret": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", - "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=" - }, - "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "requires": { - "loose-envify": "1.3.1" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.1" - }, - "dependencies": { - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "requires": { - "is-unc-path": "1.0.0" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "requires": { - "unc-path-regex": "0.1.2" - } - } - } - }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "requires": { - "binary-extensions": "1.11.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-ci": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", - "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", - "requires": { - "ci-info": "1.1.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } - } - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "requires": { - "global-dirs": "0.1.1", - "is-path-inside": "1.0.1" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - }, - "is-odd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", - "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", - "requires": { - "is-number": "3.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - } - } - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "requires": { - "is-path-inside": "1.0.1" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" - }, - "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "requires": { - "is-unc-path": "0.1.2" - } - }, - "is-relative-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-relative-url/-/is-relative-url-2.0.0.tgz", - "integrity": "sha1-cpAtf+BLPUeS59sV+duEtyBMnO8=", - "requires": { - "is-absolute-url": "2.1.0" - } - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" - }, - "is-root": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-1.0.0.tgz", - "integrity": "sha1-B7bCM7w5TNnQK6FclmvWZg1jQtU=" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "requires": { - "html-comment-regex": "1.1.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-windows": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", - "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=" - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isemail": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.0.0.tgz", - "integrity": "sha512-rz0ng/c+fX+zACpLgDB8fnUQ845WSU06f4hlhk4K8TJxmR6f5hyvitu9a9JdMD7aq/P4E0XdG1uaab2OiXgHlA==", - "requires": { - "punycode": "2.1.0" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isnumeric": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/isnumeric/-/isnumeric-0.2.0.tgz", - "integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=" - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "1.7.3", - "whatwg-fetch": "2.0.3" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "items": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz", - "integrity": "sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg=" - }, - "iterall": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", - "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==" - }, - "joi": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-12.0.0.tgz", - "integrity": "sha512-z0FNlV4NGgjQN1fdtHYXf5kmgludM65fG/JlXzU6+rwkt9U5UWuXVYnXa2FpK0u6+qBuCmrm5byPNuiiddAHvQ==", - "requires": { - "hoek": "4.2.0", - "isemail": "3.0.0", - "topo": "2.0.2" - } - }, - "js-base64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.1.tgz", - "integrity": "sha512-2h586r2I/CqU7z1aa1kBgWaVAXWAZK+zHnceGi/jFgn7+7VSluxYer/i3xOZVearCxxXvyDkLtTBo+OeJCA3kA==" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", - "requires": { - "argparse": "1.0.9", - "esprima": "2.7.3" - } - }, - "jsan": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/jsan/-/jsan-3.1.9.tgz", - "integrity": "sha1-JwVnbBBY8KfZrCZq0Daldpz6fJY=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" - }, - "json-loader": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "4.1.11" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jspm": { - "version": "0.17.0-beta.47", - "resolved": "https://registry.npmjs.org/jspm/-/jspm-0.17.0-beta.47.tgz", - "integrity": "sha512-fqO8V3/V2j9zqDHg6msMvRj/yr5T8WSEO5w/2PrgGC3noKuh4Mg/W6Tp+jOAbDl/t0jHQVLHfVBEA128EYhkug==", - "optional": true, - "requires": { - "bluebird": "3.5.1", - "chalk": "1.1.3", - "core-js": "1.2.7", - "glob": "6.0.4", - "graceful-fs": "4.1.11", - "jspm-github": "0.14.13", - "jspm-npm": "0.30.3", - "jspm-registry": "0.4.4", - "liftoff": "2.5.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ncp": "2.0.0", - "proper-lockfile": "1.2.0", - "request": "2.83.0", - "rimraf": "2.6.2", - "sane": "1.7.0", - "semver": "5.5.0", - "systemjs": "0.20.19", - "systemjs-builder": "0.16.12", - "traceur": "0.0.105", - "uglify-js": "2.8.29" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "optional": true - }, - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "optional": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "jspm-github": { - "version": "0.14.13", - "resolved": "https://registry.npmjs.org/jspm-github/-/jspm-github-0.14.13.tgz", - "integrity": "sha1-Mm5SF9NjmyFgkpOwHn4Yd13T3Mc=", - "optional": true, - "requires": { - "bluebird": "3.5.1", - "expand-tilde": "1.2.2", - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "netrc": "0.1.4", - "request": "2.83.0", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar-fs": "1.16.0", - "which": "1.3.0" - } - }, - "jspm-npm": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/jspm-npm/-/jspm-npm-0.30.3.tgz", - "integrity": "sha512-yZBzuvA+9pGw+KbdnvV8IxAGAkyonwisqu/WbZHZcs5XaQa4vzTpCdAopuGypPEQBuvUjpFenINtP4nJIkHxDw==", - "optional": true, - "requires": { - "bluebird": "3.5.1", - "buffer-peek-stream": "1.0.1", - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "readdirp": "2.1.0", - "request": "2.83.0", - "semver": "5.5.0", - "tar-fs": "1.16.0", - "traceur": "0.0.105", - "which": "1.3.0" - } - }, - "jspm-registry": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jspm-registry/-/jspm-registry-0.4.4.tgz", - "integrity": "sha1-1TFmA1qHzc5YXWK6o5dWhUaZbXA=", - "optional": true, - "requires": { - "graceful-fs": "4.1.11", - "rimraf": "2.6.2", - "rsvp": "3.6.2", - "semver": "4.3.6" - }, - "dependencies": { - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "optional": true - } - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "requires": { - "package-json": "4.0.1" - } - }, - "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", - "requires": { - "set-getter": "0.1.0" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "1.0.0" - } - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "optional": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.5.0" - } - }, - "linked-list": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/linked-list/-/linked-list-0.1.0.tgz", - "integrity": "sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=" - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - }, - "lodash-es": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", - "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" - }, - "lodash-id": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.0.tgz", - "integrity": "sha1-uvSJNOVDobXWNG+MhGmLGoyAOJY=" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" - }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" - }, - "lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" - }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" - }, - "lodash.merge": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", - "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=" - }, - "lodash.pad": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", - "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=" - }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" - }, - "lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - }, - "lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" - }, - "lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" - }, - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.templatesettings": "4.1.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "requires": { - "lodash._reinterpolate": "3.0.0" - } - }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "requires": { - "chalk": "1.1.3" - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "requires": { - "js-tokens": "3.0.2" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, - "lowdb": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-0.16.2.tgz", - "integrity": "sha1-oql262bsV3lykZcPPIfNthEm+jo=", - "requires": { - "graceful-fs": "4.1.11", - "is-promise": "2.1.0", - "lodash": "4.17.4", - "steno": "0.4.4" - } - }, - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "ltcdr": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltcdr/-/ltcdr-2.2.1.tgz", - "integrity": "sha1-Wrh60dTB2rjowIu/A37gwZAih88=" - }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=" - }, - "make-dir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", - "requires": { - "pify": "3.0.0" - } - }, - "make-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", - "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", - "optional": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "optional": true, - "requires": { - "tmpl": "1.0.4" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "1.0.1" - } - }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=" - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "1.1.6" - } - }, - "md5-file": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", - "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", - "requires": { - "buffer-alloc": "1.1.0" - } - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - }, - "dependencies": { - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - } - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "requires": { - "mimic-fn": "1.1.0" - } - }, - "memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", - "requires": { - "errno": "0.1.6", - "readable-stream": "2.3.3" - } - }, - "merge": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micro": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/micro/-/micro-9.1.0.tgz", - "integrity": "sha512-0Ap4bXS9MyInYSLBe/5u+qEBY3VgcOTQlAt5wGc3DN/Rk4IH+PdRI47x3/xWBxQWt0ISRgmE4+U72sfm4ksthg==", - "requires": { - "content-type": "1.0.4", - "is-stream": "1.1.0", - "mri": "1.1.0", - "raw-body": "2.3.2" - } - }, - "micro-compress": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micro-compress/-/micro-compress-1.0.0.tgz", - "integrity": "sha1-U/WoC0rQMgyhZaVZtuPfFF1PcE8=", - "requires": { - "compression": "1.7.1" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "requires": { - "mime-db": "1.30.0" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "0.1.1" - } - }, - "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mitt": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.1.3.tgz", - "integrity": "sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA==" - }, - "mixin-deep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", - "integrity": "sha512-dgaCvoh6i1nosAUBKb0l0pfJ78K8+S9fluyIR2YvAeUD/QuMahnFnF3xYty5eYXMjhGSsB0DsW6A0uAZyetoAg==", - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "moment": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", - "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" - }, - "mri": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.0.tgz", - "integrity": "sha1-XAo/KcjM/7ux7JQdzsCdcfoy82o=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", - "optional": true - }, - "nanomatch": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz", - "integrity": "sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg==", - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "is-odd": "1.0.0", - "kind-of": "5.1.0", - "object.pick": "1.3.0", - "regex-not": "1.0.0", - "snapdragon": "0.8.1", - "to-regex": "3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", - "optional": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "netrc": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/netrc/-/netrc-0.1.4.tgz", - "integrity": "sha1-a+lPysqNd63gqWcNxGCRTJRHJEQ=", - "optional": true - }, - "node-emoji": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", - "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", - "requires": { - "lodash.toarray": "4.4.0" - } - }, - "node-eta": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/node-eta/-/node-eta-0.9.0.tgz", - "integrity": "sha1-n7CwmbzSoCGUDmA8ZCVNwAPZp6g=" - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" - } - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" - }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.1.7", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.3", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "1.0.3", - "timers-browserify": "2.0.4", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "node-version": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.1.0.tgz", - "integrity": "sha512-t1V2RFiaTavaW3jtQO0A2nok6k7/Gghuvx2rjvICuT0B0dYaObBQ4U0xHL+ZTPFZodt1LMYG2Vi2nypfz4/AJg==" - }, - "noms": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", - "integrity": "sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "1.0.34" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "2.0.1" - } - }, - "npmlog": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.3.tgz", - "integrity": "sha1-Ag+ZNR8MAuOZxnS6JW58TTs90pg=", - "requires": { - "ansi": "0.3.1", - "are-we-there-yet": "1.1.4", - "gauge": "1.2.7" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "requires": { - "boolbase": "1.0.0" - } - }, - "null-loader": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-0.1.1.tgz", - "integrity": "sha1-F76av80/8OFRL2/Er8sfUDk3j64=" - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - } - } - }, - "object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "optional": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "optional": true, - "requires": { - "for-in": "1.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "optional": true - } - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "optional": true, - "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "optional": true, - "requires": { - "for-in": "1.0.2" - } - } - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onecolor": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-2.4.2.tgz", - "integrity": "sha1-pT7D/xccNEYBbdUhDRobVEv32HQ=" - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "1.1.0" - } - }, - "open": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", - "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=" - }, - "openssl-self-signed-certificate": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz", - "integrity": "sha1-nTpHdrGlfphHNQOSEUrS+RWoPdQ=" - }, - "opn": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.2.0.tgz", - "integrity": "sha512-Jd/GpzPyHF4P2/aNOVmS3lfMSWV9J7cOhCG1s08XCEAsPkB7lp6ddiU0J7XzyQRDUh8BqJ7PchfINjR8jyofRQ==", - "requires": { - "is-wsl": "1.1.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.2" - } - }, - "original": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", - "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", - "requires": { - "url-parse": "1.0.5" - }, - "dependencies": { - "url-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", - "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", - "requires": { - "querystringify": "0.0.4", - "requires-port": "1.0.0" - } - } - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - } - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "requires": { - "p-try": "1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "1.2.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "requires": { - "got": "6.7.1", - "registry-auth-token": "3.3.1", - "registry-url": "3.1.0", - "semver": "5.5.0" - } - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" - }, - "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "requires": { - "asn1.js": "4.9.2", - "browserify-aes": "1.1.1", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.14" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "requires": { - "better-assert": "1.0.2" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "requires": { - "better-assert": "1.0.2" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "requires": { - "pify": "2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "pbkdf2": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", - "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.9" - } - }, - "pbkdf2-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", - "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "2.0.4" - } - }, - "pixrem": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-3.0.2.tgz", - "integrity": "sha1-MNG6+0w73Ojpu0vVahOYVhkyDDQ=", - "requires": { - "browserslist": "1.7.7", - "postcss": "5.2.18", - "reduce-css-calc": "1.3.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "requires": { - "caniuse-db": "1.0.30000793", - "electron-to-chromium": "1.3.31" - } - } - } - }, - "pkg-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz", - "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=", - "requires": { - "find-up": "1.1.2", - "load-json-file": "1.1.0", - "object-assign": "4.1.1", - "symbol": "0.2.3" - }, - "dependencies": { - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "requires": { - "find-up": "1.1.2" - } - }, - "pkg-resolve": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/pkg-resolve/-/pkg-resolve-0.1.14.tgz", - "integrity": "sha1-Mpsudsy7Ny4i5qOkHLMKsEV4Nro=", - "optional": true, - "requires": { - "jspm": "0.17.0-beta.47", - "resolve": "1.5.0" - } - }, - "pkginfo": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", - "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=" - }, - "pleeease-filters": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-3.0.1.tgz", - "integrity": "sha1-Tf4OjxBGYTUXxktyi8gGCKfr8i8=", - "requires": { - "onecolor": "2.4.2", - "postcss": "5.2.18" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.1", - "source-map": "0.5.7", - "supports-color": "3.2.3" - }, - "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "postcss-apply": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.3.0.tgz", - "integrity": "sha1-ovN8W9+ogeTBX08kXsDNlt0ucNU=", - "requires": { - "balanced-match": "0.4.2", - "postcss": "5.2.18" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "postcss-attribute-case-insensitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-1.0.1.tgz", - "integrity": "sha1-zrc3d+EGFn6yM/GTjJvZ8uaXMI0=", - "requires": { - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" - } - }, - "postcss-browser-reporter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/postcss-browser-reporter/-/postcss-browser-reporter-0.5.0.tgz", - "integrity": "sha1-rgad0IbVc4jRluHaw5y412Jv60g=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "requires": { - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" - } - }, - "postcss-color-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-function/-/postcss-color-function-2.0.1.tgz", - "integrity": "sha1-mtIm9VDop8f4uKd4YFRbbdf1UkE=", - "requires": { - "css-color-function": "1.3.3", - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-color-gray": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-3.0.1.tgz", - "integrity": "sha1-dEMu3mbdg7HRNjVlxos3bhj/Z3A=", - "requires": { - "color": "0.11.4", - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-function-call": "1.0.2" - } - }, - "postcss-color-hex-alpha": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-2.0.0.tgz", - "integrity": "sha1-RP1uyt5mAoZIyIHLZQTNy/3GzQk=", - "requires": { - "color": "0.10.1", - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0" - }, - "dependencies": { - "color": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/color/-/color-0.10.1.tgz", - "integrity": "sha1-wEGI34KiCd3rzOzazT7DIPGTc58=", - "requires": { - "color-convert": "0.5.3", - "color-string": "0.3.0" - } - }, - "color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" - } - } - }, - "postcss-color-hsl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-color-hsl/-/postcss-color-hsl-1.0.5.tgz", - "integrity": "sha1-9Tuxw0gxDOMHrYnjGBqGRzi15oc=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "units-css": "0.4.0" - } - }, - "postcss-color-hwb": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-hwb/-/postcss-color-hwb-2.0.1.tgz", - "integrity": "sha1-1jr6+bcMtZX5AKKcn+V78qMvq+w=", - "requires": { - "color": "0.11.4", - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-function-call": "1.0.2" - } - }, - "postcss-color-rebeccapurple": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-2.0.1.tgz", - "integrity": "sha1-dMZETny7fYVhO19yht96SRYIRRw=", - "requires": { - "color": "0.11.4", - "postcss": "5.2.18" - } - }, - "postcss-color-rgb": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/postcss-color-rgb/-/postcss-color-rgb-1.1.4.tgz", - "integrity": "sha1-8pJD4i6OjBNDRHQJI3LUzmBb6Lw=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-color-rgba-fallback": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-2.2.0.tgz", - "integrity": "sha1-bSlJG+WZCpMXPUfnx29YELCUAro=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "rgb-hex": "1.0.0" - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "requires": { - "colormin": "1.1.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-cssnext": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/postcss-cssnext/-/postcss-cssnext-2.11.0.tgz", - "integrity": "sha1-MeaPAB5AlgTacDtm3hS4uMjJ8rE=", - "requires": { - "autoprefixer": "6.7.7", - "caniuse-api": "1.6.1", - "chalk": "1.1.3", - "pixrem": "3.0.2", - "pleeease-filters": "3.0.1", - "postcss": "5.2.18", - "postcss-apply": "0.3.0", - "postcss-attribute-case-insensitive": "1.0.1", - "postcss-calc": "5.3.1", - "postcss-color-function": "2.0.1", - "postcss-color-gray": "3.0.1", - "postcss-color-hex-alpha": "2.0.0", - "postcss-color-hsl": "1.0.5", - "postcss-color-hwb": "2.0.1", - "postcss-color-rebeccapurple": "2.0.1", - "postcss-color-rgb": "1.1.4", - "postcss-color-rgba-fallback": "2.2.0", - "postcss-custom-media": "5.0.1", - "postcss-custom-properties": "5.0.2", - "postcss-custom-selectors": "3.0.0", - "postcss-font-family-system-ui": "1.0.2", - "postcss-font-variant": "2.0.1", - "postcss-image-set-polyfill": "0.3.5", - "postcss-initial": "1.5.3", - "postcss-media-minmax": "2.1.2", - "postcss-nesting": "2.3.1", - "postcss-pseudo-class-any-link": "1.0.0", - "postcss-pseudoelements": "3.0.0", - "postcss-replace-overflow-wrap": "1.0.0", - "postcss-selector-matches": "2.0.5", - "postcss-selector-not": "2.0.0" - } - }, - "postcss-custom-media": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-5.0.1.tgz", - "integrity": "sha1-E40loYS/LrVN4S1VpsAcMKnYvYE=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-custom-properties": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-5.0.2.tgz", - "integrity": "sha1-lxnXjy2pz59TgQrrwj1GVhMKzrE=", - "requires": { - "balanced-match": "0.4.2", - "postcss": "5.2.18" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "postcss-custom-selectors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-3.0.0.tgz", - "integrity": "sha1-j4Ekn17Qeo0JF89qOf5bBWt/lqw=", - "requires": { - "balanced-match": "0.2.1", - "postcss": "5.2.18", - "postcss-selector-matches": "2.0.5" - }, - "dependencies": { - "balanced-match": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", - "integrity": "sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc=" - } - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "requires": { - "postcss": "5.2.18", - "uniqs": "2.0.0" - } - }, - "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", - "requires": { - "postcss": "5.2.18", - "uniqid": "4.1.1" - } - }, - "postcss-font-family-system-ui": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-1.0.2.tgz", - "integrity": "sha1-PhpeP7fjHl6ecUOcyw6AFFVpJ8c=", - "requires": { - "lodash": "4.17.4", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-font-variant": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-2.0.1.tgz", - "integrity": "sha1-fKKRA/WfoCyjrOLKIrL3VoU9Tvg=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-image-set-polyfill": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz", - "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=", - "requires": { - "postcss": "6.0.16", - "postcss-media-query-parser": "0.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - }, - "dependencies": { - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "postcss": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", - "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==", - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "5.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", - "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-import": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-8.2.0.tgz", - "integrity": "sha1-+S/SRU4h7077HnXADEesA/TROXw=", - "requires": { - "object-assign": "4.1.1", - "pkg-resolve": "0.1.14", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "promise-each": "2.2.0", - "read-cache": "1.0.0", - "resolve": "1.5.0" - } - }, - "postcss-initial": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-1.5.3.tgz", - "integrity": "sha1-IMPpHJaCLdsb7UlQjbltVrrDd9A=", - "requires": { - "lodash.template": "4.4.0", - "postcss": "5.2.18" - } - }, - "postcss-loader": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-0.13.0.tgz", - "integrity": "sha1-cv2vDSlETfd9N1HOTmncQLyZ7YU=", - "requires": { - "loader-utils": "0.2.17", - "postcss": "5.2.18" - } - }, - "postcss-media-minmax": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-2.1.2.tgz", - "integrity": "sha1-RExc+JJqteT9iiUJ6Sl+dRZJzfg=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=" - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.1" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "requires": { - "caniuse-db": "1.0.30000793", - "electron-to-chromium": "1.3.31" - } - } - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=" - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" - } - }, - "postcss-modules-extract-imports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", - "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", - "requires": { - "postcss": "6.0.16" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - }, - "dependencies": { - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "postcss": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", - "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==", - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "5.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", - "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.16" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - }, - "dependencies": { - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "postcss": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", - "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==", - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "5.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", - "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.16" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - }, - "dependencies": { - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "postcss": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", - "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==", - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "5.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", - "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "requires": { - "icss-replace-symbols": "1.1.0", - "postcss": "6.0.16" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - }, - "dependencies": { - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "postcss": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", - "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==", - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "5.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", - "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-nesting": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-2.3.1.tgz", - "integrity": "sha1-lKa2pO9wf77CCof+5clXdZtOAc8=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-pseudo-class-any-link": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-1.0.0.tgz", - "integrity": "sha1-kDI5GWQB0zX+c6x1YYb6YuaTryY=", - "requires": { - "postcss": "5.2.18", - "postcss-selector-parser": "1.3.3" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-1.3.3.tgz", - "integrity": "sha1-0u4Z33pk+O8hwacchvfUg1yIwoE=", - "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" - } - } - } - }, - "postcss-pseudoelements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-3.0.0.tgz", - "integrity": "sha1-bGghd8eQC6BTtt8X+MWQKEx7i7w=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-replace-overflow-wrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-1.0.0.tgz", - "integrity": "sha1-8KA7Meq5Y2ppNr/SEOKu8bQ0pkM=", - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", - "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", - "requires": { - "chalk": "1.1.3", - "lodash": "4.17.4", - "log-symbols": "1.0.2", - "postcss": "5.2.18" - } - }, - "postcss-selector-matches": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-2.0.5.tgz", - "integrity": "sha1-+g9Dvle2jneqTNEYBwI0kqExAn8=", - "requires": { - "balanced-match": "0.4.2", - "postcss": "5.2.18" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "postcss-selector-not": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-2.0.0.tgz", - "integrity": "sha1-xzrSGj91I0vuf+4mnhVP1qhpeY0=", - "requires": { - "balanced-match": "0.2.1", - "postcss": "5.2.18" - }, - "dependencies": { - "balanced-match": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", - "integrity": "sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc=" - } - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "uniqs": "2.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=" - }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "uniqs": "2.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" - }, - "prettier": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.10.2.tgz", - "integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==", - "dev": true - }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", - "requires": { - "renderkid": "2.0.1", - "utila": "0.4.0" - } - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "2.0.6" - } - }, - "promise-each": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/promise-each/-/promise-each-2.2.0.tgz", - "integrity": "sha1-M1MXTv8mlEgQN+BOAfd6oPttG2A=", - "requires": { - "any-promise": "0.1.0" - } - }, - "prop-types": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", - "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "proper-lockfile": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-1.2.0.tgz", - "integrity": "sha1-zv9d2J0+XxD7deHo52vHWAGlnDQ=", - "optional": true, - "requires": { - "err-code": "1.1.2", - "extend": "3.0.1", - "graceful-fs": "4.1.11", - "retry": "0.10.1" - } - }, - "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", - "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "parse-asn1": "5.1.0", - "randombytes": "2.0.6" - } - }, - "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" - }, - "querystringify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", - "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=" - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "randomfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", - "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", - "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.1" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - } - }, - "raw-loader": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", - "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=" - }, - "rc": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.4.tgz", - "integrity": "sha1-oPYGyq4qO4YrvQ74VILAElsxX6M=", - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, - "react": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz", - "integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=", - "requires": { - "create-react-class": "15.6.2", - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "prop-types": "15.6.0" - } - }, - "react-deep-force-update": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz", - "integrity": "sha1-jqQmPNZFWgULN0RbPwj9g52G6Qk=" - }, - "react-dev-utils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-4.2.1.tgz", - "integrity": "sha1-nydj57r6GhucUiVNKked7sKA8RE=", - "requires": { - "address": "1.0.3", - "babel-code-frame": "6.26.0", - "chalk": "1.1.3", - "cross-spawn": "5.1.0", - "detect-port-alt": "1.1.3", - "escape-string-regexp": "1.0.5", - "filesize": "3.5.11", - "global-modules": "1.0.0", - "gzip-size": "3.0.0", - "inquirer": "3.3.0", - "is-root": "1.0.0", - "opn": "5.1.0", - "react-error-overlay": "3.0.0", - "recursive-readdir": "2.2.1", - "shell-quote": "1.6.1", - "sockjs-client": "1.1.4", - "strip-ansi": "3.0.1", - "text-table": "0.2.0" - }, - "dependencies": { - "detect-port-alt": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.3.tgz", - "integrity": "sha1-pNLwYddXoDTs83xRQmCph1DysTE=", - "requires": { - "address": "1.0.3", - "debug": "2.6.9" - } - }, - "opn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", - "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", - "requires": { - "is-wsl": "1.1.0" - } - } - } - }, - "react-dom": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz", - "integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "prop-types": "15.6.0" - } - }, - "react-error-overlay": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-3.0.0.tgz", - "integrity": "sha512-XzgvowFrwDo6TWcpJ/WTiarb9UI6lhA4PMzS7n1joK3sHfBBBOQHUc0U4u57D6DWO9vHv6lVSWx2Q/Ymfyv4hw==" - }, - "react-helmet": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.0.tgz", - "integrity": "sha1-qBgR3yExOm1VxfBYxK66XW89l6c=", - "requires": { - "deep-equal": "1.0.1", - "object-assign": "4.1.1", - "prop-types": "15.6.0", - "react-side-effect": "1.1.3" - } - }, - "react-hot-loader": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-3.1.3.tgz", - "integrity": "sha512-d7nZf78irxoGN5PY4zd6CSgZiroOhvIWzRast3qwTn4sSnBwlt08kV8WMQ9mitmxEdlCTwZt+5ClrRSjxWguMQ==", - "requires": { - "global": "4.3.2", - "react-deep-force-update": "2.1.1", - "react-proxy": "3.0.0-alpha.1", - "redbox-react": "1.5.0", - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "react-proxy": { - "version": "3.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz", - "integrity": "sha1-RABCa8+oDKpnJMd1VpUxUgn6Swc=", - "requires": { - "lodash": "4.17.4" - } - }, - "react-router": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", - "integrity": "sha512-DY6pjwRhdARE4TDw7XjxjZsbx9lKmIcyZoZ+SDO7SBJ1KUeWNxT22Kara2AC7u6/c2SYEHlEDLnzBCcNhLE8Vg==", - "requires": { - "history": "4.7.2", - "hoist-non-react-statics": "2.3.1", - "invariant": "2.2.2", - "loose-envify": "1.3.1", - "path-to-regexp": "1.7.0", - "prop-types": "15.6.0", - "warning": "3.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "react-router-dom": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.2.2.tgz", - "integrity": "sha512-cHMFC1ZoLDfEaMFoKTjN7fry/oczMgRt5BKfMAkTu5zEuJvUiPp1J8d0eXSVTnBh6pxlbdqDhozunOOLtmKfPA==", - "requires": { - "history": "4.7.2", - "invariant": "2.2.2", - "loose-envify": "1.3.1", - "prop-types": "15.6.0", - "react-router": "4.2.0", - "warning": "3.0.0" - } - }, - "react-side-effect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.1.3.tgz", - "integrity": "sha1-USwlq+DewXKDTEAB7FxR4E1BvFw=", - "requires": { - "exenv": "1.2.2", - "shallowequal": "1.0.2" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "requires": { - "mute-stream": "0.0.7" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "requires": { - "pify": "2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "readdir-enhanced": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/readdir-enhanced/-/readdir-enhanced-1.5.2.tgz", - "integrity": "sha1-YUYwSGkKxqRVt1ti+nioj43IXlM=", - "requires": { - "call-me-maybe": "1.0.1", - "es6-promise": "4.2.2", - "glob-to-regexp": "0.3.0" - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.3", - "set-immediate-shim": "1.0.1" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "1.5.0" - } - }, - "recursive-readdir": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.1.tgz", - "integrity": "sha1-kO8jHQd4xc4JPJpI105cVCLROpk=", - "requires": { - "minimatch": "3.0.3" - }, - "dependencies": { - "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "redbox-react": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/redbox-react/-/redbox-react-1.5.0.tgz", - "integrity": "sha512-mdxArOI3sF8K5Nay5NG+lv/VW516TbXjjd4h1wcV1Iy4IMDQPnCayjoQXBAycAFSME4nyXRUXCjHxsw2rYpVRw==", - "requires": { - "error-stack-parser": "1.3.6", - "object-assign": "4.1.1", - "prop-types": "15.6.0", - "sourcemapped-stacktrace": "1.1.8" - }, - "dependencies": { - "error-stack-parser": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", - "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", - "requires": { - "stackframe": "0.3.1" - } - }, - "stackframe": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", - "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=" - } - } - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "requires": { - "balanced-match": "0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "redux": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", - "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", - "requires": { - "lodash": "4.17.4", - "lodash-es": "4.17.4", - "loose-envify": "1.3.1", - "symbol-observable": "1.1.0" - } - }, - "redux-devtools-instrument": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/redux-devtools-instrument/-/redux-devtools-instrument-1.8.2.tgz", - "integrity": "sha1-XpHP5ALnkNrj/S8NI197fYSwn/4=", - "requires": { - "lodash": "4.17.4", - "symbol-observable": "1.1.0" - } - }, - "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" - }, - "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==" - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "requires": { - "is-equal-shallow": "0.1.3" - } - }, - "regex-not": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", - "requires": { - "extend-shallow": "2.0.1" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "registry-auth-token": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", - "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", - "requires": { - "rc": "1.2.4", - "safe-buffer": "5.1.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "requires": { - "rc": "1.2.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "requires": { - "jsesc": "0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - } - } - }, - "relay-compiler": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/relay-compiler/-/relay-compiler-1.4.1.tgz", - "integrity": "sha512-8O9dVIOOTp1TlbQhdNp2EBO/WUaSEPaYhQ8HFgMVjpvLTCaCfHEpptNQPJf5uDG/AH1p2qhPtLaCyQ2pBYh7Cw==", - "requires": { - "babel-generator": "6.26.0", - "babel-polyfill": "6.26.0", - "babel-preset-fbjs": "2.1.4", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "chalk": "1.1.3", - "fast-glob": "1.0.1", - "fb-watchman": "2.0.0", - "fbjs": "0.8.16", - "graphql": "0.11.7", - "immutable": "3.7.6", - "relay-runtime": "1.4.1", - "signedsource": "1.0.0", - "yargs": "9.0.1" - }, - "dependencies": { - "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" - } - } - } - }, - "relay-debugger-react-native-runtime": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/relay-debugger-react-native-runtime/-/relay-debugger-react-native-runtime-0.0.10.tgz", - "integrity": "sha1-DvNgEqH7qSiWIgVRS0b2NcZS8jU=" - }, - "relay-runtime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-1.4.1.tgz", - "integrity": "sha512-hsEVCPik0Wo+8xvVqaMK96d45fqYAcHz/UCAw2qy1dxY+2kHUhnDUh6CGilFKB1H3f+DLzvqIHUyNYKWS/jZ/g==", - "requires": { - "babel-runtime": "6.26.0", - "fbjs": "0.8.16", - "relay-debugger-react-native-runtime": "0.0.10" - } - }, - "remote-redux-devtools": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/remote-redux-devtools/-/remote-redux-devtools-0.5.12.tgz", - "integrity": "sha1-QsuV36nlTB2WcTF8Xnu6QeaMrsI=", - "requires": { - "jsan": "3.1.9", - "querystring": "0.2.0", - "redux-devtools-instrument": "1.8.2", - "remotedev-utils": "0.1.4", - "rn-host-detect": "1.1.3", - "socketcluster-client": "5.5.2" - } - }, - "remotedev-serialize": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/remotedev-serialize/-/remotedev-serialize-0.1.0.tgz", - "integrity": "sha1-B0do6Yy3qoBvRZlO6wyK+VEg7jI=", - "requires": { - "jsan": "3.1.9" - } - }, - "remotedev-utils": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/remotedev-utils/-/remotedev-utils-0.1.4.tgz", - "integrity": "sha1-ZDcAgZqUNngHPHXrGF6B2WYgs0g=", - "requires": { - "get-params": "0.1.2", - "jsan": "3.1.9", - "lodash": "4.17.4", - "remotedev-serialize": "0.1.0", - "shortid": "2.2.8" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "renderkid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", - "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", - "requires": { - "css-select": "1.2.0", - "dom-converter": "0.1.4", - "htmlparser2": "3.3.0", - "strip-ansi": "3.0.1", - "utila": "0.3.3" - }, - "dependencies": { - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=" - } - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "1.0.2" - } - }, - "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.1", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-like": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "requires": { - "resolve-from": "3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" - }, - "resolve-pathname": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", - "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "retry": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", - "optional": true - }, - "rgb": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/rgb/-/rgb-0.1.0.tgz", - "integrity": "sha1-vieykej+/+rBvZlylyG/pA/AN7U=" - }, - "rgb-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-1.0.0.tgz", - "integrity": "sha1-v6+M2c2RZLWibXHrTxWgllMks8E=" - }, - "ric": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ric/-/ric-1.3.0.tgz", - "integrity": "sha1-jpUEJgnOghNUioMWTQjpT66UkJ8=" - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "7.1.2" - } - }, - "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.3" - } - }, - "rn-host-detect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/rn-host-detect/-/rn-host-detect-1.1.3.tgz", - "integrity": "sha1-JC124vpIXEjXUUFuZbfM5ZaWnpE=" - }, - "rollup": { - "version": "0.36.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.36.4.tgz", - "integrity": "sha1-oiRJTFOGwdc9OPe7hvafXrARo9I=", - "optional": true, - "requires": { - "source-map-support": "0.4.18" - } - }, - "rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==" - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "requires": { - "rx-lite": "4.0.8" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "sane": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-1.7.0.tgz", - "integrity": "sha1-s1ebzLRclM8gNVzIESSZDf00bjA=", - "optional": true, - "requires": { - "anymatch": "1.3.2", - "exec-sh": "0.2.1", - "fb-watchman": "2.0.0", - "minimatch": "3.0.4", - "minimist": "1.2.0", - "walker": "1.0.7", - "watch": "0.10.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "optional": true - } - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "sc-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/sc-channel/-/sc-channel-1.0.6.tgz", - "integrity": "sha1-s4vUepk+eCkPvFNGeGf2sqCghjk=", - "requires": { - "sc-emitter": "1.1.0" - } - }, - "sc-emitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/sc-emitter/-/sc-emitter-1.1.0.tgz", - "integrity": "sha1-7xGdQiL0xk+Ie0hpZO8REWzdDnU=", - "requires": { - "component-emitter": "1.2.0" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.0.tgz", - "integrity": "sha1-zNETqGOI0GSC0D3j/H35hSa6jv4=" - } - } - }, - "sc-errors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/sc-errors/-/sc-errors-1.3.3.tgz", - "integrity": "sha1-wAvEx2apcMyNWTfQjNWOkx19rgU=" - }, - "sc-formatter": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sc-formatter/-/sc-formatter-3.0.2.tgz", - "integrity": "sha512-9PbqYBpCq+OoEeRQ3QfFIGE6qwjjBcd2j7UjgDlhnZbtSnuGgHdcRklPKYGuYFH82V/dwd+AIpu8XvA1zqTd+A==" - }, - "scroll-behavior": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/scroll-behavior/-/scroll-behavior-0.9.5.tgz", - "integrity": "sha512-/5CtMX6YHmCrcV6AICYqFpNqYgx5v6YOyDTeMgVFdLZpgU+T3JXmgV+9s4R+uApcyYwcc7o8Nwp7VTt/ue8y0Q==", - "requires": { - "dom-helpers": "3.3.1", - "invariant": "2.2.2" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "requires": { - "semver": "5.5.0" - } - }, - "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", - "requires": { - "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "fresh": "0.5.2", - "http-errors": "1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" - }, - "dependencies": { - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - } - } - }, - "serve": { - "version": "6.4.8", - "resolved": "https://registry.npmjs.org/serve/-/serve-6.4.8.tgz", - "integrity": "sha512-RiQKBV2pAqb2YhyyRJFqSN+wHKZIlZW7GPgVB7rji6gWNBQcjWso/tpV179vTIgqCfIAsS5T4LPE8WVrqOwkFQ==", - "requires": { - "@zeit/check-updates": "1.0.5", - "args": "3.0.8", - "basic-auth": "2.0.0", - "bluebird": "3.5.1", - "boxen": "1.3.0", - "chalk": "2.3.0", - "clipboardy": "1.2.2", - "dargs": "5.1.0", - "detect-port": "1.2.2", - "filesize": "3.5.11", - "fs-extra": "5.0.0", - "handlebars": "4.0.11", - "ip": "1.1.5", - "micro": "9.1.0", - "micro-compress": "1.0.0", - "mime-types": "2.1.17", - "node-version": "1.1.0", - "openssl-self-signed-certificate": "1.1.6", - "opn": "5.1.0", - "path-type": "3.0.0", - "send": "0.16.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "opn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", - "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", - "requires": { - "is-wsl": "1.1.0" - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { - "pify": "3.0.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "requires": { - "accepts": "1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "1.0.3", - "http-errors": "1.6.2", - "mime-types": "2.1.17", - "parseurl": "1.3.2" - } - }, - "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", - "requires": { - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "requires": { - "to-object-path": "0.3.0" - } - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "sha.js": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", - "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "shallowequal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.0.2.tgz", - "integrity": "sha512-zlVXeVUKvo+HEv1e2KQF/csyeMKx2oHvatQ9l6XjCUj3agvC8XGf6R9HvIPDSmp8FNPvx7b5kaEJTRi7CqxtEw==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "requires": { - "array-filter": "0.0.1", - "array-map": "0.0.0", - "array-reduce": "0.0.0", - "jsonify": "0.0.0" - } - }, - "shelljs": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.0.tgz", - "integrity": "sha1-P28uSWXOxWX2X/OGHWRPh5KBpXY=", - "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" - }, - "dependencies": { - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" - } - } - }, - "shortid": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.8.tgz", - "integrity": "sha1-AzsRfWoul1gE9vCWnb59PQs1UTE=" - }, - "sift": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/sift/-/sift-3.3.12.tgz", - "integrity": "sha1-T1zfFq89syr6BKslKXsOIK2YKUo=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "signedsource": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/signedsource/-/signedsource-1.0.0.tgz", - "integrity": "sha1-HdrOSYF5j5O9gzlzgD2A1S6TrWo=" - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "snapdragon": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "3.2.2" - } - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.2.0" - } - }, - "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", - "requires": { - "debug": "2.6.9", - "engine.io": "3.1.4", - "socket.io-adapter": "1.1.1", - "socket.io-client": "2.0.4", - "socket.io-parser": "3.1.2" - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" - }, - "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "2.6.9", - "engine.io-client": "3.1.4", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "3.1.2", - "to-array": "0.1.4" - } - }, - "socket.io-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.2.tgz", - "integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=", - "requires": { - "component-emitter": "1.2.1", - "debug": "2.6.9", - "has-binary2": "1.0.2", - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "socketcluster-client": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/socketcluster-client/-/socketcluster-client-5.5.2.tgz", - "integrity": "sha1-nUNp4Oci/35V5UIsLUT1r+Gv8Sg=", - "requires": { - "base-64": "0.1.0", - "clone": "2.1.1", - "linked-list": "0.1.0", - "querystring": "0.2.0", - "sc-channel": "1.0.6", - "sc-emitter": "1.1.0", - "sc-errors": "1.3.3", - "sc-formatter": "3.0.2", - "ws": "3.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" - } - } - }, - "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", - "requires": { - "faye-websocket": "0.10.0", - "uuid": "3.2.1" - }, - "dependencies": { - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "requires": { - "websocket-driver": "0.7.0" - } - } - } - }, - "sockjs-client": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", - "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", - "requires": { - "debug": "2.6.9", - "eventsource": "0.1.6", - "faye-websocket": "0.11.1", - "inherits": "2.0.3", - "json3": "3.3.2", - "url-parse": "1.2.0" - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "requires": { - "is-plain-obj": "1.1.0" - } - }, - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "requires": { - "atob": "2.0.3", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "requires": { - "source-map": "0.5.7" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "sourcemapped-stacktrace": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/sourcemapped-stacktrace/-/sourcemapped-stacktrace-1.1.8.tgz", - "integrity": "sha512-OkVoI7GQOLl/laR1qsSo1c87tS8kF2VXhQq2SrQCDdXufBAcm8FgXogWso96ciMYoDtTw1Dn70CVdwYzoYs6Pg==", - "requires": { - "source-map": "0.5.6" - }, - "dependencies": { - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" - } - } - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "requires": { - "spdx-license-ids": "1.2.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" - }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "stackframe": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", - "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "static-site-generator-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-3.4.1.tgz", - "integrity": "sha1-buIkaIMLxUZ5ijfg/Kb9aZzJO4E=", - "requires": { - "bluebird": "3.5.1", - "cheerio": "0.22.0", - "eval": "0.1.2", - "url": "0.11.0", - "webpack-sources": "0.2.3" - }, - "dependencies": { - "source-list-map": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-1.1.2.tgz", - "integrity": "sha1-mIkBnRAkzOVc3AaUmDN+9hhqEaE=" - }, - "webpack-sources": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.2.3.tgz", - "integrity": "sha1-F8Yr+vE8cH+dAsR54Nzd6DgGl/s=", - "requires": { - "source-list-map": "1.1.2", - "source-map": "0.5.7" - } - } - } - }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" - }, - "steno": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", - "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", - "requires": { - "graceful-fs": "4.1.11" - } - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3" - } - }, - "stream-cache": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stream-cache/-/stream-cache-0.0.2.tgz", - "integrity": "sha1-GsWtaDJCjKVWZ9ve45Xa1ObbEY8=" - }, - "stream-http": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", - "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" - } - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" - }, - "string-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", - "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=", - "requires": { - "strip-ansi": "3.0.1" - } - }, - "string-similarity": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.0.tgz", - "integrity": "sha1-11FTyzg4RjGLejmo2SkrtNtOnDA=", - "requires": { - "lodash": "4.17.4" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "style-loader": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.2.tgz", - "integrity": "sha1-dFMzhM9pjHEEx5URULSXF63C87s=", - "requires": { - "loader-utils": "1.1.0" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" - } - }, - "symbol": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz", - "integrity": "sha1-O5hzuKkB5Hxu/iFSajrDcu8ou8c=" - }, - "symbol-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz", - "integrity": "sha512-dQoid9tqQ+uotGhuTKEY11X4xhyYePVnqGSoSm3OGKh2E8LZ6RPULp1uXTctk33IeERlrRJYoVSBglsL05F5Uw==" - }, - "systemjs": { - "version": "0.20.19", - "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-0.20.19.tgz", - "integrity": "sha512-H/rKwNEEyej/+IhkmFNmKFyJul8tbH/muiPq5TyNoVTwsGhUjRsN3NlFnFQUvFXA3+GQmsXkCNXU6QKPl779aw==", - "optional": true - }, - "systemjs-builder": { - "version": "0.16.12", - "resolved": "https://registry.npmjs.org/systemjs-builder/-/systemjs-builder-0.16.12.tgz", - "integrity": "sha512-E+INOPzUsi1VpXat3GYDKl1Xap3Acv3Bw6KmRC9TdpfdJnTk6Jh5K07DdM8P+LEPXZaLZvTaaN/5q2i+1FD1vA==", - "optional": true, - "requires": { - "babel-core": "6.26.0", - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-amd-system-wrapper": "0.3.7", - "babel-plugin-transform-cjs-system-wrapper": "0.6.2", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-global-system-wrapper": "0.3.4", - "babel-plugin-transform-system-register": "0.0.1", - "bluebird": "3.5.1", - "data-uri-to-buffer": "0.0.4", - "es6-template-strings": "2.0.1", - "glob": "7.1.2", - "mkdirp": "0.5.1", - "rollup": "0.36.4", - "source-map": "0.5.7", - "systemjs": "0.19.47", - "traceur": "0.0.105", - "uglify-js": "2.8.29" - }, - "dependencies": { - "systemjs": { - "version": "0.19.47", - "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-0.19.47.tgz", - "integrity": "sha1-yMk5NxgPP1SBx2nNJyB2P7SjHG8=", - "optional": true, - "requires": { - "when": "3.7.8" - } - } - } - }, - "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=" - }, - "tar-fs": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.0.tgz", - "integrity": "sha512-I9rb6v7mjWLtOfCau9eH5L7sLJyU2BnxtEZRQ5Mt+eRKmf1F0ohXmT/Jc3fr52kDvjJ/HV5MH3soQfPL5bQ0Yg==", - "requires": { - "chownr": "1.0.1", - "mkdirp": "0.5.1", - "pump": "1.0.3", - "tar-stream": "1.5.5" - } - }, - "tar-stream": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", - "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", - "requires": { - "bl": "1.2.1", - "end-of-stream": "1.4.1", - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "requires": { - "execa": "0.7.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=" - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" - }, - "timers-browserify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", - "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", - "requires": { - "setimmediate": "1.0.5" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "optional": true - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "3.2.2" - } - }, - "to-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", - "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", - "requires": { - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "regex-not": "1.0.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - } - } - } - }, - "topo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", - "requires": { - "hoek": "4.2.0" - } - }, - "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "requires": { - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "traceur": { - "version": "0.0.105", - "resolved": "https://registry.npmjs.org/traceur/-/traceur-0.0.105.tgz", - "integrity": "sha1-XPne6D1rd4YcPWxE1ThZrterBHk=", - "requires": { - "commander": "2.9.0", - "glob": "5.0.15", - "rsvp": "3.6.2", - "semver": "4.3.6", - "source-map-support": "0.2.10" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" - }, - "source-map": { - "version": "0.1.32", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", - "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", - "requires": { - "amdefine": "1.0.1" - } - }, - "source-map-support": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", - "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", - "requires": { - "source-map": "0.1.32" - } - } - } - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.17" - } - }, - "type-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-of/-/type-of-2.0.1.tgz", - "integrity": "sha1-5yoXQYllaOn2KDeNgW1pEvfyOXI=" - }, - "ua-parser-js": { - "version": "0.7.17", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", - "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" - }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", - "requires": { - "macaddress": "0.2.8" - } - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "requires": { - "crypto-random-string": "1.0.0" - } - }, - "units-css": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/units-css/-/units-css-0.4.0.tgz", - "integrity": "sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc=", - "requires": { - "isnumeric": "0.2.0", - "viewport-dimensions": "0.2.0" - } - }, - "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" - }, - "update-notifier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.3.0.tgz", - "integrity": "sha1-TognpruRUUCrCTVZ1wFOPruDdFE=", - "requires": { - "boxen": "1.3.0", - "chalk": "2.3.0", - "configstore": "3.1.1", - "import-lazy": "2.1.0", - "is-installed-globally": "0.1.0", - "is-npm": "1.0.0", - "latest-version": "3.1.0", - "semver-diff": "2.1.0", - "xdg-basedir": "3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "url-loader": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.5.9.tgz", - "integrity": "sha512-B7QYFyvv+fOBqBVeefsxv6koWWtjmHaMFT6KZWti4KRw8YUD/hOU+3AECvXuzyVawIBx3z7zQRejXCDSO5kk1Q==", - "requires": { - "loader-utils": "1.1.0", - "mime": "1.3.6" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - }, - "mime": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", - "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=" - } - } - }, - "url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", - "requires": { - "querystringify": "1.0.0", - "requires-port": "1.0.0" - }, - "dependencies": { - "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "requires": { - "prepend-http": "1.0.4" - } - }, - "use": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", - "requires": { - "define-property": "0.2.5", - "isobject": "3.0.1", - "lazy-cache": "2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - }, - "uws": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz", - "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", - "optional": true - }, - "v8-compile-cache": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-1.1.0.tgz", - "integrity": "sha1-HcKjQPuOX4AKMrzb+4wjzXRwIbk=" - }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - } - }, - "value-equal": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", - "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "vendors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", - "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - } - }, - "viewport-dimensions": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz", - "integrity": "sha1-3nQHR9tTh/0XJfUXXpG6x2r982w=" - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "requires": { - "indexof": "0.0.1" - } - }, - "walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "optional": true, - "requires": { - "makeerror": "1.0.11" - } - }, - "warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "requires": { - "loose-envify": "1.3.1" - } - }, - "watch": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz", - "integrity": "sha1-d3mLLaD5kQ1ZXxrOWwwiWFIfIdw=", - "optional": true - }, - "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", - "requires": { - "async": "0.9.2", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - } - } - }, - "webpack": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", - "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "requires": { - "acorn": "3.3.0", - "async": "1.5.2", - "clone": "1.0.3", - "enhanced-resolve": "0.9.1", - "interpret": "0.6.6", - "loader-utils": "0.2.17", - "memory-fs": "0.3.0", - "mkdirp": "0.5.1", - "node-libs-browser": "0.7.0", - "optimist": "0.6.1", - "supports-color": "3.2.3", - "tapable": "0.1.10", - "uglify-js": "2.7.5", - "watchpack": "0.2.9", - "webpack-core": "0.6.9" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - }, - "browserify-aes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", - "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", - "requires": { - "inherits": "2.0.3" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "requires": { - "pako": "0.2.9" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "crypto-browserify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", - "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", - "requires": { - "browserify-aes": "0.4.0", - "pbkdf2-compat": "2.0.1", - "ripemd160": "0.2.0", - "sha.js": "2.2.6" - } - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" - }, - "node-libs-browser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", - "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.1.4", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "1.1.7", - "events": "1.1.1", - "https-browserify": "0.0.1", - "os-browserify": "0.2.1", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.3", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "0.10.31", - "timers-browserify": "2.0.4", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4" - } - }, - "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=" - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "ripemd160": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", - "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=" - }, - "sha.js": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", - "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "requires": { - "has-flag": "1.0.0" - } - }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" - } - } - }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", - "requires": { - "source-list-map": "0.1.8", - "source-map": "0.4.4" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "webpack-configurator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/webpack-configurator/-/webpack-configurator-0.3.1.tgz", - "integrity": "sha1-0WgCr6Z0EBoMv6b8NE1BXJZJVAs=", - "requires": { - "lodash": "3.10.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } - }, - "webpack-core": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.4.8.tgz", - "integrity": "sha1-B/xVq6gdF9uoyuWkPWvWkjb4tfg=", - "requires": { - "source-map": "0.1.43" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", - "requires": { - "memory-fs": "0.4.1", - "mime": "1.6.0", - "path-is-absolute": "1.0.1", - "range-parser": "1.2.0", - "time-stamp": "2.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "requires": { - "errno": "0.1.6", - "readable-stream": "2.3.3" - } - } - } - }, - "webpack-dev-server": { - "version": "1.16.5", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-1.16.5.tgz", - "integrity": "sha1-DL1fLSrI1OWTqs1clwLnu9XlmJI=", - "requires": { - "compression": "1.7.1", - "connect-history-api-fallback": "1.5.0", - "express": "4.16.2", - "http-proxy-middleware": "0.17.4", - "open": "0.0.5", - "optimist": "0.6.1", - "serve-index": "1.9.1", - "sockjs": "0.3.19", - "sockjs-client": "1.1.4", - "stream-cache": "0.0.2", - "strip-ansi": "3.0.1", - "supports-color": "3.2.3", - "webpack-dev-middleware": "1.12.2" - }, - "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "webpack-hot-middleware": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.21.0.tgz", - "integrity": "sha512-P6xiOLy10QlSVSO7GanU9PLxN6zLLQ7RG16MPTvmFwf2KUG7jMp6m+fmdgsR7xoaVVLA7OlX3YO6JjoZEKjCuA==", - "requires": { - "ansi-html": "0.0.7", - "html-entities": "1.2.1", - "querystring": "0.2.0", - "strip-ansi": "3.0.1" - } - }, - "webpack-md5-hash": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/webpack-md5-hash/-/webpack-md5-hash-0.0.5.tgz", - "integrity": "sha1-2fGJnq1mRFndi2sMkmrHHPvXvHo=", - "requires": { - "md5": "2.2.1" - } - }, - "webpack-sources": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.1.5.tgz", - "integrity": "sha1-qh86vw8NdNtxEcQOUAuE+WZkB1A=", - "requires": { - "source-list-map": "0.1.8", - "source-map": "0.5.7" - } - }, - "webpack-stats-plugin": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/webpack-stats-plugin/-/webpack-stats-plugin-0.1.5.tgz", - "integrity": "sha1-KeXxLr/VMVjTHWVqETrB97hhedk=" - }, - "webpack-validator": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/webpack-validator/-/webpack-validator-2.3.0.tgz", - "integrity": "sha1-I1xuppqpMKkCYru/m9Ra2L1JcxA=", - "requires": { - "basename": "0.1.2", - "chalk": "1.1.3", - "commander": "2.9.0", - "common-tags": "0.1.1", - "cross-env": "3.2.4", - "find-node-modules": "1.0.4", - "joi": "9.0.0-0", - "lodash": "4.11.1", - "npmlog": "2.0.3", - "shelljs": "0.7.0", - "yargs": "4.7.1" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, - "common-tags": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-0.1.1.tgz", - "integrity": "sha1-2JNIbsxt8iz/5sOTyIwS9x5+iHE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isemail": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz", - "integrity": "sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=" - }, - "joi": { - "version": "9.0.0-0", - "resolved": "https://registry.npmjs.org/joi/-/joi-9.0.0-0.tgz", - "integrity": "sha1-p8pCGWAhSa4Np6fFyh1j08eeCWs=", - "requires": { - "hoek": "4.2.0", - "isemail": "2.2.1", - "items": "2.1.1", - "moment": "2.20.1", - "topo": "2.0.2" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "lodash": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.11.1.tgz", - "integrity": "sha1-oyEG644uyOgsJBYRQUdzyd8V+Lw=" - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "set-blocking": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-1.0.0.tgz", - "integrity": "sha1-zV5dk4BI3xrJLf6S4fFq3WVvXsU=" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "0.2.1" - } - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" - }, - "yargs": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.7.1.tgz", - "integrity": "sha1-5gQyZYozh/8mnAKOrN5KUS5Djf8=", - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "pkg-conf": "1.1.3", - "read-pkg-up": "1.0.1", - "require-main-filename": "1.0.1", - "set-blocking": "1.0.0", - "string-width": "1.0.2", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" - } - } - } - }, - "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "requires": { - "http-parser-js": "0.4.9", - "websocket-extensions": "0.1.3" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" - }, - "whatwg-fetch": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", - "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" - }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "optional": true - }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=" - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "widest-line": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", - "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", - "requires": { - "string-width": "2.1.1" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" - } - }, - "ws": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.0.0.tgz", - "integrity": "sha1-mN2wAFbIOQy3Ued4h4hJf5kQO2w=", - "requires": { - "safe-buffer": "5.0.1", - "ultron": "1.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" - } - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "yaml-loader": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.4.0.tgz", - "integrity": "sha1-Sq5EfRPBqnOpidiipTCbCxo8o1M=", - "requires": { - "js-yaml": "3.7.0" - } - }, - "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" - } - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "requires": { - "camelcase": "4.1.0" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - }, - "yurnalist": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/yurnalist/-/yurnalist-0.2.1.tgz", - "integrity": "sha1-LTK5YYq2SRiRwTG9kKUpXhn9S60=", - "requires": { - "chalk": "1.1.3", - "death": "1.1.0", - "debug": "2.6.9", - "detect-indent": "5.0.0", - "inquirer": "3.3.0", - "invariant": "2.2.2", - "is-builtin-module": "1.0.0", - "is-ci": "1.1.0", - "leven": "2.1.0", - "loud-rejection": "1.6.0", - "node-emoji": "1.8.1", - "object-path": "0.11.4", - "read": "1.0.7", - "rimraf": "2.6.2", - "semver": "5.5.0", - "strip-bom": "3.0.0" - }, - "dependencies": { - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" - } - } - } - } -} diff --git a/website/package.json b/website/package.json index 33ba8cd0..6e9dc51b 100644 --- a/website/package.json +++ b/website/package.json @@ -4,22 +4,22 @@ "version": "1.0.0", "author": "Kyle Mathews ", "dependencies": { - "antd": "^3.2.0", - "atob": "^2.0.3", + "antd": "^3.6.5", + "atob": "^2.1.1", "btoa": "^1.2.1", - "gatsby": "^1.9.158", - "gatsby-link": "^1.6.34", - "gatsby-plugin-antd": "^1.0.10", - "gatsby-plugin-google-analytics": "^1.0.19", - "gatsby-plugin-less": "^1.1.4", - "gatsby-plugin-react-helmet": "^2.0.3", - "gatsby-plugin-react-next": "^1.0.8", - "gatsby-remark-prismjs": "^1.2.14", - "gatsby-source-filesystem": "^1.5.18", - "gatsby-transformer-remark": "^1.7.31", + "gatsby": "^1.9.273", + "gatsby-link": "^1.6.45", + "gatsby-plugin-antd": "^1.0.12", + "gatsby-plugin-google-analytics": "^1.0.31", + "gatsby-plugin-less": "^1.1.8", + "gatsby-plugin-react-helmet": "^2.0.11", + "gatsby-plugin-react-next": "^1.0.11", + "gatsby-remark-prismjs": "^2.0.4", + "gatsby-source-filesystem": "^1.5.39", + "gatsby-transformer-remark": "^1.7.44", "immutable": "^4.0.0-rc.9", "react-helmet": "^5.2.0", - "react-syntax-highlighter": "^7.0.0", + "react-syntax-highlighter": "^8.0.0", "yoga-layout": "^1.9.3" }, "keywords": [ @@ -32,6 +32,6 @@ "develop": "gatsby develop" }, "devDependencies": { - "prettier": "1.13.6" + "prettier": "1.13.7" } } diff --git a/website/yarn.lock b/website/yarn.lock index 4f7f2c84..d55014e7 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -3,71 +3,102 @@ "@babel/helper-module-imports@^7.0.0-beta.34": - version "7.0.0-beta.39" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.39.tgz#39e1fd4b8f5982b05417f73250a620070541192e" + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.51.tgz#ce00428045fbb7d5ebc0ea7bf835789f15366ab2" dependencies: - "@babel/types" "7.0.0-beta.39" - lodash "^4.2.0" + "@babel/types" "7.0.0-beta.51" + lodash "^4.17.5" -"@babel/types@7.0.0-beta.39": - version "7.0.0-beta.39" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.39.tgz#2ea0d97efe4781688751edc68cde640d6559938c" +"@babel/types@7.0.0-beta.51": + version "7.0.0-beta.51" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.51.tgz#d802b7b543b5836c778aa691797abf00f3d97ea9" dependencies: esutils "^2.0.2" - lodash "^4.2.0" + lodash "^4.17.5" to-fast-properties "^2.0.0" +"@types/configstore@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@types/configstore/-/configstore-2.1.1.tgz#cd1e8553633ad3185c3f2f239ecff5d2643e92b6" + +"@types/debug@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.29.tgz#a1e514adfbd92f03a224ba54d693111dbf1f3754" + +"@types/estree@0.0.38": + version "0.0.38" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.38.tgz#c1be40aa933723c608820a99a373a16d215a1ca2" + +"@types/events@*": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" + +"@types/get-port@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/get-port/-/get-port-0.0.4.tgz#eb6bb7423d9f888b632660dc7d2fd3e69a35643e" + +"@types/glob@^5.0.30": + version "5.0.35" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + "@types/history@*", "@types/history@^4.6.2": version "4.6.2" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.6.2.tgz#12cfaba693ba20f114ed5765467ff25fdf67ddb0" +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + +"@types/mkdirp@^0.3.29": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.3.29.tgz#7f2ad7ec55f914482fc9b1ec4bb1ae6028d46066" + "@types/node@*": - version "4.0.36" - resolved "https://registry.yarnpkg.com/@types/node/-/node-4.0.36.tgz#394672a25c7d49b48698d5fb59d3ea72d2b6e5fa" + version "10.5.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.1.tgz#d578446f4abff5c0b49ade9b4e5274f6badaadfc" + +"@types/node@^7.0.11": + version "7.0.66" + resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.66.tgz#3d1dc4d6f52e484e843806ff456379f7e6ad5553" "@types/react-router-dom@^4.2.2": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.2.3.tgz#06e0b67ff536adc0681dffdbe592ae91fb85887d" + version "4.2.7" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.2.7.tgz#9d36bfe175f916dd8d7b6b0237feed6cce376b4c" dependencies: "@types/history" "*" "@types/react" "*" "@types/react-router" "*" "@types/react-router@*": - version "4.0.21" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-4.0.21.tgz#d6c7ea3b45dba02eb8f869629f3b7d7b6e9a7938" + version "4.0.28" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-4.0.28.tgz#b0445fc38613c81e92ca9ec0e08ab36697d51003" dependencies: "@types/history" "*" "@types/react" "*" "@types/react@*": - version "16.0.36" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.0.36.tgz#ceb5639013bdb92a94147883052e69bb2c22c69b" - -"@zeit/check-updates@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@zeit/check-updates/-/check-updates-1.0.5.tgz#3ac40afe270a0cc646a279b629698a77ad4543c6" + version "16.4.6" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.6.tgz#5024957c6bcef4f02823accf5974faba2e54fada" dependencies: - chalk "^2.3.0" - ms "^2.1.1" - update-notifier "^2.3.0" + csstype "^2.2.0" + +"@types/tmp@^0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.32.tgz#0d3cb31022f8427ea58c008af32b80da126ca4e3" abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" -accepts@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" +accepts@^1.3.0, accepts@~1.3.4, accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" dependencies: - mime-types "~2.1.11" - negotiator "0.6.1" - -accepts@^1.3.0, accepts@~1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" - dependencies: - mime-types "~2.1.16" + mime-types "~2.1.18" negotiator "0.6.1" acorn@^3.0.0: @@ -95,7 +126,7 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^5.1.0: +ajv@^5.0.0, ajv@^5.1.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: @@ -126,13 +157,9 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - ansi-escapes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" ansi-html@0.0.7: version "0.0.7" @@ -150,9 +177,9 @@ 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.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" @@ -160,9 +187,9 @@ ansi@^0.3.0, ansi@~0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" -antd@^3.1.0, antd@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/antd/-/antd-3.2.0.tgz#83f2980f1e73a4147dce3d643c749bd8ba91d057" +antd@^3.5.1, antd@^3.6.5: + version "3.6.5" + resolved "https://registry.yarnpkg.com/antd/-/antd-3.6.5.tgz#bed51a7e8c557a9c6331065087929f8ac4800cb2" dependencies: array-tree-filter "^2.0.0" babel-runtime "6.x" @@ -171,41 +198,43 @@ antd@^3.1.0, antd@^3.2.0: css-animation "^1.2.5" dom-closest "^0.2.0" enquire.js "^2.1.1" - lodash.debounce "^4.0.8" + intersperse "^1.0.0" + lodash "^4.17.5" moment "^2.19.3" omit.js "^1.0.0" prop-types "^15.5.7" + raf "^3.4.0" rc-animate "^2.4.1" - rc-calendar "~9.5.0" - rc-cascader "~0.12.0" - rc-checkbox "~2.1.1" - rc-collapse "~1.8.0" + rc-calendar "~9.6.0" + rc-cascader "~0.13.0" + rc-checkbox "~2.1.5" + rc-collapse "~1.9.0" rc-dialog "~7.1.0" rc-dropdown "~2.1.0" rc-editor-mention "^1.0.2" rc-form "^2.1.0" rc-input-number "~4.0.0" - rc-menu "~6.2.0" - rc-notification "~3.0.0" - rc-pagination "~1.15.0" + rc-menu "~7.0.2" + rc-notification "~3.1.1" + rc-pagination "~1.16.1" rc-progress "~2.2.2" rc-rate "~2.4.0" - rc-select "~7.7.0" + rc-select "~8.0.7" rc-slider "~8.6.0" rc-steps "~3.1.0" rc-switch "~1.6.0" rc-table "~6.1.0" rc-tabs "~9.2.0" - rc-time-picker "~3.2.1" + rc-time-picker "~3.3.0" rc-tooltip "~3.7.0" - rc-tree "~1.7.0" + rc-tree "~1.8.0" rc-tree-select "~1.12.0" rc-upload "~2.4.0" rc-util "^4.0.4" react-lazy-load "^3.0.12" - react-slick "~0.17.0" + react-slick "~0.23.1" shallowequal "^1.0.1" - warning "~3.0.0" + warning "~4.0.1" any-promise@^0.1.0: version "0.1.0" @@ -223,31 +252,34 @@ aproba@^1.0.3: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" arch@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" + version "2.1.1" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" dependencies: delegates "^1.0.0" readable-stream "^2.0.6" +arg@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arg/-/arg-2.0.0.tgz#c06e7ff69ab05b3a4a03ebe0407fac4cba657545" + argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" -args@3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/args/-/args-3.0.8.tgz#2f425ab639c69d74ff728f3d7c6e93b97b91af7c" +args@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/args/-/args-4.0.0.tgz#5ca24cdba43d4b17111c56616f5f2e9d91933954" dependencies: - camelcase "4.1.0" - chalk "2.1.0" + camelcase "5.0.0" + chalk "2.3.2" + leven "2.1.0" mri "1.1.0" - pkginfo "0.4.1" - string-similarity "1.2.0" arr-diff@^2.0.0: version "2.0.0" @@ -284,8 +316,8 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" array-iterate@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.1.tgz#865bf7f8af39d6b0982c60902914ac76bc0108f6" + version "1.1.2" + resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.2.tgz#f66a57e84426f8097f4197fbb6c051b8e5cdf7d8" array-map@~0.0.0: version "0.0.0" @@ -334,8 +366,8 @@ asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" asn1.js@^4.0.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -386,10 +418,10 @@ async@^1.3.0, async@^1.4.0, async@^1.5.0: resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" async@^2.1.2: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: - lodash "^4.14.0" + lodash "^4.17.10" async@~0.2.6: version "0.2.10" @@ -399,9 +431,9 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -atob@^2.0.0, atob@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" autogypi@^0.2.2: version "0.2.2" @@ -431,8 +463,8 @@ aws-sign2@~0.7.0: resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" babel-cli@^6.26.0: version "6.26.0" @@ -464,8 +496,8 @@ babel-code-frame@6.26.0, babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, bab js-tokens "^3.0.2" babel-core@^6.24.1, babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -477,15 +509,15 @@ babel-core@^6.24.1, babel-core@^6.26.0: babel-traverse "^6.26.0" babel-types "^6.26.0" babylon "^6.18.0" - convert-source-map "^1.5.0" - debug "^2.6.8" + convert-source-map "^1.5.1" + debug "^2.6.9" json5 "^0.5.1" lodash "^4.17.4" minimatch "^3.0.4" path-is-absolute "^1.0.1" - private "^0.1.7" + private "^0.1.8" slash "^1.0.0" - source-map "^0.5.6" + source-map "^0.5.7" babel-generator@^6.24.1, babel-generator@^6.26.0: version "6.26.1" @@ -651,9 +683,9 @@ babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants dependencies: babel-runtime "^6.22.0" -babel-plugin-import@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-import/-/babel-plugin-import-1.6.3.tgz#f4deeac51ff9f997c9cf38e8d7d7b9142504eaf5" +babel-plugin-import@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-import/-/babel-plugin-import-1.8.0.tgz#260deddd78f6fea0d110e1d106ba72a518d3c88c" dependencies: "@babel/helper-module-imports" "^7.0.0-beta.34" @@ -860,8 +892,8 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-template "^6.24.1" babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.8.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -1048,14 +1080,6 @@ babel-plugin-transform-system-register@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-system-register/-/babel-plugin-transform-system-register-0.0.1.tgz#9dff40390c2763ac518f0b2ad7c5ea4f65a5be25" -babel-polyfill@6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - babel-polyfill@^6.20.0, babel-polyfill@^6.23.0, babel-polyfill@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" @@ -1065,8 +1089,8 @@ babel-polyfill@^6.20.0, babel-polyfill@^6.23.0, babel-polyfill@^6.26.0: regenerator-runtime "^0.10.5" babel-preset-env@^1.6.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -1095,7 +1119,7 @@ babel-preset-env@^1.6.0: babel-plugin-transform-es2015-unicode-regex "^6.22.0" babel-plugin-transform-exponentiation-operator "^6.22.0" babel-plugin-transform-regenerator "^6.22.0" - browserslist "^2.1.2" + browserslist "^3.2.6" invariant "^2.2.2" semver "^5.3.0" @@ -1274,8 +1298,8 @@ backo2@1.0.2: resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" bail@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764" + version "1.0.3" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" balanced-match@0.1.0: version "0.1.0" @@ -1302,8 +1326,8 @@ base64-arraybuffer@0.1.5: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" base64-js@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" base64id@1.0.0: version "1.0.0" @@ -1355,8 +1379,8 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" dependencies: tweetnacl "^0.14.3" @@ -1370,9 +1394,9 @@ better-queue-memory@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/better-queue-memory/-/better-queue-memory-1.0.2.tgz#aa6d169aa1d0cc77409185cb9cb5c7dc251bcd41" -better-queue@^3.8.6: - version "3.8.6" - resolved "https://registry.yarnpkg.com/better-queue/-/better-queue-3.8.6.tgz#73220bdfab403924cffa7497220dd387abb73a63" +better-queue@^3.8.6, better-queue@^3.8.7: + version "3.8.7" + resolved "https://registry.yarnpkg.com/better-queue/-/better-queue-3.8.7.tgz#de39b82b05f55d92ba065c9066958dad80789ab3" dependencies: better-queue-memory "^1.0.1" node-eta "^0.9.0" @@ -1387,10 +1411,11 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" bl@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" dependencies: - readable-stream "^2.0.5" + readable-stream "^2.3.5" + safe-buffer "^5.1.1" blob@0.0.4: version "0.0.4" @@ -1435,18 +1460,6 @@ boom@2.x.x: dependencies: hoek "2.x.x" -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - dependencies: - hoek "4.x.x" - boxen@1.3.0, boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -1460,8 +1473,8 @@ boxen@1.3.0, boxen@^1.2.1: widest-line "^2.0.0" brace-expansion@^1.0.0, brace-expansion@^1.1.7: - version "1.1.9" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.9.tgz#acdc7dde0e939fb3b32fe933336573e2a7dc2b7c" + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1474,13 +1487,12 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -braces@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" - define-property "^1.0.0" extend-shallow "^2.0.1" fill-range "^4.0.0" isobject "^3.0.1" @@ -1501,8 +1513,8 @@ browserify-aes@0.4.0: inherits "^2.0.1" browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1512,16 +1524,16 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: safe-buffer "^5.0.1" browserify-cipher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" evp_bytestokey "^1.0.0" browserify-des@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.1.tgz#3343124db6d7ad53e26a8826318712bdc8450f9c" dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1565,12 +1577,12 @@ browserslist@^1.0.0, browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7 caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" -browserslist@^2.1.2: - version "2.11.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" dependencies: - caniuse-lite "^1.0.30000792" - electron-to-chromium "^1.3.30" + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" bser@^2.0.0: version "2.0.0" @@ -1582,20 +1594,20 @@ btoa@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" -buffer-alloc-unsafe@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz#ffe1f67551dd055737de253337bfe853dfab1a6a" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" buffer-alloc@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.1.0.tgz#05514d33bf1656d3540c684f65b1202e90eca303" + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" dependencies: - buffer-alloc-unsafe "^0.1.0" - buffer-fill "^0.1.0" + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" -buffer-fill@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-0.1.0.tgz#ca9470e8d4d1b977fd7543f4e2ab6a7dc95101a8" +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" buffer-peek-stream@^1.0.1: version "1.0.1" @@ -1647,9 +1659,9 @@ callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" -camelcase@4.1.0, camelcase@^4.0.0, 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.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" camelcase@^1.0.2: version "1.2.1" @@ -1659,9 +1671,9 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -can-use-dom@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" caniuse-api@^1.5.2, caniuse-api@^1.5.3: version "1.6.1" @@ -1673,12 +1685,12 @@ caniuse-api@^1.5.2, caniuse-api@^1.5.3: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000805" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000805.tgz#8f1ad9264c835989b5055dd9b009513ce6d95338" + version "1.0.30000864" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000864.tgz#35a4b2325a8d4553a46b516dbc233bf391d75555" -caniuse-lite@^1.0.30000792: - version "1.0.30000805" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000805.tgz#83a5f21ead01486e67bccca6fae5dca7cde496de" +caniuse-lite@^1.0.30000844: + version "1.0.30000864" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000864.tgz#7a08c78da670f23c06f11aa918831b8f2dd60ddc" capture-stack-trace@^1.0.0: version "1.0.0" @@ -1689,8 +1701,8 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" ccount@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.2.tgz#53b6a2f815bb77b9c2871f7b9a72c3a25f1d8e89" + version "1.0.3" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff" center-align@^0.1.1: version "0.1.3" @@ -1709,37 +1721,45 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" +chalk@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" dependencies: - ansi-styles "^3.1.0" + ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + supports-color "^5.3.0" -chalk@2.3.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" +chalk@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.0.tgz#a060a297a6b57e15b61ca63ce84995daa0fe6e52" dependencies: - ansi-styles "^3.1.0" + ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + supports-color "^5.3.0" + +chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" character-entities-html4@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.1.tgz#359a2a4a0f7e29d3dc2ac99bdbe21ee39438ea50" + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" character-entities-legacy@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz#f40779df1a101872bb510a3d295e1fccf147202f" + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" character-entities@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.1.tgz#f76871be5ef66ddb7f8f8e3478ecc374c27d6dca" + version "1.2.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363" character-reference-invalid@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz#942835f750e4ec61a308e60c2ef8cc1011202efc" + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed" chardet@^0.4.0: version "0.4.2" @@ -1796,8 +1816,8 @@ chunk-manifest-webpack-plugin@0.1.0: webpack-core "^0.4.8" ci-info@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4" + version "1.1.3" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -1821,9 +1841,9 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@2.x, classnames@^2.2.0, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@~2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" +classnames@2.x, classnames@^2.2.0, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6, classnames@~2.2.0: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" cli-boxes@^1.0.0: version "1.0.0" @@ -1839,17 +1859,17 @@ cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" -clipboard@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b" +clipboard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.1.tgz#a12481e1c13d8a50f5f036b0560fe5d16d74e46a" dependencies: good-listener "^1.2.2" select "^1.1.2" tiny-emitter "^2.0.0" -clipboardy@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2" +clipboardy@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" dependencies: arch "^2.1.0" execa "^0.8.0" @@ -1870,6 +1890,14 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -1885,8 +1913,8 @@ clone@2.1.1: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" clone@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" co@^4.6.0: version "4.6.0" @@ -1903,8 +1931,8 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" collapse-white-space@^1.0.0, collapse-white-space@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c" + version "1.0.4" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" collection-visit@^1.0.0: version "1.0.0" @@ -1918,12 +1946,16 @@ color-convert@^0.5.3: resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" color-convert@^1.3.0, color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" dependencies: - color-name "^1.1.1" + color-name "1.1.1" -color-name@^1.0.0, color-name@^1.1.1: +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +color-name@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -1960,18 +1992,22 @@ colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" -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" +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" comma-separated-tokens@^1.0.0, comma-separated-tokens@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.4.tgz#72083e58d4a462f01866f6617f4d98a3cd3b8a46" + version "1.0.5" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz#b13793131d9ea2d2431cf5b507ddec258f0ce0db" dependencies: trim "0.0.1" +command-exists@^1.2.2: + version "1.2.7" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.7.tgz#16828f0c3ff2b0c58805861ef211b64fc15692a8" + commander@2.9.0, commander@2.9.x, commander@~2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -1979,8 +2015,8 @@ commander@2.9.0, commander@2.9.x, commander@~2.9.0: graceful-readlink ">= 1.0.0" commander@^2.11.0: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" common-tags@0.1.1: version "0.1.1" @@ -1989,10 +2025,8 @@ common-tags@0.1.1: babel-runtime "^6.6.1" common-tags@^1.4.0: - version "1.7.2" - resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.7.2.tgz#24d9768c63d253a56ecff93845b44b4df1d52771" - dependencies: - babel-runtime "^6.26.0" + version "1.8.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" commondir@^1.0.1: version "1.0.1" @@ -2024,19 +2058,19 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" -compressible@~2.0.11: - version "2.0.12" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" +compressible@~2.0.13: + version "2.0.14" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7" dependencies: - mime-db ">= 1.30.0 < 2" + mime-db ">= 1.34.0 < 2" compression@^1.5.2, compression@^1.6.2: - version "1.7.1" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" + version "1.7.2" + resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" dependencies: accepts "~1.3.4" bytes "3.0.0" - compressible "~2.0.11" + compressible "~2.0.13" debug "2.6.9" on-headers "~1.0.1" safe-buffer "5.1.1" @@ -2047,8 +2081,8 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" configstore@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" + version "3.1.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" dependencies: dot-prop "^4.1.0" graceful-fs "^4.1.2" @@ -2079,7 +2113,7 @@ content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" -content-type@1.0.4, content-type@^1.0.2, content-type@~1.0.4: +content-type@1.0.4, content-type@^1.0.4, content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -2087,7 +2121,7 @@ convert-hrtime@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-hrtime/-/convert-hrtime-2.0.0.tgz#19bfb2c9162f9e11c2f04c2c79de2b7e8095c627" -convert-source-map@^1.5.0: +convert-source-map@^1.5.0, convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -2119,16 +2153,16 @@ core-js@^1.0.0, core-js@^1.2.6: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.1: - version "2.5.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" create-ecdh@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -2140,17 +2174,18 @@ create-error-class@^3.0.0: capture-stack-trace "^1.0.0" create-hash@^1.1.0, create-hash@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" dependencies: cipher-base "^1.0.1" inherits "^2.0.1" - ripemd160 "^2.0.0" + md5.js "^1.3.4" + ripemd160 "^2.0.1" sha.js "^2.4.0" create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -2192,12 +2227,6 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - dependencies: - boom "5.x.x" - crypto-browserify@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.3.0.tgz#b9fc75bb4a0ed61dcf1cd5dae96eb30c9c3e506c" @@ -2337,6 +2366,10 @@ csso@~2.3.1: clap "^1.0.9" source-map "^0.5.3" +csstype@^2.2.0: + version "2.5.5" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.5.tgz#4125484a3d42189a863943f23b9e4b80fedfa106" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -2371,13 +2404,13 @@ death@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@^3.1.0: +debug@^3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -2401,9 +2434,9 @@ deep-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" define-properties@^1.1.1: version "1.1.2" @@ -2424,6 +2457,13 @@ define-property@^1.0.0: dependencies: is-descriptor "^1.0.0" +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -2455,7 +2495,7 @@ depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" -depd@~1.1.1: +depd@~1.1.1, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -2507,24 +2547,45 @@ detect-port-alt@1.1.3: address "^1.0.1" debug "^2.6.0" -detect-port@1.2.2, detect-port@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469" +detect-port@1.2.3, detect-port@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.3.tgz#15bf49820d02deb84bfee0a74876b32d791bf610" dependencies: address "^1.0.1" debug "^2.6.0" +devcert-san@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/devcert-san/-/devcert-san-0.3.3.tgz#aa77244741b2d831771c011f22ee25e396ad4ba9" + dependencies: + "@types/configstore" "^2.1.1" + "@types/debug" "^0.0.29" + "@types/get-port" "^0.0.4" + "@types/glob" "^5.0.30" + "@types/mkdirp" "^0.3.29" + "@types/node" "^7.0.11" + "@types/tmp" "^0.0.32" + command-exists "^1.2.2" + configstore "^3.0.0" + debug "^2.6.3" + eol "^0.8.1" + get-port "^3.0.0" + glob "^7.1.1" + mkdirp "^0.5.1" + tmp "^0.0.31" + tslib "^1.6.0" + diffie-hellman@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" randombytes "^2.0.0" -dom-align@1.x: - version "1.6.7" - resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.6.7.tgz#6858138efb6b77405ce99146d0be5e4f7282813f" +dom-align@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.8.0.tgz#c0e89b5b674c6e836cd248c52c2992135f093654" dom-closest@^0.2.0: version "0.2.0" @@ -2580,8 +2641,8 @@ domhandler@2.1: domelementtype "1" domhandler@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" dependencies: domelementtype "1" @@ -2645,9 +2706,9 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30: - version "1.3.33" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.33.tgz#bf00703d62a7c65238136578c352d6c5c042a545" +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47: + version "1.3.51" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.51.tgz#6a42b49daaf7f22a5b37b991daf949f34dbdb9b5" elliptic@^6.0.0: version "6.4.0" @@ -2673,7 +2734,7 @@ 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" -encodeurl@~1.0.1: +encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -2689,13 +2750,13 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -engine.io-client@~3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.4.tgz#4fcf1370b47163bd2ce9be2733972430350d4ea1" +engine.io-client@~3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" dependencies: component-emitter "1.2.1" component-inherit "0.0.3" - debug "~2.6.9" + debug "~3.1.0" engine.io-parser "~2.1.1" has-cors "1.1.0" indexof "0.0.1" @@ -2715,18 +2776,16 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: blob "0.0.4" has-binary2 "~1.0.2" -engine.io@~3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.4.tgz#3d0211b70a552ce841ffc7da8627b301a9a4162e" +engine.io@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.0.tgz#54332506f42f2edc71690d2f2a42349359f3bf7d" dependencies: - accepts "1.3.3" + accepts "~1.3.4" base64id "1.0.0" cookie "0.3.1" - debug "~2.6.9" + debug "~3.1.0" engine.io-parser "~2.1.0" ws "~3.3.1" - optionalDependencies: - uws "~0.14.4" enhanced-resolve@~0.9.0: version "0.9.1" @@ -2744,19 +2803,27 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" +envinfo@^5.8.1: + version "5.10.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.10.0.tgz#503a9774ae15b93ea68bdfae2ccd6306624ea6df" + +eol@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/eol/-/eol-0.8.1.tgz#defc3224990c7eca73bb34461a56cf9dc24761d0" + err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" errno@^0.1.1, errno@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" dependencies: prr "~1.0.1" error-ex@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" dependencies: is-arrayish "^0.2.1" @@ -2767,17 +2834,18 @@ error-stack-parser@^1.3.6: stackframe "^0.3.1" error-stack-parser@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.1.tgz#a3202b8fb03114aa9b40a0e3669e48b2b65a010a" + version "2.0.2" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.2.tgz#4ae8dbaa2bf90a8b450707b9149dcabca135520d" dependencies: - stackframe "^1.0.3" + stackframe "^1.0.4" es5-ext@^0.10.12, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.38" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.38.tgz#fa7d40d65bbc9bb8a67e1d3f9cc656a00530eed3" + version "0.10.45" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.45.tgz#0bfdf7b473da5919d5adf3bd25ceb754fccc3653" dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" + next-tick "1" es6-iterator@~2.0.3: version "2.0.3" @@ -2842,9 +2910,9 @@ eval@^0.1.0: dependencies: require-like ">= 0.1.1" -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" +eventemitter3@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" eventlistener@0.0.1: version "0.0.1" @@ -2868,10 +2936,10 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" exec-sh@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" + version "0.2.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" dependencies: - merge "^1.1.3" + merge "^1.2.0" execa@^0.7.0: version "0.7.0" @@ -2938,19 +3006,19 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: homedir-polyfill "^1.0.1" express-graphql@^0.6.6: - version "0.6.11" - resolved "https://registry.yarnpkg.com/express-graphql/-/express-graphql-0.6.11.tgz#3dce78d0643e78e7e3606646ce162025ba0585ab" + version "0.6.12" + resolved "https://registry.yarnpkg.com/express-graphql/-/express-graphql-0.6.12.tgz#dfcb2058ca72ed5190b140830ad8cdbf76a9128a" dependencies: accepts "^1.3.0" - content-type "^1.0.2" + content-type "^1.0.4" http-errors "^1.3.0" - raw-body "^2.1.0" + raw-body "^2.3.2" express@^4.13.3, express@^4.14.0: - version "4.16.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" + version "4.16.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" dependencies: - accepts "~1.3.4" + accepts "~1.3.5" array-flatten "1.1.1" body-parser "1.18.2" content-disposition "0.5.2" @@ -2958,26 +3026,26 @@ express@^4.13.3, express@^4.14.0: cookie "0.3.1" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.1" - encodeurl "~1.0.1" + depd "~1.1.2" + encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.1.0" + finalhandler "1.1.1" fresh "0.5.2" merge-descriptors "1.0.1" methods "~1.1.2" on-finished "~2.3.0" parseurl "~1.3.2" path-to-regexp "0.1.7" - proxy-addr "~2.0.2" + proxy-addr "~2.0.3" qs "6.5.1" range-parser "~1.2.0" safe-buffer "5.1.1" - send "0.16.1" - serve-static "1.13.1" + send "0.16.2" + serve-static "1.13.2" setprototypeof "1.1.0" - statuses "~1.3.1" - type-is "~1.6.15" + statuses "~1.4.0" + type-is "~1.6.16" utils-merge "1.0.1" vary "~1.1.2" @@ -2987,7 +3055,7 @@ extend-shallow@^2.0.1: dependencies: is-extendable "^0.1.0" -extend-shallow@^3.0.0: +extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" dependencies: @@ -2998,9 +3066,9 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.0.1, external-editor@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" +external-editor@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" @@ -3012,7 +3080,7 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extglob@^2.0.2: +extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" dependencies: @@ -3042,8 +3110,8 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" fast-glob@^1.0.1: version "1.0.1" @@ -3058,10 +3126,20 @@ fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" +fault@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa" + dependencies: + format "^0.2.2" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -3081,8 +3159,8 @@ fb-watchman@^2.0.0: bser "^2.0.0" fbjs@^0.8.14, fbjs@^0.8.15, fbjs@^0.8.16, fbjs@^0.8.9: - version "0.8.16" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + version "0.8.17" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" dependencies: core-js "^1.0.0" isomorphic-fetch "^2.1.1" @@ -3090,7 +3168,7 @@ fbjs@^0.8.14, fbjs@^0.8.15, fbjs@^0.8.16, fbjs@^0.8.9: object-assign "^4.1.0" promise "^7.1.1" setimmediate "^1.0.5" - ua-parser-js "^0.7.9" + ua-parser-js "^0.7.18" figures@^2.0.0: version "2.0.0" @@ -3112,13 +3190,17 @@ filesize@3.5.11: version "3.5.11" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" +filesize@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" dependencies: is-number "^2.1.0" isobject "^2.0.0" - randomatic "^1.1.3" + randomatic "^3.0.0" repeat-element "^1.1.2" repeat-string "^1.5.2" @@ -3131,16 +3213,16 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" dependencies: debug "2.6.9" - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" on-finished "~2.3.0" parseurl "~1.3.2" - statuses "~1.3.1" + statuses "~1.4.0" unpipe "~1.0.0" find-cache-dir@^0.1.1: @@ -3165,7 +3247,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" dependencies: @@ -3213,6 +3295,12 @@ flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" +follow-redirects@^1.0.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.0.tgz#234f49cf770b7f35b40e790f636ceba0c3a0ab77" + dependencies: + debug "^3.1.0" + for-in@^0.1.3: version "0.1.8" resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" @@ -3250,13 +3338,17 @@ form-data@~2.1.1: mime-types "^2.1.12" form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "1.0.6" mime-types "^2.1.12" +format@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -3272,12 +3364,12 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" friendly-errors-webpack-plugin@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.6.1.tgz#e32781c4722f546a06a9b5d7a7cfa28520375d70" + version "1.7.0" + resolved "https://registry.yarnpkg.com/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz#efc86cbb816224565861a1be7a9d84d0aafea136" dependencies: chalk "^1.1.3" error-stack-parser "^2.0.0" - string-length "^1.0.1" + string-width "^2.0.0" front-matter@^2.1.0: version "2.3.0" @@ -3285,13 +3377,17 @@ front-matter@^2.1.0: dependencies: js-yaml "^3.10.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + fs-exists-sync@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" -fs-extra@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" +fs-extra@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3305,6 +3401,12 @@ fs-extra@^4.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + fs-readdir-recursive@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -3314,21 +3416,13 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" fsevents@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.39" + nan "^2.9.2" + node-pre-gyp "^0.10.0" -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: +fstream@^1.0.0, fstream@^1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" dependencies: @@ -3337,19 +3431,26 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" -function-bind@^1.0.2: +function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" -gatsby-1-config-css-modules@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/gatsby-1-config-css-modules/-/gatsby-1-config-css-modules-1.0.8.tgz#c051b7be22c6d07d485c2d9d05e0b88c13f4a572" +gatsby-1-config-css-modules@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/gatsby-1-config-css-modules/-/gatsby-1-config-css-modules-1.0.11.tgz#5a102c6b11f9a6963b3892ecc959511e1688e525" dependencies: babel-runtime "^6.26.0" -gatsby-cli@^1.1.39: - version "1.1.39" - resolved "https://registry.yarnpkg.com/gatsby-cli/-/gatsby-cli-1.1.39.tgz#f2f4bf67d081de88c0a9a3728d9fcf0e215e182d" +gatsby-1-config-extract-plugin@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/gatsby-1-config-extract-plugin/-/gatsby-1-config-extract-plugin-1.0.3.tgz#9e2c962d4563c95fa29da83e3d93017129af0115" + dependencies: + babel-runtime "^6.26.0" + extract-text-webpack-plugin "^1.0.1" + +gatsby-cli@^1.1.58: + version "1.1.58" + resolved "https://registry.yarnpkg.com/gatsby-cli/-/gatsby-cli-1.1.58.tgz#5dda246b9877ab925f6a512f723c20557af22d57" dependencies: babel-code-frame "^6.26.0" babel-runtime "^6.26.0" @@ -3357,6 +3458,7 @@ gatsby-cli@^1.1.39: common-tags "^1.4.0" convert-hrtime "^2.0.0" core-js "^2.5.0" + envinfo "^5.8.1" execa "^0.8.0" fs-extra "^4.0.1" hosted-git-info "^2.5.0" @@ -3366,12 +3468,12 @@ gatsby-cli@^1.1.39: source-map "^0.5.7" stack-trace "^0.0.10" update-notifier "^2.3.0" - yargs "^8.0.2" + yargs "^11.1.0" yurnalist "^0.2.1" -gatsby-link@^1.6.34, gatsby-link@^1.6.36: - version "1.6.36" - resolved "https://registry.yarnpkg.com/gatsby-link/-/gatsby-link-1.6.36.tgz#3f969d38e9396e2650d3804543c76881eab98feb" +gatsby-link@^1.6.45: + version "1.6.45" + resolved "https://registry.yarnpkg.com/gatsby-link/-/gatsby-link-1.6.45.tgz#6a28d377cd9eee4bf5454be5a9292550b5d1d929" dependencies: "@types/history" "^4.6.2" "@types/react-router-dom" "^4.2.2" @@ -3379,75 +3481,87 @@ gatsby-link@^1.6.34, gatsby-link@^1.6.36: prop-types "^15.5.8" ric "^1.3.0" -gatsby-module-loader@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/gatsby-module-loader/-/gatsby-module-loader-1.0.9.tgz#a33f3496589577749d2fbb680f7bab9ddcc86172" +gatsby-module-loader@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/gatsby-module-loader/-/gatsby-module-loader-1.0.11.tgz#35f269456f6a6d85c693bdc2b3b3b3432987f55b" dependencies: babel-runtime "^6.26.0" loader-utils "^0.2.16" -gatsby-plugin-antd@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/gatsby-plugin-antd/-/gatsby-plugin-antd-1.0.10.tgz#d33a4089657689fa6fff3a52469bd76e583d795d" +gatsby-plugin-antd@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/gatsby-plugin-antd/-/gatsby-plugin-antd-1.0.12.tgz#bd1c5b02b9951f36171a8209df4bf52c85c94bb2" dependencies: - antd "^3.1.0" - babel-plugin-import "^1.6.3" + antd "^3.5.1" + babel-plugin-import "^1.7.0" -gatsby-plugin-google-analytics@^1.0.19: - version "1.0.19" - resolved "https://registry.yarnpkg.com/gatsby-plugin-google-analytics/-/gatsby-plugin-google-analytics-1.0.19.tgz#e9112f01118e0a16eb61f1b39bb0757feba88f2b" +gatsby-plugin-google-analytics@^1.0.31: + version "1.0.31" + resolved "https://registry.yarnpkg.com/gatsby-plugin-google-analytics/-/gatsby-plugin-google-analytics-1.0.31.tgz#eaf16e1809461b10badf12c05038c429745783c0" dependencies: babel-runtime "^6.26.0" -gatsby-plugin-less@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/gatsby-plugin-less/-/gatsby-plugin-less-1.1.4.tgz#f226e207b8d17e064865ce3f18b712dea71c4570" +gatsby-plugin-less@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/gatsby-plugin-less/-/gatsby-plugin-less-1.1.8.tgz#206e6b44996e976856260ff3ff2fe166ddd6173e" dependencies: babel-runtime "^6.26.0" extract-text-webpack-plugin "^1.0.1" - gatsby-1-config-css-modules "^1.0.8" + gatsby-1-config-css-modules "^1.0.11" less "^2.7.2" less-loader "^3.0.0" webpack "^1.13.3" -gatsby-plugin-react-helmet@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-2.0.4.tgz#330bd5c2052411b7e4dd8f74e9a57b44ff2ed1ea" +gatsby-plugin-page-creator@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-1.0.1.tgz#6bad33a7f46cb5b87dbdaacc3c1bbd81ac63bc20" + dependencies: + babel-runtime "^6.26.0" + bluebird "^3.5.0" + chokidar "^1.7.0" + glob "^7.1.1" + lodash "^4.17.4" + parse-filepath "^1.0.1" + slash "^1.0.0" + +gatsby-plugin-react-helmet@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-2.0.11.tgz#a2db81755f5b41d54e0e535ca1d9a008d3ccff0a" dependencies: babel-runtime "^6.26.0" -gatsby-plugin-react-next@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/gatsby-plugin-react-next/-/gatsby-plugin-react-next-1.0.8.tgz#f27afe3175a7820ab4c15989d82b8cd5848b962c" +gatsby-plugin-react-next@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/gatsby-plugin-react-next/-/gatsby-plugin-react-next-1.0.11.tgz#715cab5ea86f64664f96af3e7f3640eecd9de5e3" dependencies: babel-runtime "^6.26.0" core-js "^2.5.1" react "^16.0.0" react-dom "^16.0.0" -gatsby-react-router-scroll@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/gatsby-react-router-scroll/-/gatsby-react-router-scroll-1.0.10.tgz#a520ea98fd25d5c307790974b13955cb128e01df" +gatsby-react-router-scroll@^1.0.18: + version "1.0.18" + resolved "https://registry.yarnpkg.com/gatsby-react-router-scroll/-/gatsby-react-router-scroll-1.0.18.tgz#616ffb801dbdbe4598611e2ff3861b91ac3eecbf" dependencies: babel-runtime "^6.26.0" scroll-behavior "^0.9.9" warning "^3.0.0" -gatsby-remark-prismjs@^1.2.14: - version "1.2.14" - resolved "https://registry.yarnpkg.com/gatsby-remark-prismjs/-/gatsby-remark-prismjs-1.2.14.tgz#3f5fd2ac1d5a174673a6b6fa63b4e4fa526d36c0" +gatsby-remark-prismjs@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/gatsby-remark-prismjs/-/gatsby-remark-prismjs-2.0.4.tgz#31243fe887c07b889c52bfdc68b53c83a42554e7" dependencies: babel-runtime "^6.26.0" parse-numeric-range "0.0.2" - prismjs "^1.11.0" unist-util-visit "^1.3.0" -gatsby-source-filesystem@^1.5.18: - version "1.5.18" - resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-1.5.18.tgz#e2cb96a2c248c304e58ba3d0142316a695d3ef35" +gatsby-source-filesystem@^1.5.39: + version "1.5.39" + resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-1.5.39.tgz#c7e49b7809632b53c827e66ff3ee0ba74ef62dd8" dependencies: babel-cli "^6.26.0" babel-runtime "^6.26.0" + better-queue "^3.8.7" bluebird "^3.5.0" chokidar "^1.7.0" fs-extra "^4.0.1" @@ -3458,9 +3572,9 @@ gatsby-source-filesystem@^1.5.18: slash "^1.0.0" valid-url "^1.0.9" -gatsby-transformer-remark@^1.7.31: - version "1.7.31" - resolved "https://registry.yarnpkg.com/gatsby-transformer-remark/-/gatsby-transformer-remark-1.7.31.tgz#b429e14e60c8cf8809def0c6c914627ef7ff3a1c" +gatsby-transformer-remark@^1.7.44: + version "1.7.44" + resolved "https://registry.yarnpkg.com/gatsby-transformer-remark/-/gatsby-transformer-remark-1.7.44.tgz#69b45f377a68484d1eab13f1feb7924428378ce1" dependencies: babel-runtime "^6.26.0" bluebird "^3.5.0" @@ -3483,9 +3597,9 @@ gatsby-transformer-remark@^1.7.31: unist-util-select "^1.5.0" unist-util-visit "^1.1.1" -gatsby@^1.9.158: - version "1.9.188" - resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-1.9.188.tgz#2bacf2b956cfdf514c4be9be86b1e78b781f1307" +gatsby@^1.9.273: + version "1.9.273" + resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-1.9.273.tgz#bf3d685cbd5112a55514ca0450888d2da95d4444" dependencies: async "^2.1.2" babel-code-frame "^6.22.0" @@ -3514,25 +3628,28 @@ gatsby@^1.9.158: debug "^2.6.0" del "^3.0.0" detect-port "^1.2.1" + devcert-san "^0.3.3" domready "^1.0.8" dotenv "^4.0.0" express "^4.14.0" express-graphql "^0.6.6" - extract-text-webpack-plugin "^1.0.1" + fast-levenshtein "~2.0.4" file-loader "^0.9.0" flat "^2.0.1" friendly-errors-webpack-plugin "^1.6.1" front-matter "^2.1.0" fs-extra "^4.0.1" - gatsby-1-config-css-modules "^1.0.8" - gatsby-cli "^1.1.39" - gatsby-link "^1.6.36" - gatsby-module-loader "^1.0.9" - gatsby-react-router-scroll "^1.0.10" + gatsby-1-config-css-modules "^1.0.11" + gatsby-1-config-extract-plugin "^1.0.3" + gatsby-cli "^1.1.58" + gatsby-link "^1.6.45" + gatsby-module-loader "^1.0.11" + gatsby-plugin-page-creator "^1.0.1" + gatsby-react-router-scroll "^1.0.18" glob "^7.1.1" graphql "^0.11.7" graphql-relay "^0.5.1" - graphql-skip-limit "^1.0.9" + graphql-skip-limit "^1.0.11" history "^4.6.2" invariant "^2.2.2" is-relative "^0.2.1" @@ -3570,7 +3687,7 @@ gatsby@^1.9.158: react-router "^4.1.1" react-router-dom "^4.1.1" redux "^3.6.0" - relay-compiler "^1.4.1" + relay-compiler "1.4.1" remote-redux-devtools "^0.5.7" serve "^6.4.0" shallow-compare "^1.2.2" @@ -3582,7 +3699,7 @@ gatsby@^1.9.158: string-similarity "^1.2.0" style-loader "^0.13.0" type-of "^2.0.1" - url-loader "^0.5.7" + url-loader "^0.6.2" uuid "^3.1.0" v8-compile-cache "^1.1.0" webpack "^1.13.3" @@ -3626,6 +3743,10 @@ get-params@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/get-params/-/get-params-0.1.2.tgz#bae0dfaba588a0c60d7834c0d8dc2ff60eeef2fe" +get-port@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3812,12 +3933,12 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.4, resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" graphql-relay@^0.5.1: - version "0.5.4" - resolved "https://registry.yarnpkg.com/graphql-relay/-/graphql-relay-0.5.4.tgz#58050cfe16118595f82ab3aabfc974546ce755a8" + version "0.5.5" + resolved "https://registry.yarnpkg.com/graphql-relay/-/graphql-relay-0.5.5.tgz#d6815e6edd618e878d5d921c13fc66033ec867e2" -graphql-skip-limit@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/graphql-skip-limit/-/graphql-skip-limit-1.0.9.tgz#20d0de6bd6cf3460c4fdcee3d6b379634d0d44b7" +graphql-skip-limit@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/graphql-skip-limit/-/graphql-skip-limit-1.0.11.tgz#c6970d11bdfe7aa001f96c8ba41b9a93a6dc805c" dependencies: babel-runtime "^6.26.0" graphql "^0.11.7" @@ -3890,8 +4011,8 @@ has-ansi@^2.0.0: ansi-regex "^2.0.0" has-binary2@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98" + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" dependencies: isarray "2.0.1" @@ -3903,13 +4024,13 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" has-symbol-support-x@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz#66ec2e377e0c7d7ccedb07a3a84d77510ff1bc4c" + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" has-to-string-tag-x@^1.2.0: version "1.4.1" @@ -3949,16 +4070,10 @@ has-values@^1.0.0: kind-of "^4.0.0" has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: - function-bind "^1.0.2" - -hash-base@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" - dependencies: - inherits "^2.0.1" + function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" @@ -3968,8 +4083,8 @@ hash-base@^3.0.0: safe-buffer "^5.0.1" hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + version "1.1.4" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.4.tgz#8b50e1f35d51bd01e5ed9ece4dbe3549ccfa0a3c" dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.0" @@ -3996,12 +4111,12 @@ hast-util-from-parse5@^2.0.0: vfile-location "^2.0.0" hast-util-is-element@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz#3f7216978b2ae14d98749878782675f33be3ce00" + version "1.0.1" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.0.1.tgz#c76e8aafbdb6e5c83265bf50324e2f2e024eb12a" hast-util-parse-selector@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.1.0.tgz#b55c0f4bb7bb2040c889c325ef87ab29c38102b4" + version "2.1.1" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.1.1.tgz#fc06985272f5d204a25187f002bb916521e74f3a" hast-util-raw@^2.0.2: version "2.0.2" @@ -4042,8 +4157,8 @@ hast-util-to-parse5@^2.0.0: zwitch "^1.0.0" hast-util-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz#bd096919625d2936e1ff17bc4df7fd727f17ece9" + version "1.0.1" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.1.tgz#d67da2c87637b1ce1d85dd15b270ba057930149a" hastscript@^3.0.0, hastscript@^3.1.0: version "3.1.0" @@ -4055,7 +4170,7 @@ hastscript@^3.0.0, hastscript@^3.1.0: property-information "^3.0.0" space-separated-tokens "^1.0.0" -hawk@3.1.3, hawk@~3.1.3: +hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" dependencies: @@ -4064,15 +4179,6 @@ hawk@3.1.3, hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - highlight.js@~9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" @@ -4100,12 +4206,12 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" -hoist-non-react-statics@^2.3.0, hoist-non-react-statics@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" +hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0: + version "2.5.5" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" home-or-tmp@^2.0.0: version "2.0.0" @@ -4121,8 +4227,8 @@ homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: parse-passwd "^1.0.0" hosted-git-info@^2.1.4, hosted-git-info@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + version "2.6.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.1.tgz#6e4cee78b01bb849dcf93527708c69fdbee410df" html-comment-regex@^1.1.0: version "1.1.1" @@ -4133,8 +4239,8 @@ html-entities@^1.2.0: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" html-void-elements@^1.0.0, html-void-elements@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.2.tgz#9d22e0ca32acc95b3f45b8d5b4f6fbdc05affd55" + version "1.0.3" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.3.tgz#956707dbecd10cf658c92c5d27fee763aa6aa982" htmlparser2@^3.9.0, htmlparser2@^3.9.1: version "3.9.2" @@ -4156,7 +4262,7 @@ htmlparser2@~3.3.0: domutils "1.1" readable-stream "1.0" -http-errors@1.6.2, http-errors@^1.3.0, http-errors@~1.6.2: +http-errors@1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" dependencies: @@ -4165,9 +4271,18 @@ http-errors@1.6.2, http-errors@^1.3.0, http-errors@~1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" +http-errors@1.6.3, http-errors@^1.3.0, http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + http-parser-js@>=0.4.0: - version "0.4.10" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + version "0.4.13" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.13.tgz#3bd6d6fde6e3172c9334c3b33b6c193d80fe1137" http-proxy-middleware@~0.17.1: version "0.17.4" @@ -4179,11 +4294,12 @@ http-proxy-middleware@~0.17.1: micromatch "^2.3.11" http-proxy@^1.16.2: - version "1.16.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" + version "1.17.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a" dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" + eventemitter3 "^3.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" http-signature@~1.1.0: version "1.1.1" @@ -4209,17 +4325,29 @@ https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" -iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13: +iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@0.4.23, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" ieee754@^1.1.4: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" image-size@~0.5.0: version "0.5.5" @@ -4272,24 +4400,6 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@3.3.0, inquirer@^3.0.1: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" @@ -4317,9 +4427,13 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" -invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" +intersperse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/intersperse/-/intersperse-1.0.0.tgz#f2561fb1cfef9f5277cc3347a22886b4351a5181" + +invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: loose-envify "^1.0.0" @@ -4331,9 +4445,9 @@ ip@1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" -ipaddr.js@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" +ipaddr.js@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b" is-absolute-url@^2.0.0: version "2.1.0" @@ -4359,16 +4473,16 @@ is-accessor-descriptor@^1.0.0: kind-of "^6.0.0" is-alphabetical@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.1.tgz#c77079cc91d4efac775be1034bf2d243f95e6f08" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41" is-alphanumeric@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" is-alphanumerical@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz#dfb4aa4d1085e33bdb61c2dee9c80e9c6c19f53b" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40" dependencies: is-alphabetical "^1.0.0" is-decimal "^1.0.0" @@ -4412,8 +4526,8 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-decimal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.1.tgz#f5fb6a94996ad9e8e3761fbfbd091f1fca8c4e82" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff" is-descriptor@^0.1.0: version "0.1.6" @@ -4423,7 +4537,7 @@ is-descriptor@^0.1.0: is-data-descriptor "^0.1.4" kind-of "^5.0.0" -is-descriptor@^1.0.0: +is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" dependencies: @@ -4494,8 +4608,8 @@ is-glob@^4.0.0: is-extglob "^2.1.1" is-hexadecimal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" is-installed-globally@^0.1.0: version "0.1.0" @@ -4510,6 +4624,10 @@ is-nan@^1.2.1: dependencies: define-properties "^1.1.1" +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -4526,6 +4644,10 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -4534,19 +4656,13 @@ is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" -is-odd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" - dependencies: - is-number "^3.0.0" - is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" dependencies: is-path-inside "^1.0.0" @@ -4639,20 +4755,20 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" is-whitespace-character@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed" is-windows@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" -is-windows@^1.0.0, is-windows@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" +is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" is-word-character@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553" is-wsl@^1.1.0: version "1.1.0" @@ -4675,8 +4791,8 @@ isemail@2.x.x: resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6" isemail@3.x.x: - version "3.1.1" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.1.1.tgz#e8450fe78ff1b48347db599122adcd0668bd92b5" + version "3.1.2" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.1.2.tgz#937cf919002077999a73ea8b1951d590e84e01dd" dependencies: punycode "2.x.x" @@ -4743,16 +4859,16 @@ joi@9.0.0-0: topo "2.x.x" js-base64@^2.1.9: - version "2.4.3" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582" + version "2.4.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.5.tgz#e293cd3c7c82f070d700fc7a1ca0a2e69f101f92" js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" js-yaml@^3.10.0, js-yaml@^3.5.2: - version "3.10.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4764,9 +4880,9 @@ js-yaml@~3.7.0: argparse "^1.0.7" esprima "^2.6.0" -jsan@^3.1.0, jsan@^3.1.5: - version "3.1.9" - resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.9.tgz#2705676c1058f0a7d9ac266ad036a5769cfa7c96" +jsan@^3.1.5, jsan@^3.1.9: + version "3.1.10" + resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.10.tgz#ba9917b864defff567e0c990a34ae7a8d5eb1d90" jsbn@~0.1.0: version "0.1.1" @@ -4866,8 +4982,8 @@ jspm-registry@^0.4.1: semver "^4.3.3" jspm@^0.17.0-beta.13: - version "0.17.0-beta.47" - resolved "https://registry.yarnpkg.com/jspm/-/jspm-0.17.0-beta.47.tgz#6a9850dbdb949c9dcac9220ab59b3d130f374af2" + version "0.17.0-beta.48" + resolved "https://registry.yarnpkg.com/jspm/-/jspm-0.17.0-beta.48.tgz#3d0980709dd547b6eddd2fa520d1948e3c44b6ef" dependencies: bluebird "^3.0.5" chalk "^1.1.1" @@ -4886,8 +5002,8 @@ jspm@^0.17.0-beta.13: rimraf "^2.4.4" sane "^1.3.3" semver "^5.1.0" - systemjs "0.20.19" - systemjs-builder "0.16.12" + systemjs "0.21.3" + systemjs-builder "0.16.13" traceur "0.0.105" uglify-js "^2.6.1" @@ -4910,7 +5026,7 @@ kind-of@^2.0.1: dependencies: is-buffer "^1.0.2" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -4944,12 +5060,6 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" -lazy-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - dependencies: - set-getter "^0.1.0" - lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -4976,7 +5086,7 @@ less@^2.7.2: request "2.81.0" source-map "^0.5.3" -leven@^2.0.0: +leven@2.1.0, leven@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -5041,8 +5151,8 @@ locate-path@^2.0.0: path-exists "^3.0.0" lodash-es@^4.2.1: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.5.tgz#9fc6e737b1c4d151d8f9cae2247305d552ce748f" + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.10.tgz#62cd7104cdf5dd87f235a837f0ede0e8e5117e05" lodash-id@^0.14.0: version "0.14.0" @@ -5100,10 +5210,6 @@ lodash.foreach@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -5112,6 +5218,14 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + lodash.keys@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -5128,7 +5242,7 @@ lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" -lodash.merge@^4.4.0, lodash.merge@^4.6.0: +lodash.merge@^4.4.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" @@ -5193,9 +5307,9 @@ lodash@3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.5, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" +lodash@4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.16.5, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" lodash@4.11.1: version "4.11.1" @@ -5238,18 +5352,19 @@ lowdb@^0.16.2: steno "^0.4.1" lowercase-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" lowlight@~1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.1.tgz#ed7c3dffc36f8c1f263735c0fe0c907847c11250" + version "1.9.2" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.2.tgz#0b9127e3cec2c3021b7795dd81005c709a42fdd1" dependencies: + fault "^1.0.2" highlight.js "~9.12.0" lru-cache@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -5258,21 +5373,17 @@ ltcdr@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf" -macaddress@^0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" - make-dir@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" dependencies: pify "^3.0.0" make-iterator@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.0.tgz#57bef5dc85d23923ba23767324d8e8f8f3d9694b" + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" dependencies: - kind-of "^3.1.0" + kind-of "^6.0.2" makeerror@1.0.x: version "1.0.11" @@ -5291,23 +5402,27 @@ map-visit@^1.0.0: object-visit "^1.0.0" mapz@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mapz/-/mapz-1.0.1.tgz#9ecec757d3c3fe0a8a6f363e328eaee69a428441" + version "1.0.2" + resolved "https://registry.yarnpkg.com/mapz/-/mapz-1.0.2.tgz#f6af94c425db0874ac2c4e67a76f5df1724b1322" dependencies: x-is-array "^0.1.0" markdown-escapes@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" + version "1.0.2" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" markdown-table@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.1.tgz#4b3dd3a133d1518b8ef0dbc709bf2a1b4824bc8c" + version "1.1.2" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786" math-expression-evaluator@^1.2.14: version "1.2.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + md5-file@^3.1.1: version "3.2.3" resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-3.2.3.tgz#f9bceb941eca2214a4c0727f5e700314e770f06f" @@ -5415,7 +5530,7 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" -merge@^1.1.3, merge@^1.2.0: +merge@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" @@ -5429,13 +5544,14 @@ micro-compress@1.0.0: dependencies: compression "^1.6.2" -micro@9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.0.tgz#f2effba306639076e994c007c327dfc36a5185e9" +micro@9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/micro/-/micro-9.3.1.tgz#0c37eba0171554b1beccda5215ff8ea4e7aa59d6" dependencies: + arg "2.0.0" + chalk "2.4.0" content-type "1.0.4" is-stream "1.1.0" - mri "1.1.0" raw-body "2.3.2" micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: @@ -5457,22 +5573,22 @@ micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: regex-cache "^0.4.2" micromatch@^3.0.3, micromatch@^3.0.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.5.tgz#d05e168c206472dfbca985bfef4f57797b4cd4ba" + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" - braces "^2.3.0" - define-property "^1.0.0" - extend-shallow "^2.0.1" - extglob "^2.0.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" fragment-cache "^0.2.1" - kind-of "^6.0.0" - nanomatch "^1.2.5" + kind-of "^6.0.2" + nanomatch "^1.2.9" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" - to-regex "^3.0.1" + to-regex "^3.0.2" miller-rabin@^4.0.0: version "4.0.1" @@ -5481,29 +5597,25 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -"mime-db@>= 1.30.0 < 2": - version "1.32.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" +"mime-db@>= 1.34.0 < 2": + version "1.34.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.34.0.tgz#452d0ecff5c30346a6dc1e64b1eaee0d3719ff9a" -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" -mime-types@2.1.17, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" +mime-types@2.1.18, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: - mime-db "~1.30.0" - -mime@1.3.x: - version "1.3.6" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" + mime-db "~1.33.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -mime@^1.2.11, mime@^1.3.6, mime@^1.5.0: +mime@^1.2.11, mime@^1.3.6, mime@^1.4.1, mime@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -5521,17 +5633,17 @@ min-document@^2.19.0: dependencies: dom-walk "^0.1.0" -mini-store@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mini-store/-/mini-store-1.0.4.tgz#a540fbfdbddd0415daf17a8b0cc8290c9f7d8bd6" +mini-store@^1.0.2, mini-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mini-store/-/mini-store-1.1.0.tgz#4d6b3fb5c89aa0303d9b39475efb3439cd42f04f" dependencies: hoist-non-react-statics "^2.3.1" prop-types "^15.6.0" shallowequal "^1.0.2" minimalistic-assert@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" @@ -5553,7 +5665,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0: +minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -5561,6 +5673,19 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + mitt@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8" @@ -5586,8 +5711,8 @@ mixin-object@^2.0.1: minimist "0.0.8" moment@2.x, moment@2.x.x, moment@^2.16.0, moment@^2.19.3: - version "2.20.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" + version "2.22.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" mri@1.1.0: version "1.1.0" @@ -5597,46 +5722,50 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.3.0, nan@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" -nanomatch@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.7.tgz#53cd4aa109ff68b7f869591fdc9d10daeeea3e79" +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" fragment-cache "^0.2.1" - is-odd "^1.0.0" - kind-of "^5.0.2" + is-windows "^1.0.2" + kind-of "^6.0.2" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" to-regex "^3.0.1" nbind@^0.3.14: - version "0.3.14" - resolved "https://registry.yarnpkg.com/nbind/-/nbind-0.3.14.tgz#ea85b685ae86801012509062f6ce4d639a19b864" + version "0.3.15" + resolved "https://registry.yarnpkg.com/nbind/-/nbind-0.3.15.tgz#20c74d77d54e28627ab8268c2767f7e40aef8c53" dependencies: emscripten-library-decorator "~0.2.2" mkdirp "~0.5.1" - nan "^2.7.0" + nan "^2.9.2" ncp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" +needle@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -5645,9 +5774,13 @@ netrc@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444" +next-tick@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + nlcst-to-string@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nlcst-to-string/-/nlcst-to-string-2.0.1.tgz#f90f3cf905c137dc8edd8727fbcde73e73c2a1d9" + version "2.0.2" + resolved "https://registry.yarnpkg.com/nlcst-to-string/-/nlcst-to-string-2.0.2.tgz#7125af4d4d369850c697192a658f01f36af9937b" node-emoji@^1.0.4: version "1.8.1" @@ -5659,13 +5792,6 @@ node-eta@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-eta/-/node-eta-0.9.0.tgz#9fb0b099bcd2a021940e603c64254dc003d9a7a8" -node-fetch@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -5674,18 +5800,17 @@ node-fetch@^1.0.1: is-stream "^1.0.1" node-gyp@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" + version "3.7.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.7.0.tgz#789478e8f6c45e277aa014f3e28f958f286f9203" dependencies: fstream "^1.0.0" glob "^7.0.3" graceful-fs "^4.1.2" - minimatch "^3.0.2" mkdirp "^0.5.0" nopt "2 || 3" npmlog "0 || 1 || 2 || 3 || 4" osenv "0" - request "2" + request ">=2.9.0 <2.82.0" rimraf "2" semver "~5.3.0" tar "^2.0.0" @@ -5751,25 +5876,24 @@ node-libs-browser@^2.0.0: util "^0.10.3" vm-browserify "0.0.4" -node-pre-gyp@^0.6.39: - version "0.6.39" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" +node-pre-gyp@^0.10.0: + version "0.10.2" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.2.tgz#e8945c20ef6795a20aac2b44f036eb13cf5146e3" dependencies: detect-libc "^1.0.2" - hawk "3.1.3" mkdirp "^0.5.1" + needle "^2.2.0" nopt "^4.0.1" + npm-packlist "^1.1.6" npmlog "^4.0.2" - rc "^1.1.7" - request "2.81.0" + rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" + tar "^4" -node-version@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.0.tgz#f437d7ba407e65e2c4eaef8887b1718ba523d4f0" +node-version@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.3.tgz#1081c87cce6d2dbbd61d0e51e28c287782678496" noms@0.0.0: version "0.0.0" @@ -5819,6 +5943,17 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.10" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + 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" @@ -5864,7 +5999,7 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1, object-assign@~4.1.0: +object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5881,8 +6016,8 @@ object-copy@^0.1.0: kind-of "^3.0.3" object-keys@^1.0.8: - version "1.0.11" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" object-path@^0.11.2: version "0.11.4" @@ -5939,7 +6074,7 @@ on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" -once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -5959,37 +6094,19 @@ open@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" -opencollective@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" - dependencies: - babel-polyfill "6.23.0" - chalk "1.1.3" - inquirer "3.0.6" - minimist "1.2.0" - node-fetch "1.6.3" - opn "4.0.2" - openssl-self-signed-certificate@1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4" -opn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - opn@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" dependencies: is-wsl "^1.1.0" -opn@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225" +opn@5.3.0, opn@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" dependencies: is-wsl "^1.1.0" @@ -6001,10 +6118,10 @@ optimist@^0.6.1, optimist@~0.6.0, optimist@~0.6.1: wordwrap "~0.0.2" original@>=0.0.5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b" + version "1.0.1" + resolved "https://registry.yarnpkg.com/original/-/original-1.0.1.tgz#b0a53ff42ba997a8c9cd1fb5daaeb42b9d693190" dependencies: - url-parse "1.0.x" + url-parse "~1.4.0" os-browserify@^0.2.0: version "0.2.1" @@ -6032,13 +6149,13 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" osenv@0, osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -6060,8 +6177,8 @@ p-finally@^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" + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" dependencies: p-try "^1.0.0" @@ -6103,8 +6220,8 @@ pako@~1.0.5: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" parse-asn1@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -6113,8 +6230,8 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" parse-english@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/parse-english/-/parse-english-4.1.0.tgz#1a642d955e375e1d4a50cc01957b13c7110b7a5c" + version "4.1.1" + resolved "https://registry.yarnpkg.com/parse-english/-/parse-english-4.1.1.tgz#2f75872e617769d857d9b6992dcde2a891f1b2d3" dependencies: nlcst-to-string "^2.0.0" parse-latin "^4.0.0" @@ -6122,8 +6239,8 @@ parse-english@^4.0.0: unist-util-visit-children "^1.0.0" parse-entities@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890" + version "1.1.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.2.tgz#9eaf719b29dc3bd62246b4332009072e01527777" dependencies: character-entities "^1.0.0" character-entities-legacy "^1.0.0" @@ -6156,8 +6273,8 @@ parse-json@^2.2.0: error-ex "^1.2.0" parse-latin@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/parse-latin/-/parse-latin-4.1.0.tgz#f560d46cab1cf04d632815443485a8b3b31e31a7" + version "4.1.1" + resolved "https://registry.yarnpkg.com/parse-latin/-/parse-latin-4.1.1.tgz#3a3edef405b2d5dce417b7157d3d8a5c7cdfab1d" dependencies: nlcst-to-string "^2.0.0" unist-util-modify-children "^1.0.0" @@ -6276,8 +6393,8 @@ pbkdf2-compat@2.0.1: resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288" pbkdf2@^3.0.3: - version "3.0.14" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade" + version "3.0.16" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -6341,10 +6458,6 @@ pkg-resolve@^0.1.7: jspm "^0.17.0-beta.13" resolve "^1.1.7" -pkginfo@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - pleeease-filters@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/pleeease-filters/-/pleeease-filters-3.0.1.tgz#4dfe0e8f1046613517c64b728bc80608a7ebf22f" @@ -6553,11 +6666,10 @@ postcss-discard-unused@^2.2.1: uniqs "^2.0.0" postcss-filter-plugins@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c" + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" dependencies: postcss "^5.0.4" - uniqid "^4.0.0" postcss-font-family-system-ui@^1.0.1: version "1.0.2" @@ -6851,12 +6963,12 @@ postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0. supports-color "^3.2.3" postcss@^6.0.1, postcss@^6.0.14: - version "6.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.17.tgz#e259a051ca513f81e9afd0c21f7f82eda50c65c5" + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" dependencies: - chalk "^2.3.0" + chalk "^2.4.1" source-map "^0.6.1" - supports-color "^5.1.0" + supports-color "^5.4.0" prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" @@ -6866,9 +6978,9 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@1.13.6: - version "1.13.6" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.6.tgz#00ae0b777ad92f81a9e7a1df2f0470b6dab0cb44" +prettier@1.13.7: + version "1.13.7" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281" pretty-bytes@^4.0.2: version "4.0.2" @@ -6881,25 +6993,25 @@ pretty-error@^2.1.1: renderkid "^2.0.1" utila "~0.4" -prismjs@^1.11.0, prismjs@^1.8.4: - version "1.11.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.11.0.tgz#297aef33eb79421bfdb19273a5092ca515970d29" +prismjs@^1.8.4: + version "1.15.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.15.0.tgz#8801d332e472091ba8def94976c8877ad60398d9" optionalDependencies: - clipboard "^1.7.1" + clipboard "^2.0.0" -prismjs@~1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.10.0.tgz#77e5187c2ae6b3253fcc313029cf25fe53778721" +prismjs@~1.14.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.14.0.tgz#bbccfdb8be5d850d26453933cb50122ca0362ae0" optionalDependencies: - clipboard "^1.7.1" + clipboard "^2.0.0" -private@^0.1.6, private@^0.1.7: +private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" process@^0.11.0, process@^0.11.10: version "0.11.10" @@ -6921,11 +7033,10 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.5.9, prop-types@^15.6.0: - version "15.6.0" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" +prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.5.9, prop-types@^15.6.0, prop-types@^15.6.1: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" dependencies: - fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" @@ -6942,12 +7053,12 @@ property-information@^3.0.0, property-information@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-3.2.0.tgz#fd1483c8fbac61808f5fe359e7693a1f48a58331" -proxy-addr@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" +proxy-addr@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" dependencies: forwarded "~0.1.2" - ipaddr.js "1.5.2" + ipaddr.js "1.6.0" prr@~1.0.1: version "1.0.1" @@ -6958,8 +7069,8 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" public-encrypt@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" + version "4.0.2" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -6979,8 +7090,8 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" punycode@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" @@ -6990,7 +7101,7 @@ q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" -qs@6.5.1, qs@~6.5.1: +qs@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" @@ -6998,6 +7109,10 @@ qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -7013,20 +7128,23 @@ querystring@0.2.0, querystring@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" -querystringify@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" +querystringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.0.0.tgz#fa3ed6e68eb15159457c89b37bc6472833195755" -querystringify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" +raf@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" + performance-now "^2.1.0" + +randomatic@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" @@ -7035,8 +7153,8 @@ randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: safe-buffer "^5.1.0" randomfill@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -7045,7 +7163,7 @@ range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" -raw-body@2.3.2, raw-body@^2.1.0: +raw-body@2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" dependencies: @@ -7054,16 +7172,25 @@ raw-body@2.3.2, raw-body@^2.1.0: iconv-lite "0.4.19" unpipe "1.0.0" +raw-body@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + raw-loader@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa" -rc-align@2.x: - version "2.3.5" - resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-2.3.5.tgz#5085cfa4d685ee9d030b9afd2971eb370c5e80a1" +rc-align@^2.4.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-2.4.3.tgz#b9b3c2a6d68adae71a8e1d041cd5e3b2a655f99a" dependencies: babel-runtime "^6.26.0" - dom-align "1.x" + dom-align "^1.7.0" prop-types "^15.5.8" rc-util "^4.0.4" @@ -7075,9 +7202,9 @@ rc-animate@2.x, rc-animate@^2.0.2, rc-animate@^2.3.0, rc-animate@^2.4.1: css-animation "^1.3.2" prop-types "15.x" -rc-calendar@~9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/rc-calendar/-/rc-calendar-9.5.0.tgz#83f3eca977d1c06765437bd7acd39a30890f6f07" +rc-calendar@~9.6.0: + version "9.6.2" + resolved "https://registry.yarnpkg.com/rc-calendar/-/rc-calendar-9.6.2.tgz#c7309db41225f4b8c81d5a1dcbe46d8ce07b6aee" dependencies: babel-runtime "6.x" classnames "2.x" @@ -7087,9 +7214,9 @@ rc-calendar@~9.5.0: rc-trigger "^2.2.0" rc-util "^4.1.1" -rc-cascader@~0.12.0: - version "0.12.2" - resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-0.12.2.tgz#2d08fe44b504364137d3c748f51ac393483e7b3b" +rc-cascader@~0.13.0: + version "0.13.1" + resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-0.13.1.tgz#157df251c5da734bf134b7a595a9b06446a6db80" dependencies: array-tree-filter "^1.0.0" prop-types "^15.5.8" @@ -7097,18 +7224,18 @@ rc-cascader@~0.12.0: rc-util "^4.0.4" shallow-equal "^1.0.0" -rc-checkbox@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-2.1.4.tgz#7f5ebabe7035ef333597d026faa0edd0f4d919b4" +rc-checkbox@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-2.1.5.tgz#411858448c0ee2a797ef8544dac63bcaeef722ef" dependencies: babel-runtime "^6.23.0" classnames "2.x" prop-types "15.x" rc-util "^4.0.4" -rc-collapse@~1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-1.8.0.tgz#107bd9193e36b1ec5381c9ed9ff4f7245a79adb5" +rc-collapse@~1.9.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-1.9.2.tgz#baa88a724ebbf444ad1f7776fe912f2f894e4099" dependencies: classnames "2.x" css-animation "1.x" @@ -7116,28 +7243,28 @@ rc-collapse@~1.8.0: rc-animate "2.x" rc-dialog@~7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-7.1.0.tgz#ffc18c8f799f1cbc343e9f3a1bd9190a1cb62079" + version "7.1.7" + resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-7.1.7.tgz#75d65203be91af8e02f582166a7cf7d713b69e59" dependencies: babel-runtime "6.x" - create-react-class "^15.5.2" - object-assign "~4.1.0" rc-animate "2.x" - rc-util "^4.1.0" + rc-util "^4.4.0" rc-dropdown@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-2.1.0.tgz#ae39db67e593ef4ed889dee99ef13ae3994a5c7f" + version "2.1.2" + resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-2.1.2.tgz#f99844d2ec17707232f244dda75c8d8a623d0272" dependencies: babel-runtime "^6.26.0" prop-types "^15.5.8" rc-trigger "^2.2.2" + react-lifecycles-compat "^3.0.2" rc-editor-core@~0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/rc-editor-core/-/rc-editor-core-0.8.3.tgz#0be6a37a10152ae6d58bd2ecfefdf2c80ce0689a" + version "0.8.6" + resolved "https://registry.yarnpkg.com/rc-editor-core/-/rc-editor-core-0.8.6.tgz#e48b288286effb3272cbc9c6f801450dcdb0b247" dependencies: babel-runtime "^6.26.0" + classnames "^2.2.5" draft-js "^0.10.0" immutable "^3.7.4" lodash "^4.16.5" @@ -7145,8 +7272,8 @@ rc-editor-core@~0.8.3: setimmediate "^1.0.5" rc-editor-mention@^1.0.2: - version "1.1.6" - resolved "https://registry.yarnpkg.com/rc-editor-mention/-/rc-editor-mention-1.1.6.tgz#acbb92661e2392f971f8d8ad1c235b084796c895" + version "1.1.7" + resolved "https://registry.yarnpkg.com/rc-editor-mention/-/rc-editor-mention-1.1.7.tgz#c72d181859beda96669f4b43e19a941e68fa985b" dependencies: babel-runtime "^6.23.0" classnames "^2.2.5" @@ -7157,8 +7284,8 @@ rc-editor-mention@^1.0.2: rc-editor-core "~0.8.3" rc-form@^2.1.0: - version "2.1.7" - resolved "https://registry.yarnpkg.com/rc-form/-/rc-form-2.1.7.tgz#3e01c5e19838038b65a58014e2802deb088b60b7" + version "2.2.0" + resolved "https://registry.yarnpkg.com/rc-form/-/rc-form-2.2.0.tgz#ea596c6c92c7df6092f95cbbf8f15014ea07e9f5" dependencies: async-validator "1.x" babel-runtime "6.x" @@ -7177,30 +7304,45 @@ rc-hammerjs@~0.6.0: prop-types "^15.5.9" rc-input-number@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-4.0.2.tgz#09651d5fc05c7f6a1e2111dbfad7ed5743fa7595" + version "4.0.12" + resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-4.0.12.tgz#99b62f0b2395e1e76c9f72142b4ad7ea46f97d06" dependencies: babel-runtime "6.x" classnames "^2.2.0" + is-negative-zero "^2.0.0" prop-types "^15.5.7" - rmc-feedback "^1.0.0" + rc-util "^4.5.1" + rmc-feedback "^2.0.0" -rc-menu@^6.1.0, rc-menu@~6.2.0: - version "6.2.6" - resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-6.2.6.tgz#ad95a4926792d0476b3b25f6d015a497915dbbbd" +rc-menu@^7.0.2: + version "7.1.0" + resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-7.1.0.tgz#37edf49a68c1ca43cbbe859bd7dddcf177568892" dependencies: babel-runtime "6.x" classnames "2.x" - create-react-class "^15.5.2" dom-scroll-into-view "1.x" + mini-store "^1.1.0" prop-types "^15.5.6" rc-animate "2.x" rc-trigger "^2.3.0" rc-util "^4.1.0" -rc-notification@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-3.0.1.tgz#9ddcb831895ad40943a7e1df34951aa705173bce" +rc-menu@~7.0.2: + version "7.0.5" + resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-7.0.5.tgz#986b65df5ad227aadf399ea374b98d2313802316" + dependencies: + babel-runtime "6.x" + classnames "2.x" + dom-scroll-into-view "1.x" + mini-store "^1.1.0" + prop-types "^15.5.6" + rc-animate "2.x" + rc-trigger "^2.3.0" + rc-util "^4.1.0" + +rc-notification@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-3.1.1.tgz#14eac6730db1d59adaf569dad9fe82a2f33cd23a" dependencies: babel-runtime "6.x" classnames "2.x" @@ -7208,9 +7350,9 @@ rc-notification@~3.0.0: rc-animate "2.x" rc-util "^4.0.4" -rc-pagination@~1.15.0: - version "1.15.1" - resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-1.15.1.tgz#fbf0f88f35d3b34e90bafc068b2bf03b5156ba5f" +rc-pagination@~1.16.1: + version "1.16.4" + resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-1.16.4.tgz#239442d5cabfc531d1a2e53f87d92140085e9b0d" dependencies: babel-runtime "6.x" prop-types "^15.5.7" @@ -7231,9 +7373,9 @@ rc-rate@~2.4.0: prop-types "^15.5.8" rc-util "^4.3.0" -rc-select@~7.7.0: - version "7.7.1" - resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-7.7.1.tgz#cacd0353b79a8eb7708042e40ced6589ca749033" +rc-select@~8.0.7: + version "8.0.14" + resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-8.0.14.tgz#ff1763458a15519bea010ea15fecf6f59095b346" dependencies: babel-runtime "^6.23.0" classnames "2.x" @@ -7241,14 +7383,15 @@ rc-select@~7.7.0: dom-scroll-into-view "1.x" prop-types "^15.5.8" rc-animate "2.x" - rc-menu "^6.1.0" + rc-menu "^7.0.2" rc-trigger "^2.2.0" rc-util "^4.0.4" + react-lifecycles-compat "^3.0.2" warning "^3.0.0" rc-slider@~8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-8.6.0.tgz#73722ba6d838bfc8299c50b7a864226aa73f5c1e" + version "8.6.1" + resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-8.6.1.tgz#ee5e0380dbdf4b5de6955a265b0d4ff6196405d1" dependencies: babel-runtime "6.x" classnames "^2.2.5" @@ -7259,12 +7402,12 @@ rc-slider@~8.6.0: warning "^3.0.0" rc-steps@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/rc-steps/-/rc-steps-3.1.0.tgz#b204c9ef066287c5cc30dcbe485b2c1bf86e01c6" + version "3.1.1" + resolved "https://registry.yarnpkg.com/rc-steps/-/rc-steps-3.1.1.tgz#79583ad808309d82b8e011676321d153fd7ca403" dependencies: babel-runtime "^6.23.0" classnames "^2.2.3" - lodash.debounce "^4.0.8" + lodash "^4.17.5" prop-types "^15.5.7" rc-switch@~1.6.0: @@ -7276,22 +7419,22 @@ rc-switch@~1.6.0: prop-types "^15.5.6" rc-table@~6.1.0: - version "6.1.5" - resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-6.1.5.tgz#5610072ccfa4cd86e868819a7f37389bf2ca7aef" + version "6.1.15" + resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-6.1.15.tgz#c2da37118626604de70742ae87bffafe17351189" dependencies: babel-runtime "6.x" component-classes "^1.2.6" - lodash.get "^4.4.2" - lodash.merge "^4.6.0" + lodash "^4.17.5" mini-store "^1.0.2" prop-types "^15.5.8" rc-util "^4.0.4" + react-lifecycles-compat "^3.0.2" shallowequal "^1.0.2" warning "^3.0.0" rc-tabs@~9.2.0: - version "9.2.3" - resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-9.2.3.tgz#a6712be7ecb5660fe3be63f8cb0a40198ee295f2" + version "9.2.5" + resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-9.2.5.tgz#fdd8e0633247f50c533030b73e3992270849f1f6" dependencies: babel-runtime "6.x" classnames "2.x" @@ -7302,9 +7445,9 @@ rc-tabs@~9.2.0: rc-util "^4.0.4" warning "^3.0.0" -rc-time-picker@~3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/rc-time-picker/-/rc-time-picker-3.2.1.tgz#e105fed32814bb95f37dbc60b49495cd787abfa2" +rc-time-picker@~3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/rc-time-picker/-/rc-time-picker-3.3.1.tgz#94f8bbd51e6b93de1f01e78064aef1e6d765b367" dependencies: babel-runtime "6.x" classnames "2.x" @@ -7313,29 +7456,39 @@ rc-time-picker@~3.2.1: rc-trigger "^2.2.0" rc-tooltip@^3.7.0, rc-tooltip@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-3.7.0.tgz#3afbf109865f7cdcfe43752f3f3f501f7be37aaa" + version "3.7.2" + resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-3.7.2.tgz#3698656d4bacd51b72d9e327bed15d1d5a9f1b27" dependencies: babel-runtime "6.x" prop-types "^15.5.8" rc-trigger "^2.2.2" rc-tree-select@~1.12.0: - version "1.12.9" - resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-1.12.9.tgz#340ce3b1ce7afab2e717ee90febff114720e5fef" + version "1.12.13" + resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-1.12.13.tgz#3bf5684a3e38fbfbf8cc149d4f4a5d62f5ef0d47" dependencies: babel-runtime "^6.23.0" classnames "^2.2.1" - object-assign "^4.0.1" prop-types "^15.5.8" rc-animate "^2.0.2" rc-tree "~1.7.1" rc-trigger "^2.2.2" - rc-util "^4.0.2" + rc-util "^4.5.0" -rc-tree@~1.7.0, rc-tree@~1.7.1: - version "1.7.10" - resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-1.7.10.tgz#8d93d73fa3a91ebf6dde4ebaa98e750a9c8fe154" +rc-tree@~1.7.1: + version "1.7.11" + resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-1.7.11.tgz#349de6383fc7d22bf4c13b0751794111022adddf" + dependencies: + babel-runtime "^6.23.0" + classnames "2.x" + prop-types "^15.5.8" + rc-animate "2.x" + rc-util "^4.0.4" + warning "^3.0.0" + +rc-tree@~1.8.0: + version "1.8.3" + resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-1.8.3.tgz#2875e83bc951b5ed7577c1038490f8245d79a37f" dependencies: babel-runtime "^6.23.0" classnames "2.x" @@ -7345,15 +7498,15 @@ rc-tree@~1.7.0, rc-tree@~1.7.1: warning "^3.0.0" rc-trigger@^2.2.0, rc-trigger@^2.2.2, rc-trigger@^2.3.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-2.3.3.tgz#406c5ddea594aca71d067852f27d91a5f3a653b8" + version "2.5.4" + resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-2.5.4.tgz#9088a24ba5a811b254f742f004e38a9e2f8843fb" dependencies: babel-runtime "6.x" - create-react-class "15.x" + classnames "^2.2.6" prop-types "15.x" - rc-align "2.x" + rc-align "^2.4.0" rc-animate "2.x" - rc-util "^4.3.0" + rc-util "^4.4.0" rc-upload@~2.4.0: version "2.4.4" @@ -7364,20 +7517,20 @@ rc-upload@~2.4.0: prop-types "^15.5.7" warning "2.x" -rc-util@^4.0.2, rc-util@^4.0.4, rc-util@^4.1.0, rc-util@^4.1.1, rc-util@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.3.1.tgz#79f0adb30f449c1b29d7c5cdb2d82c193920c362" +rc-util@^4.0.4, rc-util@^4.1.0, rc-util@^4.1.1, rc-util@^4.3.0, rc-util@^4.4.0, rc-util@^4.5.0, rc-util@^4.5.1: + version "4.5.1" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.5.1.tgz#0e435057174c024901c7600ba8903dd03da3ab39" dependencies: add-dom-event-listener "1.x" babel-runtime "6.x" prop-types "^15.5.10" shallowequal "^0.2.2" -rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: - version "1.2.5" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd" +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" dependencies: - deep-extend "~0.4.0" + deep-extend "^0.6.0" ini "~1.3.0" minimist "^1.2.0" strip-json-comments "~2.0.1" @@ -7419,8 +7572,8 @@ react-dom@^15.6.0: prop-types "^15.5.10" react-dom@^16.0.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" + version "16.4.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.1.tgz#7f8b0223b3a5fbe205116c56deb85de32685dad6" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -7459,6 +7612,10 @@ react-lazy-load@^3.0.12: lodash.throttle "^4.0.0" prop-types "^15.5.8" +react-lifecycles-compat@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + react-proxy@^3.0.0-alpha.0: version "3.0.0-alpha.1" resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07" @@ -7466,56 +7623,54 @@ react-proxy@^3.0.0-alpha.0: lodash "^4.6.1" react-router-dom@^4.1.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d" + version "4.3.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" dependencies: history "^4.7.2" - invariant "^2.2.2" + invariant "^2.2.4" loose-envify "^1.3.1" - prop-types "^15.5.4" - react-router "^4.2.0" - warning "^3.0.0" + prop-types "^15.6.1" + react-router "^4.3.1" + warning "^4.0.1" -react-router@^4.1.1, react-router@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.2.0.tgz#61f7b3e3770daeb24062dae3eedef1b054155986" +react-router@^4.1.1, react-router@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e" dependencies: history "^4.7.2" - hoist-non-react-statics "^2.3.0" - invariant "^2.2.2" + hoist-non-react-statics "^2.5.0" + invariant "^2.2.4" loose-envify "^1.3.1" path-to-regexp "^1.7.0" - prop-types "^15.5.4" - warning "^3.0.0" + prop-types "^15.6.1" + warning "^4.0.1" react-side-effect@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.3.tgz#512c25abe0dec172834c4001ec5c51e04d41bc5c" + version "1.1.5" + resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d" dependencies: exenv "^1.2.1" shallowequal "^1.0.1" -react-slick@~0.17.0: - version "0.17.1" - resolved "https://registry.yarnpkg.com/react-slick/-/react-slick-0.17.1.tgz#64b6a23d3b3823047e6e705a3578301483da8748" +react-slick@~0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/react-slick/-/react-slick-0.23.1.tgz#15791c4107f0ba3a5688d5bd97b7b7ceaa0dd181" dependencies: - can-use-dom "^0.1.0" classnames "^2.2.5" - create-react-class "^15.5.2" enquire.js "^2.1.6" json2mq "^0.2.0" - object-assign "^4.1.0" - opencollective "^1.0.3" + lodash.debounce "^4.0.8" + resize-observer-polyfill "^1.5.0" -react-syntax-highlighter@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-7.0.0.tgz#a522ccf95f272178b8f25de2184383e9bf647155" +react-syntax-highlighter@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-8.0.0.tgz#d093c8cadca0ac27a5b6e1aedfcc7c9c215da36a" dependencies: babel-runtime "^6.18.0" highlight.js "~9.12.0" lowlight "~1.9.1" prismjs "^1.8.4" - refractor "^2.0.0" + refractor "^2.4.1" react@^15.6.0: version "15.6.2" @@ -7528,8 +7683,8 @@ react@^15.6.0: prop-types "^15.5.10" react@^16.0.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" + version "16.4.1" + resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -7587,16 +7742,16 @@ readable-stream@1.0, readable-stream@~1.0.31: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" isarray "~1.0.0" - process-nextick-args "~1.0.6" + process-nextick-args "~2.0.0" safe-buffer "~5.1.1" - string_decoder "~1.0.3" + string_decoder "~1.1.1" util-deprecate "~1.0.1" readdir-enhanced@^1.5.2: @@ -7629,8 +7784,8 @@ recursive-readdir@2.2.1: minimatch "3.0.3" redbox-react@^1.3.6: - version "1.5.0" - resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.5.0.tgz#04dab11557d26651bf3562a67c22ace56c5d3967" + version "1.6.0" + resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.6.0.tgz#e753ac02595bc1bf695b3935889a4f5b1b5a21a1" dependencies: error-stack-parser "^1.3.6" object-assign "^4.0.1" @@ -7652,8 +7807,8 @@ reduce-function-call@^1.0.1: balanced-match "^0.4.2" redux-devtools-instrument@^1.3.3: - version "1.8.2" - resolved "https://registry.yarnpkg.com/redux-devtools-instrument/-/redux-devtools-instrument-1.8.2.tgz#5e91cfe402e790dae3fd2f0d235f7b7d84b09ffe" + version "1.8.3" + resolved "https://registry.yarnpkg.com/redux-devtools-instrument/-/redux-devtools-instrument-1.8.3.tgz#c510d67ab4e5e4525acd6e410c25ab46b85aca7c" dependencies: lodash "^4.2.0" symbol-observable "^1.0.2" @@ -7667,18 +7822,18 @@ redux@^3.6.0: loose-envify "^1.1.0" symbol-observable "^1.0.3" -refractor@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.3.0.tgz#b8cade8f88020f8836ca3622c6ef87fd2444d76a" +refractor@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.4.1.tgz#067654311ed1618fc2dd76e9263c8cf05ab6298b" dependencies: hastscript "^3.1.0" - prismjs "~1.10.0" + prismjs "~1.14.0" regenerate@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" -regenerator-runtime@^0.10.0, regenerator-runtime@^0.10.5: +regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" @@ -7700,11 +7855,12 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" -regex-not@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" dependencies: - extend-shallow "^2.0.1" + extend-shallow "^3.0.2" + safe-regex "^1.1.0" regexpu-core@^1.0.0: version "1.0.0" @@ -7722,14 +7878,14 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -registry-auth-token@^3.0.1: +registry-auth-token@3.3.2, registry-auth-token@^3.0.1: version "3.3.2" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" dependencies: rc "^1.1.6" safe-buffer "^5.0.1" -registry-url@^3.0.3: +registry-url@3.1.0, registry-url@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" dependencies: @@ -7745,7 +7901,7 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -relay-compiler@^1.4.1: +relay-compiler@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/relay-compiler/-/relay-compiler-1.4.1.tgz#10e83f0f5de8db3d000851a4c0e435e7dd1deb95" dependencies: @@ -7883,10 +8039,10 @@ remote-redux-devtools@^0.5.7: socketcluster-client "^5.3.1" remotedev-serialize@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/remotedev-serialize/-/remotedev-serialize-0.1.0.tgz#074768e98cb7aa806f45994eeb0c8af95120ee32" + version "0.1.1" + resolved "https://registry.yarnpkg.com/remotedev-serialize/-/remotedev-serialize-0.1.1.tgz#0f598000b7dd7515d67f9b51a61d211e18ce9554" dependencies: - jsan "^3.1.0" + jsan "^3.1.9" remotedev-utils@^0.1.1: version "0.1.4" @@ -7930,34 +8086,7 @@ replace-ext@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" -request@2, request@^2.58.0, request@^2.67.0, request@^2.74.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@2.81.0: +request@2.81.0, "request@>=2.9.0 <2.82.0": version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -7984,6 +8113,31 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +request@^2.58.0, request@^2.67.0, request@^2.74.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -7996,10 +8150,14 @@ 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" -requires-port@1.0.x, requires-port@1.x.x, requires-port@~1.0.0: +requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" +resize-observer-polyfill@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69" + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -8033,8 +8191,8 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" resolve@^1.1.6, resolve@^1.1.7: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: path-parse "^1.0.5" @@ -8049,6 +8207,10 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + retext-english@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/retext-english/-/retext-english-3.0.0.tgz#c17cb56bd5f1ba3dee3355ddbab79f1c4894a809" @@ -8078,7 +8240,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.3.2, rimraf@^2.4.4, rimraf@^2.5.0, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.3.2, rimraf@^2.4.4, rimraf@^2.5.0, rimraf@^2.5.4, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -8089,15 +8251,15 @@ ripemd160@0.2.0: resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" dependencies: - hash-base "^2.0.0" + hash-base "^3.0.0" inherits "^2.0.1" -rmc-feedback@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/rmc-feedback/-/rmc-feedback-1.0.4.tgz#fba066059ae2057ac0e0b53ea7ce982c8f4f7f19" +rmc-feedback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rmc-feedback/-/rmc-feedback-2.0.0.tgz#cbc6cb3ae63c7a635eef0e25e4fbaf5ac366eeaa" dependencies: babel-runtime "6.x" classnames "^2.2.5" @@ -8106,11 +8268,12 @@ rn-host-detect@^1.0.1: version "1.1.3" resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.1.3.tgz#242d76e2fa485c48d751416e65b7cce596969e91" -rollup@^0.36.3: - version "0.36.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.36.4.tgz#a224494c5386c1d73d38f7bb86f69f5eb011a3d2" +rollup@^0.58.2: + version "0.58.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.58.2.tgz#2feddea8c0c022f3e74b35c48e3c21b3433803ce" dependencies: - source-map-support "^0.4.0" + "@types/estree" "0.0.38" + "@types/node" "*" rsvp@^3.0.13, rsvp@^3.0.18: version "3.6.2" @@ -8132,18 +8295,28 @@ rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + sane@^1.3.3: version "1.7.0" resolved "https://registry.yarnpkg.com/sane/-/sane-1.7.0.tgz#b3579bccb45c94cf20355cc81124990dfd346e30" @@ -8157,19 +8330,21 @@ sane@^1.3.3: watch "~0.10.0" sanitize-html@^1.14.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.17.0.tgz#5c95e57044604d4797367efd9152acaf5b087bb4" + version "1.18.2" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.2.tgz#61877ba5a910327e42880a28803c2fbafa8e4642" dependencies: chalk "^2.3.0" htmlparser2 "^3.9.0" lodash.clonedeep "^4.5.0" lodash.escaperegexp "^4.1.2" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" lodash.mergewith "^4.6.0" postcss "^6.0.14" srcset "^1.0.0" xtend "^4.0.0" -sax@~1.2.1: +sax@^1.2.4, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -8193,6 +8368,12 @@ sc-formatter@~3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/sc-formatter/-/sc-formatter-3.0.2.tgz#9abdb14e71873ce7157714d3002477bbdb33c4e6" +schema-utils@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" + dependencies: + ajv "^5.0.0" + scroll-behavior@^0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/scroll-behavior/-/scroll-behavior-0.9.9.tgz#ebfe0658455b82ad885b66195215416674dacce2" @@ -8222,14 +8403,14 @@ semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -send@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" dependencies: debug "2.6.9" - depd "~1.1.1" + depd "~1.1.2" destroy "~1.0.4" - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" @@ -8238,7 +8419,7 @@ send@0.16.1: ms "2.0.0" on-finished "~2.3.0" range-parser "~1.2.0" - statuses "~1.3.1" + statuses "~1.4.0" serve-index@^1.7.2: version "1.9.1" @@ -8252,41 +8433,41 @@ serve-index@^1.7.2: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" dependencies: - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.2" - send "0.16.1" + send "0.16.2" serve@^6.4.0: - version "6.4.9" - resolved "https://registry.yarnpkg.com/serve/-/serve-6.4.9.tgz#1d8721132d58a2f6fc6469bb62df9b5d2eacc5ca" + version "6.5.8" + resolved "https://registry.yarnpkg.com/serve/-/serve-6.5.8.tgz#fd7ad6b9c10ba12084053030cc1a8b636c0a10a7" dependencies: - "@zeit/check-updates" "1.0.5" - args "3.0.8" + args "4.0.0" basic-auth "2.0.0" bluebird "3.5.1" boxen "1.3.0" - chalk "2.3.0" - clipboardy "1.2.2" + chalk "2.4.1" + clipboardy "1.2.3" dargs "5.1.0" - detect-port "1.2.2" - filesize "3.5.11" - fs-extra "5.0.0" + detect-port "1.2.3" + filesize "3.6.1" + fs-extra "6.0.1" handlebars "4.0.11" ip "1.1.5" - micro "9.1.0" + micro "9.3.1" micro-compress "1.0.0" - mime-types "2.1.17" - node-version "1.1.0" + mime-types "2.1.18" + node-version "1.1.3" openssl-self-signed-certificate "1.1.6" - opn "5.1.0" + opn "5.3.0" path-is-inside "1.0.2" path-type "3.0.0" - send "0.16.1" + send "0.16.2" + update-check "1.5.1" set-blocking@^1.0.0: version "1.0.0" @@ -8296,12 +8477,6 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -set-getter@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - dependencies: - to-object-path "^0.3.0" - set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -8341,8 +8516,8 @@ sha.js@2.2.6: resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.10" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b" + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -8371,8 +8546,8 @@ shallowequal@^0.2.2: lodash.keys "^3.1.2" shallowequal@^1.0.1, shallowequal@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" shebang-command@^1.2.0: version "1.2.0" @@ -8436,8 +8611,8 @@ snapdragon-util@^3.0.1: kind-of "^3.2.0" snapdragon@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" dependencies: base "^0.11.1" debug "^2.2.0" @@ -8446,7 +8621,7 @@ snapdragon@^0.8.1: map-cache "^0.2.2" source-map "^0.5.6" source-map-resolve "^0.5.0" - use "^2.0.0" + use "^3.1.0" sntp@1.x.x: version "1.0.9" @@ -8454,52 +8629,47 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - dependencies: - hoek "4.x.x" - socket.io-adapter@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" -socket.io-client@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.4.tgz#0918a552406dc5e540b380dcd97afc4a64332f8e" +socket.io-client@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" dependencies: backo2 "1.0.2" base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" - debug "~2.6.4" - engine.io-client "~3.1.0" + debug "~3.1.0" + engine.io-client "~3.2.0" + has-binary2 "~1.0.2" has-cors "1.1.0" indexof "0.0.1" object-component "0.0.3" parseqs "0.0.5" parseuri "0.0.5" - socket.io-parser "~3.1.1" + socket.io-parser "~3.2.0" to-array "0.1.4" -socket.io-parser@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.2.tgz#dbc2282151fc4faebbe40aeedc0772eba619f7f2" +socket.io-parser@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" dependencies: component-emitter "1.2.1" - debug "~2.6.4" - has-binary2 "~1.0.2" + debug "~3.1.0" isarray "2.0.1" socket.io@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.0.4.tgz#c1a4590ceff87ecf13c72652f046f716b29e6014" + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" dependencies: - debug "~2.6.6" - engine.io "~3.1.0" + debug "~3.1.0" + engine.io "~3.2.0" + has-binary2 "~1.0.2" socket.io-adapter "~1.1.0" - socket.io-client "2.0.4" - socket.io-parser "~3.1.1" + socket.io-client "2.1.1" + socket.io-parser "~3.2.0" socketcluster-client@^5.3.1: version "5.5.2" @@ -8515,7 +8685,7 @@ socketcluster-client@^5.3.1: sc-formatter "~3.0.0" ws "3.0.0" -sockjs-client@1.1.4, sockjs-client@^1.0.3: +sockjs-client@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.4.tgz#5babe386b775e4cf14e7520911452654016c8b12" dependencies: @@ -8526,6 +8696,17 @@ sockjs-client@1.1.4, sockjs-client@^1.0.3: json3 "^3.3.2" url-parse "^1.1.8" +sockjs-client@^1.0.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.5.tgz#1bb7c0f7222c40f42adf14f4442cbd1269771a83" + dependencies: + debug "^2.6.6" + eventsource "0.1.6" + faye-websocket "~0.11.0" + inherits "^2.0.1" + json3 "^3.3.2" + url-parse "^1.1.8" + sockjs@^0.3.15: version "0.3.19" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" @@ -8548,16 +8729,16 @@ source-list-map@^1.1.1: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" source-map-resolve@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" dependencies: - atob "^2.0.0" + atob "^2.1.1" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.0, source-map-support@^0.4.15: +source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: @@ -8610,24 +8791,32 @@ sourcemapped-stacktrace@^1.1.6: source-map "0.5.6" space-separated-tokens@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz#9695b9df9e65aec1811d4c3f9ce52520bc2f7e4d" + version "1.1.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz#e95ab9d19ae841e200808cd96bc7bd0adbbb3412" dependencies: trim "0.0.1" -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" dependencies: - spdx-license-ids "^1.0.2" + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" -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-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" -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" +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -8651,13 +8840,14 @@ srcset@^1.0.0: number-is-nan "^1.0.0" sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" dashdash "^1.12.0" getpass "^0.1.1" + safer-buffer "^2.0.2" optionalDependencies: bcrypt-pbkdf "^1.0.0" ecc-jsbn "~0.1.1" @@ -8672,13 +8862,13 @@ stackframe@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-0.3.1.tgz#33aa84f1177a5548c8935533cbfeb3420975f5a4" -stackframe@^1.0.3: +stackframe@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" state-toggle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" + version "1.0.1" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a" static-extend@^0.1.1: version "0.1.2" @@ -8697,14 +8887,14 @@ static-site-generator-webpack-plugin@^3.4.1: url "^0.11.0" webpack-sources "^0.2.0" -"statuses@>= 1.3.1 < 2": +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - steno@^0.4.1: version "0.4.4" resolved "https://registry.yarnpkg.com/steno/-/steno-0.4.4.tgz#071105bdfc286e6615c0403c27e9d7b5dcb855cb" @@ -8723,12 +8913,12 @@ stream-cache@~0.0.1: resolved "https://registry.yarnpkg.com/stream-cache/-/stream-cache-0.0.2.tgz#1ac5ad6832428ca55667dbdee395dad4e6db118f" stream-http@^2.3.1, stream-http@^2.7.2: - version "2.8.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" - readable-stream "^2.3.3" + readable-stream "^2.3.6" to-arraybuffer "^1.0.0" xtend "^4.0.0" @@ -8740,19 +8930,13 @@ string-convert@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" -string-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" - dependencies: - strip-ansi "^3.0.0" - -string-similarity@1.2.0, string-similarity@^1.2.0: +string-similarity@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-1.2.0.tgz#d75153cb383846318b7a39a8d9292bb4db4e9c30" dependencies: lodash "^4.13.1" -string-width@^1.0.1, string-width@^1.0.2: +string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: @@ -8760,7 +8944,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -8771,24 +8955,24 @@ string_decoder@^0.10.25, string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -string_decoder@^1.0.0, string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" dependencies: safe-buffer "~5.1.0" stringify-entities@^1.0.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.1.tgz#b150ec2d72ac4c1b5f324b51fb6b28c9cdff058c" + version "1.3.2" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7" dependencies: character-entities-html4 "^1.0.0" character-entities-legacy "^1.0.0" is-alphanumerical "^1.0.0" is-hexadecimal "^1.0.0" -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" +stringstream@~0.0.4: + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" strip-ansi@3.0.1, strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" @@ -8840,17 +9024,11 @@ supports-color@^3.1.0, supports-color@^3.1.1, supports-color@^3.2.3: dependencies: has-flag "^1.0.0" -supports-color@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" dependencies: - has-flag "^2.0.0" - -supports-color@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" - dependencies: - has-flag "^2.0.0" + has-flag "^3.0.0" svgo@^0.7.0: version "0.7.2" @@ -8872,9 +9050,9 @@ symbol@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/symbol/-/symbol-0.2.3.tgz#3b9873b8a901e47c6efe21526a3ac372ef28bbc7" -systemjs-builder@0.16.12: - version "0.16.12" - resolved "https://registry.yarnpkg.com/systemjs-builder/-/systemjs-builder-0.16.12.tgz#0ceee27504d7903b09e047c660563d9ff2c0007b" +systemjs-builder@0.16.13: + version "0.16.13" + resolved "https://registry.yarnpkg.com/systemjs-builder/-/systemjs-builder-0.16.13.tgz#02b47d03afd1e2f29562b11ec8bc13457e785c76" dependencies: babel-core "^6.24.1" babel-plugin-syntax-dynamic-import "^6.18.0" @@ -8888,15 +9066,15 @@ systemjs-builder@0.16.12: es6-template-strings "^2.0.0" glob "^7.0.3" mkdirp "^0.5.1" - rollup "^0.36.3" + rollup "^0.58.2" source-map "^0.5.3" systemjs "^0.19.46" traceur "0.0.105" uglify-js "^2.6.1" -systemjs@0.20.19: - version "0.20.19" - resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-0.20.19.tgz#c2b9e79c19f4bea53a19b1ed3f974ffb463be949" +systemjs@0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/systemjs/-/systemjs-0.21.3.tgz#76467a34a9a12ead3b11028a27345f7649e46204" systemjs@^0.19.46: version "0.19.47" @@ -8909,37 +9087,27 @@ tapable@^0.1.8, tapable@~0.1.8: resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" tar-fs@^1.13.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.0.tgz#e877a25acbcc51d8c790da1c57c9cf439817b896" + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" dependencies: chownr "^1.0.1" mkdirp "^0.5.1" pump "^1.0.0" tar-stream "^1.1.2" -tar-pack@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - tar-stream@^1.1.2: - version "1.5.5" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" + version "1.6.1" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" dependencies: bl "^1.0.0" + buffer-alloc "^1.1.0" end-of-stream "^1.0.0" - readable-stream "^2.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.0" xtend "^4.0.0" -tar@^2.0.0, tar@^2.2.1: +tar@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -8947,6 +9115,18 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" +tar@^4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -8977,8 +9157,8 @@ timed-out@^4.0.0: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" timers-browserify@^2.0.2, timers-browserify@^2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae" + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" dependencies: setimmediate "^1.0.4" @@ -8986,6 +9166,12 @@ tiny-emitter@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c" +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9004,6 +9190,10 @@ to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" +to-buffer@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + 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" @@ -9025,13 +9215,14 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" -to-regex@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" dependencies: - define-property "^0.2.5" - extend-shallow "^2.0.1" - regex-not "^1.0.0" + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" topo@2.x.x: version "2.0.2" @@ -9040,8 +9231,8 @@ topo@2.x.x: hoek "4.x.x" tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1" @@ -9056,24 +9247,28 @@ traceur@0.0.105: source-map-support "~0.2.8" trim-lines@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.0.tgz#9926d03ede13ba18f7d42222631fb04c79ff26fe" + version "1.1.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.1.tgz#da738ff58fa74817588455e30b11b85289f2a396" trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" trim-trailing-lines@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz#7aefbb7808df9d669f6da2e438cac8c46ada7684" + version "1.1.1" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9" trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" trough@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.1.tgz#a9fd8b0394b0ae8fff82e0633a0a36ccad5b5f86" + version "1.0.2" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.2.tgz#7f1663ec55c480139e2de5e486c6aef6cc24a535" + +tslib@^1.6.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" tty-browserify@0.0.0: version "0.0.0" @@ -9089,20 +9284,20 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -type-is@~1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" +type-is@~1.6.15, type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" dependencies: media-typer "0.3.0" - mime-types "~2.1.15" + mime-types "~2.1.18" type-of@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/type-of/-/type-of-2.0.1.tgz#e72a1741896568e9f628378d816d6912f7f23972" -ua-parser-js@^0.7.9: - version "0.7.17" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" +ua-parser-js@^0.7.18: + version "0.7.18" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" uglify-js@^2.6, uglify-js@^2.6.1: version "2.8.29" @@ -9126,10 +9321,6 @@ uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -9146,22 +9337,21 @@ underscore.string@^3.3.4: util-deprecate "^1.0.2" unherit@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.0.tgz#6b9aaedfbf73df1756ad9e316dd981885840cd7d" + version "1.1.1" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" dependencies: inherits "^2.0.1" xtend "^4.0.1" unified@^6.0.0, unified@^6.1.5: - version "6.1.6" - resolved "https://registry.yarnpkg.com/unified/-/unified-6.1.6.tgz#5ea7f807a0898f1f8acdeefe5f25faa010cc42b1" + version "6.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" dependencies: bail "^1.0.0" extend "^3.0.0" is-plain-obj "^1.1.0" trough "^1.0.0" vfile "^2.0.0" - x-is-function "^1.0.4" x-is-string "^0.1.0" union-value@^1.0.0: @@ -9177,12 +9367,6 @@ uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" -uniqid@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1" - dependencies: - macaddress "^0.2.8" - uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" @@ -9200,26 +9384,26 @@ unist-builder@^1.0.1: object-assign "^4.1.0" unist-util-generated@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.1.tgz#99f16c78959ac854dee7c615c291924c8bf4de7f" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.2.tgz#8b993f9239d8e560be6ee6e91c3f7b7208e5ce25" unist-util-is@^2.0.0, unist-util-is@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.1.tgz#0c312629e3f960c66e931e812d3d80e77010947b" + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" unist-util-modify-children@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz#66d7e6a449e6f67220b976ab3cb8b5ebac39e51d" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz#c7f1b91712554ee59c47a05b551ed3e052a4e2d1" dependencies: array-iterate "^1.0.0" unist-util-position@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.0.0.tgz#e6e1e03eeeb81c5e1afe553e8d4adfbd7c0d8f82" + version "3.0.1" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.0.1.tgz#8e220c24658239bf7ddafada5725ed0ea1ebbc26" unist-util-remove-position@^1.0.0, unist-util-remove-position@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz#5a85c1555fc1ba0c101b86707d15e50fa4c871bb" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb" dependencies: unist-util-visit "^1.1.0" @@ -9232,16 +9416,16 @@ unist-util-select@^1.5.0: nth-check "^1.0.1" unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" unist-util-visit-children@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-children/-/unist-util-visit-children-1.1.1.tgz#eba63b371116231181068837118b6e6e10ec8844" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-children/-/unist-util-visit-children-1.1.2.tgz#bd78b53db9644b9c339ac502854f15471f964f5b" unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.1.1, unist-util-visit@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.0.tgz#41ca7c82981fd1ce6c762aac397fc24e35711444" + version "1.3.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.1.tgz#c019ac9337a62486be58531bc27e7499ae7d55c7" dependencies: unist-util-is "^2.1.1" @@ -9253,8 +9437,8 @@ units-css@^0.4.0: viewport-dimensions "^0.2.0" universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" @@ -9271,14 +9455,22 @@ unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" +update-check@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.1.tgz#24fc52266273cb8684d2f1bf9687c0e52dcf709f" + dependencies: + registry-auth-token "3.3.2" + registry-url "3.1.0" + update-notifier@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451" + version "2.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" dependencies: boxen "^1.2.1" chalk "^2.0.1" configstore "^3.0.0" import-lazy "^2.1.0" + is-ci "^1.0.10" is-installed-globally "^0.1.0" is-npm "^1.0.0" latest-version "^3.0.0" @@ -9289,12 +9481,13 @@ urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" -url-loader@^0.5.7: - version "0.5.9" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295" +url-loader@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.6.2.tgz#a007a7109620e9d988d14bce677a1decb9a993f7" dependencies: loader-utils "^1.0.2" - mime "1.3.x" + mime "^1.4.1" + schema-utils "^0.3.0" url-parse-lax@^1.0.0: version "1.0.0" @@ -9302,19 +9495,12 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -url-parse@1.0.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" +url-parse@^1.1.8, url-parse@~1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.1.tgz#4dec9dad3dc8585f862fed461d2e19bbf623df30" dependencies: - querystringify "0.0.x" - requires-port "1.0.x" - -url-parse@^1.1.8: - version "1.2.0" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986" - dependencies: - querystringify "~1.0.0" - requires-port "~1.0.0" + querystringify "^2.0.0" + requires-port "^1.0.0" url-to-options@^1.0.1: version "1.0.1" @@ -9327,13 +9513,11 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -use@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" dependencies: - define-property "^0.2.5" - isobject "^3.0.0" - lazy-cache "^2.0.2" + kind-of "^6.0.2" user-home@^1.1.1: version "1.1.1" @@ -9343,12 +9527,18 @@ util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util@0.10.3, util@^0.10.3: +util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: inherits "2.0.1" +util@^0.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + dependencies: + inherits "2.0.3" + utila@~0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/utila/-/utila-0.3.3.tgz#d7e8e7d7e309107092b05f8d9688824d633a4226" @@ -9362,12 +9552,8 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - -uws@~0.14.4: - version "0.14.5" - resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc" + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" v8-compile-cache@^1.1.0: version "1.1.2" @@ -9384,11 +9570,11 @@ valid-url@^1.0.9: resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" 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" + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" value-equal@^0.4.0: version "0.4.0" @@ -9399,8 +9585,8 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" vendors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" + version "1.0.2" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" verror@1.10.0: version "1.10.0" @@ -9411,12 +9597,12 @@ verror@1.10.0: extsprintf "^1.2.0" vfile-location@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.2.tgz#d3675c59c877498e492b4756ff65e4af1a752255" + version "2.0.3" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.3.tgz#083ba80e50968e8d420be49dd1ea9a992131df77" vfile-message@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.0.tgz#a6adb0474ea400fa25d929f1d673abea6a17e359" + version "1.0.1" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.1.tgz#51a2ccd8a6b97a7980bb34efb9ebde9632e93677" dependencies: unist-util-stringify-position "^1.1.1" @@ -9451,12 +9637,18 @@ warning@2.x: dependencies: loose-envify "^1.0.0" -warning@^3.0.0, warning@~3.0.0: +warning@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" dependencies: loose-envify "^1.0.0" +warning@^4.0.1, warning@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.1.tgz#66ce376b7fbfe8a887c22bdf0e7349d73d397745" + dependencies: + loose-envify "^1.0.0" + watch@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc" @@ -9470,8 +9662,8 @@ watchpack@^0.2.1: graceful-fs "^4.1.2" web-namespaces@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.1.tgz#742d9fff61ff84f4164f677244f42d29c10c451d" + version "1.1.2" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.2.tgz#c8dc267ab639505276bae19e129dbd6ae72b22b4" webpack-configurator@^0.3.0: version "0.3.1" @@ -9521,8 +9713,8 @@ webpack-dev-server@^1.16.1: webpack-dev-middleware "^1.10.2" webpack-hot-middleware@^2.13.2: - version "2.21.0" - resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.21.0.tgz#7b3c113a7a4b301c91e0749573c7aab28b414b52" + version "2.22.2" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.22.2.tgz#623b77ce591fcd4e1fb99f18167781443e50afac" dependencies: ansi-html "0.0.7" html-entities "^1.2.0" @@ -9601,8 +9793,8 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" whatwg-fetch@>=0.10.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" when@^3.7.5: version "3.7.8" @@ -9617,16 +9809,16 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" which@1, which@^1.0.9, which@^1.1.1, which@^1.2.12, which@^1.2.14, which@^1.2.9: - version "1.3.0" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: isexe "^2.0.0" wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" dependencies: - string-width "^1.0.2" + string-width "^1.0.2 || 2" widest-line@^2.0.0: version "2.0.0" @@ -9688,10 +9880,6 @@ x-is-array@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-array/-/x-is-array-0.1.0.tgz#de520171d47b3f416f5587d629b89d26b12dc29d" -x-is-function@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" - x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" @@ -9716,6 +9904,10 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + yaml-loader@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.4.0.tgz#4aae447d13c1aa73a989d8a2a5309b0b1a3ca353" @@ -9735,6 +9927,12 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + dependencies: + camelcase "^4.1.0" + yargs@4.7.1: version "4.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.7.1.tgz#e60432658a3387ff269c028eacde4a512e438dff" @@ -9753,23 +9951,22 @@ yargs@4.7.1: y18n "^3.2.1" yargs-parser "^2.4.0" -yargs@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" +yargs@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" + cliui "^4.0.0" decamelize "^1.1.1" + find-up "^2.1.0" get-caller-file "^1.0.1" os-locale "^2.0.0" - read-pkg-up "^2.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^7.0.0" + yargs-parser "^9.0.2" yargs@^9.0.0: version "9.0.1" @@ -9832,5 +10029,5 @@ yurnalist@^0.2.1: strip-bom "^3.0.0" zwitch@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.2.tgz#9b059541bfa844799fe2d903bde609de2503a041" + version "1.0.3" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.3.tgz#159fae4b3f737db1e42bf321d3423e4c96688a18" From ede28883262af1b852bb0e72f4231475f9d13f6c Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 04:09:39 -0700 Subject: [PATCH 009/189] Lint / reformat `YGJNI.cpp` Summary: Run clangformat on `YGJNI.cpp` @public Reviewed By: priteshrnandgaonkar Differential Revision: D8785660 fbshipit-source-id: 9748a5297e7b55e897de0280a79c2ea6ae1c1298 --- java/jni/YGJNI.cpp | 387 +++++++++++++++++++++++++++------------------ 1 file changed, 230 insertions(+), 157 deletions(-) diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 5649ef7e..1d6f464c 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -33,13 +33,17 @@ struct YGConfigContext { } }; -static inline weak_ref *YGNodeJobject(YGNodeRef node) { +static inline weak_ref* YGNodeJobject(YGNodeRef node) { return reinterpret_cast*>(node->getContext()); } -static void YGTransferLayoutDirection(YGNodeRef node, alias_ref javaNode) { - static auto layoutDirectionField = javaNode->getClass()->getField("mLayoutDirection"); - javaNode->setFieldValue(layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); +static void YGTransferLayoutDirection( + YGNodeRef node, + alias_ref javaNode) { + static auto layoutDirectionField = + javaNode->getClass()->getField("mLayoutDirection"); + javaNode->setFieldValue( + layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { @@ -50,23 +54,37 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { static auto leftField = obj->getClass()->getField("mLeft"); static auto topField = obj->getClass()->getField("mTop"); - static auto marginLeftField = obj->getClass()->getField("mMarginLeft"); - static auto marginTopField = obj->getClass()->getField("mMarginTop"); - static auto marginRightField = obj->getClass()->getField("mMarginRight"); - static auto marginBottomField = obj->getClass()->getField("mMarginBottom"); + static auto marginLeftField = + obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = + obj->getClass()->getField("mMarginTop"); + static auto marginRightField = + obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = + obj->getClass()->getField("mMarginBottom"); - static auto paddingLeftField = obj->getClass()->getField("mPaddingLeft"); - static auto paddingTopField = obj->getClass()->getField("mPaddingTop"); - static auto paddingRightField = obj->getClass()->getField("mPaddingRight"); - static auto paddingBottomField = obj->getClass()->getField("mPaddingBottom"); + static auto paddingLeftField = + obj->getClass()->getField("mPaddingLeft"); + static auto paddingTopField = + obj->getClass()->getField("mPaddingTop"); + static auto paddingRightField = + obj->getClass()->getField("mPaddingRight"); + static auto paddingBottomField = + obj->getClass()->getField("mPaddingBottom"); - static auto borderLeftField = obj->getClass()->getField("mBorderLeft"); - static auto borderTopField = obj->getClass()->getField("mBorderTop"); - static auto borderRightField = obj->getClass()->getField("mBorderRight"); - static auto borderBottomField = obj->getClass()->getField("mBorderBottom"); + static auto borderLeftField = + obj->getClass()->getField("mBorderLeft"); + static auto borderTopField = + obj->getClass()->getField("mBorderTop"); + static auto borderRightField = + obj->getClass()->getField("mBorderRight"); + static auto borderBottomField = + obj->getClass()->getField("mBorderBottom"); - static auto edgeSetFlagField = obj->getClass()->getField("mEdgeSetFlag"); - static auto hasNewLayoutField = obj->getClass()->getField("mHasNewLayout"); + static auto edgeSetFlagField = + obj->getClass()->getField("mEdgeSetFlag"); + static auto hasNewLayoutField = + obj->getClass()->getField("mHasNewLayout"); static auto doesLegacyStretchBehaviour = obj->getClass()->getField( "mDoesLegacyStretchFlagAffectsLayout"); @@ -76,7 +94,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { const int PADDING = 2; const int BORDER = 4; - int hasEdgeSetFlag = (int) obj->getFieldValue(edgeSetFlagField); + int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); @@ -98,17 +116,25 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { } if ((hasEdgeSetFlag & PADDING) == 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)); + 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 ((hasEdgeSetFlag & BORDER) == 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)); + obj->setFieldValue( + borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); + obj->setFieldValue( + borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); + obj->setFieldValue( + borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); + obj->setFieldValue( + borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); } obj->setFieldValue(hasNewLayoutField, true); @@ -119,7 +145,10 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } else { - YGLog(root, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + root, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); } } } @@ -128,14 +157,18 @@ static void YGPrint(YGNodeRef node) { if (auto obj = YGNodeJobject(node)->lockLocal()) { cout << obj->toString() << endl; } else { - YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + node, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); } } static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) { if (auto obj = YGNodeJobject(node)->lockLocal()) { - static auto baselineFunc = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod("baseline"); + static auto baselineFunc = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod("baseline"); return baselineFunc(obj, width, height); } else { return height; @@ -150,20 +183,17 @@ static inline YGConfigRef _jlong2YGConfigRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } -static YGNodeRef YGJNIOnNodeClonedFunc( - YGNodeRef oldNode, - YGNodeRef owner, - int childIndex) { +static YGNodeRef +YGJNIOnNodeClonedFunc(YGNodeRef oldNode, YGNodeRef owner, int childIndex) { auto config = oldNode->getConfig(); if (!config) { return nullptr; } - static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig") - ->getMethod( - local_ref, - local_ref, - jint)>("cloneNode"); + static auto onNodeClonedFunc = + findClassStatic("com/facebook/yoga/YogaConfig") + ->getMethod( + local_ref, local_ref, jint)>("cloneNode"); auto context = reinterpret_cast(YGConfigGetContext(config)); auto javaConfig = context->config; @@ -174,15 +204,12 @@ static YGNodeRef YGJNIOnNodeClonedFunc( YGNodeJobject(owner)->lockLocal(), childIndex); - static auto replaceChild = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod, - jint)>("replaceChild"); + static auto replaceChild = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod, jint)>("replaceChild"); - jlong newNodeNativePointer = replaceChild( - YGNodeJobject(owner)->lockLocal(), - newNode, - childIndex); + jlong newNodeNativePointer = + replaceChild(YGNodeJobject(owner)->lockLocal(), newNode, childIndex); return _jlong2YGNodeRef(newNodeNativePointer); } @@ -194,24 +221,30 @@ static YGSize YGJNIMeasureFunc( float height, YGMeasureMode heightMode) { if (auto obj = YGNodeJobject(node)->lockLocal()) { - static auto measureFunc = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod("measure"); + static auto measureFunc = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod("measure"); YGTransferLayoutDirection(node, obj); - const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); + const auto measureResult = + measureFunc(obj, width, widthMode, height, heightMode); - static_assert(sizeof(measureResult) == 8, - "Expected measureResult to be 8 bytes, or two 32 bit ints"); + static_assert( + sizeof(measureResult) == 8, + "Expected measureResult to be 8 bytes, or two 32 bit ints"); int32_t wBits = 0xFFFFFFFF & (measureResult >> 32); int32_t hBits = 0xFFFFFFFF & measureResult; - const float *measuredWidth = reinterpret_cast(&wBits); - const float *measuredHeight = reinterpret_cast(&hBits); + const float* measuredWidth = reinterpret_cast(&wBits); + const float* measuredHeight = reinterpret_cast(&hBits); return YGSize{*measuredWidth, *measuredHeight}; } else { - YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + node, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); return YGSize{ widthMode == YGMeasureModeUndefined ? 0 : width, heightMode == YGMeasureModeUndefined ? 0 : height, @@ -223,24 +256,28 @@ struct JYogaLogLevel : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaLogLevel;"; }; -static int YGJNILogFunc(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGJNILogFunc( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { int result = vsnprintf(NULL, 0, format, args); std::vector buffer(1 + result); vsnprintf(buffer.data(), buffer.size(), format, args); static auto logFunc = findClassStatic("com/facebook/yoga/YogaLogger") - ->getMethod, local_ref, jstring)>("log"); + ->getMethod, local_ref, jstring)>("log"); static auto logLevelFromInt = - JYogaLogLevel::javaClassStatic()->getStaticMethod("fromInt"); + JYogaLogLevel::javaClassStatic() + ->getStaticMethod("fromInt"); if (auto obj = YGNodeJobject(node)->lockLocal()) { - auto jlogger = reinterpret_cast *>(YGConfigGetContext(config)); + auto jlogger = + reinterpret_cast*>(YGConfigGetContext(config)); logFunc( jlogger->get(), obj, @@ -309,13 +346,19 @@ void jni_YGNodeReset(alias_ref thiz, jlong nativePointer) { void jni_YGNodePrint(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - YGNodePrint(node, - (YGPrintOptions)(YGPrintOptionsStyle | YGPrintOptionsLayout | - YGPrintOptionsChildren)); + YGNodePrint( + node, + (YGPrintOptions)( + YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren)); } -void jni_YGNodeInsertChild(alias_ref, jlong nativePointer, jlong childPointer, jint index) { - YGNodeInsertChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); +void jni_YGNodeInsertChild( + alias_ref, + jlong nativePointer, + jlong childPointer, + jint index) { + YGNodeInsertChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } void jni_YGNodeInsertSharedChild( @@ -327,19 +370,25 @@ void jni_YGNodeInsertSharedChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } -void jni_YGNodeRemoveChild(alias_ref, jlong nativePointer, jlong childPointer) { - YGNodeRemoveChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); +void jni_YGNodeRemoveChild( + alias_ref, + jlong nativePointer, + jlong childPointer) { + YGNodeRemoveChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } -void jni_YGNodeCalculateLayout(alias_ref, - jlong nativePointer, - jfloat width, - jfloat height) { +void jni_YGNodeCalculateLayout( + alias_ref, + jlong nativePointer, + jfloat width, + jfloat height) { const YGNodeRef root = _jlong2YGNodeRef(nativePointer); - YGNodeCalculateLayout(root, - static_cast(width), - static_cast(height), - YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); + YGNodeCalculateLayout( + root, + static_cast(width), + static_cast(height), + YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); YGTransferLayoutOutputsRecursive(root); } @@ -357,20 +406,28 @@ jboolean jni_YGNodeIsDirty(alias_ref, jlong nativePointer) { return (jboolean)_jlong2YGNodeRef(nativePointer)->isDirty(); } -void jni_YGNodeSetHasMeasureFunc(alias_ref, jlong nativePointer, jboolean hasMeasureFunc) { +void jni_YGNodeSetHasMeasureFunc( + alias_ref, + jlong nativePointer, + jboolean hasMeasureFunc) { _jlong2YGNodeRef(nativePointer) ->setMeasureFunc(hasMeasureFunc ? YGJNIMeasureFunc : nullptr); } -void jni_YGNodeSetHasBaselineFunc(alias_ref, - jlong nativePointer, - jboolean hasBaselineFunc) { +void jni_YGNodeSetHasBaselineFunc( + alias_ref, + jlong nativePointer, + jboolean hasBaselineFunc) { _jlong2YGNodeRef(nativePointer) ->setBaseLineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr); } -void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNativePointer) { - YGNodeCopyStyle(_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); +void jni_YGNodeCopyStyle( + alias_ref, + jlong dstNativePointer, + jlong srcNativePointer) { + YGNodeCopyStyle( + _jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); } struct JYogaValue : public JavaClass { @@ -392,67 +449,76 @@ struct JYogaValue : public JavaClass { _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - local_ref jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ - return JYogaValue::create(YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ - } \ - \ - void jni_YGNodeStyleSet##name##Percent(alias_ref, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ +#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer) { \ + return JYogaValue::create( \ + YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent( \ + alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ - YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer) { \ - YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ +#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto( \ + alias_ref, jlong nativePointer) { \ + YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ } -#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ - javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer, jint edge) { \ - return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge)); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, \ - jlong nativePointer, \ - jint edge, \ - javatype value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ + javatype jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer, jint edge) { \ + return (javatype)YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jint edge, javatype value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - local_ref jni_YGNodeStyleGet##name(alias_ref, \ - jlong nativePointer, \ - jint edge) { \ - return JYogaValue::create( \ - YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), static_cast(edge))); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jint edge, jfloat value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ - } \ - \ - void jni_YGNodeStyleSet##name##Percent(alias_ref, \ - jlong nativePointer, \ - jint edge, \ - jfloat value) { \ - YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer, jint edge) { \ + return JYogaValue::create(YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge))); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent( \ + alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ - YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer, jint edge) { \ - YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer), static_cast(edge)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto( \ + alias_ref, jlong nativePointer, jint edge) { \ + YGNodeStyleSet##name##Auto( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ } YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); @@ -466,8 +532,12 @@ YG_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap); YG_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow); YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display); -void jni_YGNodeStyleSetFlex(alias_ref, jlong nativePointer, jfloat value) { - YGNodeStyleSetFlex(_jlong2YGNodeRef(nativePointer), static_cast(value)); +void jni_YGNodeStyleSetFlex( + alias_ref, + jlong nativePointer, + jfloat value) { + YGNodeStyleSetFlex( + _jlong2YGNodeRef(nativePointer), static_cast(value)); } YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); @@ -501,14 +571,14 @@ void jni_YGConfigFree(alias_ref, jlong nativePointer) { YGConfigFree(config); } -void jni_YGConfigSetExperimentalFeatureEnabled(alias_ref, - jlong nativePointer, - jint feature, - jboolean enabled) { +void jni_YGConfigSetExperimentalFeatureEnabled( + alias_ref, + jlong nativePointer, + jint feature, + jboolean enabled) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); - YGConfigSetExperimentalFeatureEnabled(config, - static_cast(feature), - enabled); + YGConfigSetExperimentalFeatureEnabled( + config, static_cast(feature), enabled); } void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( @@ -519,23 +589,26 @@ void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(config, enabled); } -void jni_YGConfigSetUseWebDefaults(alias_ref, - jlong nativePointer, - jboolean useWebDefaults) { +void jni_YGConfigSetUseWebDefaults( + alias_ref, + jlong nativePointer, + jboolean useWebDefaults) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseWebDefaults(config, useWebDefaults); } -void jni_YGConfigSetPointScaleFactor(alias_ref, - jlong nativePointer, - jfloat pixelsInPoint) { +void jni_YGConfigSetPointScaleFactor( + alias_ref, + jlong nativePointer, + jfloat pixelsInPoint) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetPointScaleFactor(config, pixelsInPoint); } -void jni_YGConfigSetUseLegacyStretchBehaviour(alias_ref, - jlong nativePointer, - jboolean useLegacyStretchBehaviour) { +void jni_YGConfigSetUseLegacyStretchBehaviour( + alias_ref, + jlong nativePointer, + jboolean useLegacyStretchBehaviour) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour); } @@ -592,7 +665,7 @@ jint jni_YGNodeGetInstanceCount(alias_ref clazz) { #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) -jint JNI_OnLoad(JavaVM *vm, void *) { +jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( "com/facebook/yoga/YogaNode", From 966f5ece4ad8610ebc6dee45efeaf6380b6e623c Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 04:09:40 -0700 Subject: [PATCH 010/189] guards instead of nested if Summary: Replaces two nested if-blocks with guards. This is intended to help with restructuring this function in follow-ups. @public Reviewed By: priteshrnandgaonkar Differential Revision: D8785659 fbshipit-source-id: 7b9d63e9814b83b999397c016ad67ad348bb0f72 --- java/jni/YGJNI.cpp | 180 ++++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 91 deletions(-) diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 1d6f464c..0b552055 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -47,109 +47,107 @@ static void YGTransferLayoutDirection( } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { - if (root->getHasNewLayout()) { - if (auto obj = YGNodeJobject(root)->lockLocal()) { - static auto widthField = obj->getClass()->getField("mWidth"); - static auto heightField = obj->getClass()->getField("mHeight"); - static auto leftField = obj->getClass()->getField("mLeft"); - static auto topField = obj->getClass()->getField("mTop"); + if (!root->getHasNewLayout()) { + return; + } + auto obj = YGNodeJobject(root)->lockLocal(); + if (!obj) { + YGLog( + root, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); + return; + } - static auto marginLeftField = - obj->getClass()->getField("mMarginLeft"); - static auto marginTopField = - obj->getClass()->getField("mMarginTop"); - static auto marginRightField = - obj->getClass()->getField("mMarginRight"); - static auto marginBottomField = - obj->getClass()->getField("mMarginBottom"); + static auto widthField = obj->getClass()->getField("mWidth"); + static auto heightField = obj->getClass()->getField("mHeight"); + static auto leftField = obj->getClass()->getField("mLeft"); + static auto topField = obj->getClass()->getField("mTop"); - static auto paddingLeftField = - obj->getClass()->getField("mPaddingLeft"); - static auto paddingTopField = - obj->getClass()->getField("mPaddingTop"); - static auto paddingRightField = - obj->getClass()->getField("mPaddingRight"); - static auto paddingBottomField = - obj->getClass()->getField("mPaddingBottom"); + static auto marginLeftField = + obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = obj->getClass()->getField("mMarginTop"); + static auto marginRightField = + obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = + obj->getClass()->getField("mMarginBottom"); - static auto borderLeftField = - obj->getClass()->getField("mBorderLeft"); - static auto borderTopField = - obj->getClass()->getField("mBorderTop"); - static auto borderRightField = - obj->getClass()->getField("mBorderRight"); - static auto borderBottomField = - obj->getClass()->getField("mBorderBottom"); + static auto paddingLeftField = + obj->getClass()->getField("mPaddingLeft"); + static auto paddingTopField = + obj->getClass()->getField("mPaddingTop"); + static auto paddingRightField = + obj->getClass()->getField("mPaddingRight"); + static auto paddingBottomField = + obj->getClass()->getField("mPaddingBottom"); - static auto edgeSetFlagField = - obj->getClass()->getField("mEdgeSetFlag"); - static auto hasNewLayoutField = - obj->getClass()->getField("mHasNewLayout"); - static auto doesLegacyStretchBehaviour = - obj->getClass()->getField( - "mDoesLegacyStretchFlagAffectsLayout"); + static auto borderLeftField = + obj->getClass()->getField("mBorderLeft"); + static auto borderTopField = obj->getClass()->getField("mBorderTop"); + static auto borderRightField = + obj->getClass()->getField("mBorderRight"); + static auto borderBottomField = + obj->getClass()->getField("mBorderBottom"); - /* Those flags needs be in sync with YogaNode.java */ - const int MARGIN = 1; - const int PADDING = 2; - const int BORDER = 4; + static auto edgeSetFlagField = + obj->getClass()->getField("mEdgeSetFlag"); + static auto hasNewLayoutField = + obj->getClass()->getField("mHasNewLayout"); + static auto doesLegacyStretchBehaviour = obj->getClass()->getField( + "mDoesLegacyStretchFlagAffectsLayout"); - int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); + /* Those flags needs be in sync with YogaNode.java */ + const int MARGIN = 1; + const int PADDING = 2; + const int BORDER = 4; - obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); - obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); - obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); - obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); - obj->setFieldValue( - doesLegacyStretchBehaviour, - YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); + int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); - if ((hasEdgeSetFlag & MARGIN) == 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)); - } + obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); + obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); + obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); + obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); + obj->setFieldValue( + doesLegacyStretchBehaviour, + YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); - if ((hasEdgeSetFlag & PADDING) == 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 ((hasEdgeSetFlag & MARGIN) == 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 ((hasEdgeSetFlag & BORDER) == 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)); - } + if ((hasEdgeSetFlag & PADDING) == 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)); + } - obj->setFieldValue(hasNewLayoutField, true); - YGTransferLayoutDirection(root, obj); - root->setHasNewLayout(false); + if ((hasEdgeSetFlag & BORDER) == 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)); + } - for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { - YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); - } - } else { - YGLog( - root, - YGLogLevelError, - "Java YGNode was GCed during layout calculation\n"); - } + obj->setFieldValue(hasNewLayoutField, true); + YGTransferLayoutDirection(root, obj); + root->setHasNewLayout(false); + + for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { + YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } From 6548dddec368c235824fe2f5e1e6fe753d3fd43a Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Wed, 11 Jul 2018 05:55:02 -0700 Subject: [PATCH 011/189] Fix SingleFlex Child condition Summary: Fixes the improper `singleFlexChild` optimization. In the case when all the childs have `flex-grow:0 flex-grow:0` except one child with `flex-grow:1 flex-shrink:1`, then one can simply measure all the non-flexing children and then give the flexing child all the remaining space. Also added a test case which reproduced the bug Reviewed By: IanChilds Differential Revision: D8782684 fbshipit-source-id: ffd4d35b6122f82111b987540efb23bd2a8da5a2 --- tests/YGFlexTest.cpp | 94 ++++++++++++++++++++++++++++++++++++++--- tests/YGMeasureTest.cpp | 10 ++--- yoga/Yoga.cpp | 15 ++++--- 3 files changed, 102 insertions(+), 17 deletions(-) diff --git a/tests/YGFlexTest.cpp b/tests/YGFlexTest.cpp index e1a8ba89..388bcaca 100644 --- a/tests/YGFlexTest.cpp +++ b/tests/YGFlexTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html #include @@ -64,6 +64,90 @@ TEST(YogaTest, flex_basis_flex_grow_column) { YGConfigFree(config); } +TEST(YogaTest, flex_shrink_flex_grow_row) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 500); + YGNodeStyleSetHeight(root, 500); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 0); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeStyleSetWidth(root_child0, 500); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 0); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, flex_shrink_flex_grow_child_flex_shrink_other_child) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 500); + YGNodeStyleSetHeight(root, 500); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 0); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeStyleSetWidth(root_child0, 500); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, flex_basis_flex_grow_row) { const YGConfigRef config = YGConfigNew(); diff --git a/tests/YGMeasureTest.cpp b/tests/YGMeasureTest.cpp index aea2cd59..0e599cdc 100644 --- a/tests/YGMeasureTest.cpp +++ b/tests/YGMeasureTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include #include #include diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index e5d1aabb..3684aae4 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1788,16 +1788,17 @@ static void YGNodeComputeFlexBasisForChildren( // child to exactly match the remaining space if (measureModeMainDim == YGMeasureModeExactly) { for (auto child : children) { - if (singleFlexChild != nullptr) { - if (child->isNodeFlexible()) { - // There is already a flexible child, abort + if (child->isNodeFlexible()) { + if (singleFlexChild != nullptr || + YGFloatsEqual(child->resolveFlexGrow(), 0.0f) || + YGFloatsEqual(child->resolveFlexShrink(), 0.0f)) { + // There is already a flexible child, or this flexible child doesn't + // have flexGrow and flexShrink, abort singleFlexChild = nullptr; break; + } else { + singleFlexChild = child; } - } else if ( - child->resolveFlexGrow() > 0.0f && - child->resolveFlexShrink() > 0.0f) { - singleFlexChild = child; } } } From 765bb85d1e33e7ba35159fb38bd89fe0b343d71d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 11 Jul 2018 08:51:30 -0700 Subject: [PATCH 012/189] Fix warnings when building benchmark Summary: There were a few missing prototypes and a -Wshadow violation. Merged YGBenchmark.h into YGBenchmark.c, added static where needed, fixed shadow violation. Reviewed By: davidaurelio Differential Revision: D8793124 fbshipit-source-id: c4b2dd348c38aa599169b5e9bea543c172439432 --- benchmark/YGBenchmark.c | 66 ++++++++++++++++++++++++++++++++++++-- benchmark/YGBenchmark.h | 71 ----------------------------------------- 2 files changed, 64 insertions(+), 73 deletions(-) delete mode 100644 benchmark/YGBenchmark.h diff --git a/benchmark/YGBenchmark.c b/benchmark/YGBenchmark.c index 1c5521ae..c06ca276 100644 --- a/benchmark/YGBenchmark.c +++ b/benchmark/YGBenchmark.c @@ -5,10 +5,72 @@ * LICENSE file in the root directory of this source tree. */ -#include "YGBenchmark.h" +#include +#include +#include +#include +#include #include +#define NUM_REPETITIONS 1000 + +#define YGBENCHMARKS(BLOCK) \ + int main(int argc, char const *argv[]) { \ + clock_t __start; \ + clock_t __endTimes[NUM_REPETITIONS]; \ + { BLOCK } \ + return 0; \ + } + +#define YGBENCHMARK(NAME, BLOCK) \ + __start = clock(); \ + for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \ + { BLOCK } \ + __endTimes[__i] = clock(); \ + } \ + __printBenchmarkResult(NAME, __start, __endTimes); + +static int __compareDoubles(const void *a, const void *b) { + double arg1 = *(const double *) a; + double arg2 = *(const double *) b; + + if (arg1 < arg2) { + return -1; + } + + if (arg1 > arg2) { + return 1; + } + + return 0; +} + +static void __printBenchmarkResult(char *name, clock_t start, clock_t *endTimes) { + double timesInMs[NUM_REPETITIONS]; + double mean = 0; + clock_t lastEnd = start; + for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { + timesInMs[i] = (endTimes[i] - lastEnd) / (double) CLOCKS_PER_SEC * 1000; + lastEnd = endTimes[i]; + mean += timesInMs[i]; + } + mean /= NUM_REPETITIONS; + + qsort(timesInMs, NUM_REPETITIONS, sizeof(double), __compareDoubles); + double median = timesInMs[NUM_REPETITIONS / 2]; + + double variance = 0; + for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { + variance += pow(timesInMs[i] - mean, 2); + } + variance /= NUM_REPETITIONS; + double stddev = sqrt(variance); + + printf("%s: median: %lf ms, stddev: %lf ms\n", name, median, stddev); +} + + static YGSize _measure(YGNodeRef node, float width, YGMeasureMode widthMode, @@ -97,7 +159,7 @@ YGBENCHMARKS({ YGNodeStyleSetHeight(grandGrandChild, 10); YGNodeInsertChild(grandChild, grandGrandChild, 0); - for (uint32_t iii = 0; iii < 10; iii++) { + for (uint32_t iiii = 0; iiii < 10; iiii++) { const YGNodeRef grandGrandGrandChild = YGNodeNew(); YGNodeStyleSetFlexDirection(grandGrandGrandChild, YGFlexDirectionRow); YGNodeStyleSetFlexGrow(grandGrandGrandChild, 1); diff --git a/benchmark/YGBenchmark.h b/benchmark/YGBenchmark.h deleted file mode 100644 index 54a625b7..00000000 --- a/benchmark/YGBenchmark.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#define NUM_REPETITIONS 1000 - -#define YGBENCHMARKS(BLOCK) \ - int main(int argc, char const *argv[]) { \ - clock_t __start; \ - clock_t __endTimes[NUM_REPETITIONS]; \ - { BLOCK } \ - return 0; \ - } - -#define YGBENCHMARK(NAME, BLOCK) \ - __start = clock(); \ - for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \ - { BLOCK } \ - __endTimes[__i] = clock(); \ - } \ - __printBenchmarkResult(NAME, __start, __endTimes); - -int __compareDoubles(const void *a, const void *b) { - double arg1 = *(const double *) a; - double arg2 = *(const double *) b; - - if (arg1 < arg2) { - return -1; - } - - if (arg1 > arg2) { - return 1; - } - - return 0; -} - -void __printBenchmarkResult(char *name, clock_t start, clock_t *endTimes) { - double timesInMs[NUM_REPETITIONS]; - double mean = 0; - clock_t lastEnd = start; - for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { - timesInMs[i] = (endTimes[i] - lastEnd) / (double) CLOCKS_PER_SEC * 1000; - lastEnd = endTimes[i]; - mean += timesInMs[i]; - } - mean /= NUM_REPETITIONS; - - qsort(timesInMs, NUM_REPETITIONS, sizeof(double), __compareDoubles); - double median = timesInMs[NUM_REPETITIONS / 2]; - - double variance = 0; - for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { - variance += pow(timesInMs[i] - mean, 2); - } - variance /= NUM_REPETITIONS; - double stddev = sqrt(variance); - - printf("%s: median: %lf ms, stddev: %lf ms\n", name, median, stddev); -} From 9ceed4b6014ebdbdb88d3f2d3fc6f3f7112e2706 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 11 Jul 2018 08:51:31 -0700 Subject: [PATCH 013/189] Remove unused YGNode::*nextChild Summary: This linked list was never used, and YGNodeDeepClone was doing scary things to maintain it. Reviewed By: davidaurelio Differential Revision: D8792864 fbshipit-source-id: c578fabe65c837f0791aa9ac3e18f31d93691abd --- yoga/YGNode.cpp | 13 ------------- yoga/YGNode.h | 4 ---- yoga/Yoga.cpp | 4 ---- 3 files changed, 21 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 16f9e4d0..67d991a4 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -69,10 +69,6 @@ YGNodeRef YGNode::getChild(uint32_t index) const { return children_.at(index); } -YGNodeRef YGNode::getNextChild() const { - return nextChild_; -} - YGConfigRef YGNode::getConfig() const { return config_; } @@ -249,10 +245,6 @@ void YGNode::setChildren(const YGVector& children) { children_ = children; } -void YGNode::setNextChild(YGNodeRef nextChild) { - nextChild_ = nextChild; -} - void YGNode::replaceChild(YGNodeRef child, uint32_t index) { children_[index] = child; } @@ -405,7 +397,6 @@ YGNode::YGNode() lineIndex_(0), owner_(nullptr), children_(YGVector()), - nextChild_(nullptr), config_(nullptr), isDirty_(false), resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {} @@ -423,7 +414,6 @@ YGNode::YGNode(const YGNode& node) lineIndex_(node.lineIndex_), owner_(node.owner_), children_(node.children_), - nextChild_(node.nextChild_), config_(node.config_), isDirty_(node.isDirty_), resolvedDimensions_(node.resolvedDimensions_) {} @@ -445,7 +435,6 @@ YGNode::YGNode( uint32_t lineIndex, YGNodeRef owner, const YGVector& children, - YGNodeRef nextChild, YGConfigRef config, bool isDirty, std::array resolvedDimensions) @@ -461,7 +450,6 @@ YGNode::YGNode( lineIndex_(lineIndex), owner_(owner), children_(children), - nextChild_(nextChild), config_(config), isDirty_(isDirty), resolvedDimensions_(resolvedDimensions) {} @@ -487,7 +475,6 @@ YGNode& YGNode::operator=(const YGNode& node) { lineIndex_ = node.getLineIndex(); owner_ = node.getOwner(); children_ = node.getChildren(); - nextChild_ = node.getNextChild(); config_ = node.getConfig(); isDirty_ = node.isDirty(); resolvedDimensions_ = node.getResolvedDimensions(); diff --git a/yoga/YGNode.h b/yoga/YGNode.h index e3562bb6..e4d50dcf 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -26,7 +26,6 @@ struct YGNode { uint32_t lineIndex_; YGNodeRef owner_; YGVector children_; - YGNodeRef nextChild_; YGConfigRef config_; bool isDirty_; std::array resolvedDimensions_; @@ -54,7 +53,6 @@ struct YGNode { uint32_t lineIndex, YGNodeRef owner, const YGVector& children, - YGNodeRef nextChild, YGConfigRef config, bool isDirty, std::array resolvedDimensions); @@ -83,7 +81,6 @@ struct YGNode { YGVector getChildren() const; uint32_t getChildrenCount() const; YGNodeRef getChild(uint32_t index) const; - YGNodeRef getNextChild() const; YGConfigRef getConfig() const; bool isDirty() const; std::array getResolvedDimensions() const; @@ -136,7 +133,6 @@ struct YGNode { void setLineIndex(uint32_t lineIndex); void setOwner(YGNodeRef owner); void setChildren(const YGVector& children); - void setNextChild(YGNodeRef nextChild); void setConfig(YGConfigRef config); void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 3684aae4..5b5a9088 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -275,10 +275,6 @@ static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) { node->setConfig(YGConfigClone(*(oldNode->getConfig()))); } - if (oldNode->getNextChild() != nullptr) { - node->setNextChild(YGNodeDeepClone(oldNode->getNextChild())); - } - return node; } From e384002878858dfaa4ed13463f498f7aeeccf9c1 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 11 Jul 2018 08:51:33 -0700 Subject: [PATCH 014/189] Inline simple YGNode getters/setters Summary: Simple getters/setters are usually inlined like this. Reviewed By: priteshrnandgaonkar, davidaurelio Differential Revision: D8793588 fbshipit-source-id: 436bd54880e41a5e403e3f4ae0d9dd4a413df79c --- yoga/YGNode.cpp | 130 ----------------------------------- yoga/YGNode.h | 175 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 142 insertions(+), 163 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 67d991a4..13571a9d 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -9,82 +9,6 @@ #include #include "Utils.h" -void* YGNode::getContext() const { - return context_; -} - -YGPrintFunc YGNode::getPrintFunc() const { - return print_; -} - -bool YGNode::getHasNewLayout() const { - return hasNewLayout_; -} - -YGNodeType YGNode::getNodeType() const { - return nodeType_; -} - -YGMeasureFunc YGNode::getMeasure() const { - return measure_; -} - -YGBaselineFunc YGNode::getBaseline() const { - return baseline_; -} - -YGDirtiedFunc YGNode::getDirtied() const { - return dirtied_; -} - -YGStyle& YGNode::getStyle() { - return style_; -} - -YGLayout& YGNode::getLayout() { - return layout_; -} - -uint32_t YGNode::getLineIndex() const { - return lineIndex_; -} - -YGNodeRef YGNode::getOwner() const { - return owner_; -} - -YGNodeRef YGNode::getParent() const { - return getOwner(); -} - -YGVector YGNode::getChildren() const { - return children_; -} - -uint32_t YGNode::getChildrenCount() const { - return static_cast(children_.size()); -} - -YGNodeRef YGNode::getChild(uint32_t index) const { - return children_.at(index); -} - -YGConfigRef YGNode::getConfig() const { - return config_; -} - -bool YGNode::isDirty() const { - return isDirty_; -} - -YGValue YGNode::getResolvedDimension(int index) { - return resolvedDimensions_[index]; -} - -std::array YGNode::getResolvedDimensions() const { - return resolvedDimensions_; -} - YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection& axis, const float& axisSize) const { @@ -173,29 +97,7 @@ YGFloatOptional YGNode::getMarginForAxis( // Setters -void YGNode::setContext(void* context) { - context_ = context; -} -void YGNode::setPrintFunc(YGPrintFunc printFunc) { - print_ = printFunc; -} - -void YGNode::setHasNewLayout(bool hasNewLayout) { - hasNewLayout_ = hasNewLayout; -} - -void YGNode::setNodeType(YGNodeType nodeType) { - nodeType_ = nodeType; -} - -void YGNode::setStyleFlexDirection(YGFlexDirection direction) { - style_.flexDirection = direction; -} - -void YGNode::setStyleAlignContent(YGAlign alignContent) { - style_.alignContent = alignContent; -} void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { if (measureFunc == nullptr) { @@ -217,34 +119,6 @@ void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { measure_ = measureFunc; } -void YGNode::setBaseLineFunc(YGBaselineFunc baseLineFunc) { - baseline_ = baseLineFunc; -} - -void YGNode::setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { - dirtied_ = dirtiedFunc; -} - -void YGNode::setStyle(const YGStyle& style) { - style_ = style; -} - -void YGNode::setLayout(const YGLayout& layout) { - layout_ = layout; -} - -void YGNode::setLineIndex(uint32_t lineIndex) { - lineIndex_ = lineIndex; -} - -void YGNode::setOwner(YGNodeRef owner) { - owner_ = owner; -} - -void YGNode::setChildren(const YGVector& children) { - children_ = children; -} - void YGNode::replaceChild(YGNodeRef child, uint32_t index) { children_[index] = child; } @@ -257,10 +131,6 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) { children_.insert(children_.begin() + index, child); } -void YGNode::setConfig(YGConfigRef config) { - config_ = config; -} - void YGNode::setDirty(bool isDirty) { if (isDirty == isDirty_) { return; diff --git a/yoga/YGNode.h b/yoga/YGNode.h index e4d50dcf..ab302e06 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -58,33 +58,97 @@ struct YGNode { std::array resolvedDimensions); // Getters - void* getContext() const; - YGPrintFunc getPrintFunc() const; - bool getHasNewLayout() const; - YGNodeType getNodeType() const; - YGMeasureFunc getMeasure() const; - YGBaselineFunc getBaseline() const; - YGDirtiedFunc getDirtied() const; + void* getContext() const { + return context_; + } + + YGPrintFunc getPrintFunc() const { + return print_; + } + + bool getHasNewLayout() const { + return hasNewLayout_; + } + + YGNodeType getNodeType() const { + return nodeType_; + } + + YGMeasureFunc getMeasure() const { + return measure_; + } + + YGBaselineFunc getBaseline() const { + return baseline_; + } + + YGDirtiedFunc getDirtied() const { + return dirtied_; + } + // For Performance reasons passing as reference. - YGStyle& getStyle(); + YGStyle& getStyle() { + return style_; + } + + const YGStyle& getStyle() const { + return style_; + } + // For Performance reasons passing as reference. - YGLayout& getLayout(); - uint32_t getLineIndex() const; + YGLayout& getLayout() { + return layout_; + } + + const YGLayout& getLayout() const { + return layout_; + } + + uint32_t getLineIndex() const { + return lineIndex_; + } + // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. // This method will return the parent of the YGNode when a YGNode only belongs // to one YogaTree or nullptr when the YGNode is shared between two or more // YogaTrees. - YGNodeRef getOwner() const; + YGNodeRef getOwner() const { + return owner_; + } + // Deprecated, use getOwner() instead. - YGNodeRef getParent() const; - YGVector getChildren() const; - uint32_t getChildrenCount() const; - YGNodeRef getChild(uint32_t index) const; - YGConfigRef getConfig() const; - bool isDirty() const; - std::array getResolvedDimensions() const; - YGValue getResolvedDimension(int index); + YGNodeRef getParent() const { + return getOwner(); + } + + YGVector getChildren() const { + return children_; + } + + uint32_t getChildrenCount() const { + return static_cast(children_.size()); + } + + YGNodeRef getChild(uint32_t index) const { + return children_.at(index); + } + + YGConfigRef getConfig() const { + return config_; + } + + bool isDirty() const { + return isDirty_; + } + + std::array getResolvedDimensions() const { + return resolvedDimensions_; + } + + YGValue getResolvedDimension(int index) const { + return resolvedDimensions_[index]; + } // Methods related to positions, margin, padding and border YGFloatOptional getLeadingPosition(const YGFlexDirection& axis, @@ -119,21 +183,66 @@ struct YGNode { const float& widthSize) const; // Setters - void setContext(void* context); - void setPrintFunc(YGPrintFunc printFunc); - void setHasNewLayout(bool hasNewLayout); - void setNodeType(YGNodeType nodeTye); + void setContext(void* context) { + context_ = context; + } + + void setPrintFunc(YGPrintFunc printFunc) { + print_ = printFunc; + } + + void setHasNewLayout(bool hasNewLayout) { + hasNewLayout_ = hasNewLayout; + } + + void setNodeType(YGNodeType nodeType) { + nodeType_ = nodeType; + } + + void setStyleFlexDirection(YGFlexDirection direction) { + style_.flexDirection = direction; + } + + void setStyleAlignContent(YGAlign alignContent) { + style_.alignContent = alignContent; + } + void setMeasureFunc(YGMeasureFunc measureFunc); - void setBaseLineFunc(YGBaselineFunc baseLineFunc); - void setDirtiedFunc(YGDirtiedFunc dirtiedFunc); - void setStyle(const YGStyle& style); - void setStyleFlexDirection(YGFlexDirection direction); - void setStyleAlignContent(YGAlign alignContent); - void setLayout(const YGLayout& layout); - void setLineIndex(uint32_t lineIndex); - void setOwner(YGNodeRef owner); - void setChildren(const YGVector& children); - void setConfig(YGConfigRef config); + + void setBaseLineFunc(YGBaselineFunc baseLineFunc) { + baseline_ = baseLineFunc; + } + + void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { + dirtied_ = dirtiedFunc; + } + + void setStyle(const YGStyle& style) { + style_ = style; + } + + void setLayout(const YGLayout& layout) { + layout_ = layout; + } + + void setLineIndex(uint32_t lineIndex) { + lineIndex_ = lineIndex; + } + + void setOwner(YGNodeRef owner) { + owner_ = owner; + } + + void setChildren(const YGVector& children) { + children_ = children; + } + + // TODO: rvalue override for setChildren + + void setConfig(YGConfigRef config) { + config_ = config; + } + void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis); From b6231ee0edd43145e582b2ed0207b65cc29c3e7f Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 09:33:24 -0700 Subject: [PATCH 015/189] Lint java files Summary: @public Applies lint auto-fixes to java files. Reviewed By: priteshrnandgaonkar Differential Revision: D8803814 fbshipit-source-id: 2e4dc285b233091a9fbadf38fc22dd6e36f11f8e --- java/com/facebook/yoga/YogaAlign.java | 8 ++++---- java/com/facebook/yoga/YogaBaselineFunction.java | 8 ++++---- java/com/facebook/yoga/YogaConfig.java | 8 ++++---- java/com/facebook/yoga/YogaConstants.java | 8 ++++---- java/com/facebook/yoga/YogaDimension.java | 8 ++++---- java/com/facebook/yoga/YogaDirection.java | 8 ++++---- java/com/facebook/yoga/YogaDisplay.java | 8 ++++---- java/com/facebook/yoga/YogaEdge.java | 8 ++++---- java/com/facebook/yoga/YogaExperimentalFeature.java | 8 ++++---- java/com/facebook/yoga/YogaFlexDirection.java | 8 ++++---- java/com/facebook/yoga/YogaJustify.java | 8 ++++---- java/com/facebook/yoga/YogaLogLevel.java | 8 ++++---- java/com/facebook/yoga/YogaLogger.java | 8 ++++---- java/com/facebook/yoga/YogaMeasureFunction.java | 8 ++++---- java/com/facebook/yoga/YogaMeasureMode.java | 8 ++++---- java/com/facebook/yoga/YogaMeasureOutput.java | 8 ++++---- java/com/facebook/yoga/YogaNodeCloneFunction.java | 8 ++++---- java/com/facebook/yoga/YogaNodeType.java | 8 ++++---- java/com/facebook/yoga/YogaOverflow.java | 8 ++++---- java/com/facebook/yoga/YogaPositionType.java | 8 ++++---- java/com/facebook/yoga/YogaPrintOptions.java | 8 ++++---- java/com/facebook/yoga/YogaUnit.java | 8 ++++---- java/com/facebook/yoga/YogaValue.java | 8 ++++---- java/com/facebook/yoga/YogaWrap.java | 8 ++++---- 24 files changed, 96 insertions(+), 96 deletions(-) diff --git a/java/com/facebook/yoga/YogaAlign.java b/java/com/facebook/yoga/YogaAlign.java index bea5aebd..5687ab9d 100644 --- a/java/com/facebook/yoga/YogaAlign.java +++ b/java/com/facebook/yoga/YogaAlign.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaBaselineFunction.java b/java/com/facebook/yoga/YogaBaselineFunction.java index 9ec41e7e..20feae33 100644 --- a/java/com/facebook/yoga/YogaBaselineFunction.java +++ b/java/com/facebook/yoga/YogaBaselineFunction.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index 12aa0d8e..128f5328 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index 4e081ce4..68c5c982 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 YogaConstants { diff --git a/java/com/facebook/yoga/YogaDimension.java b/java/com/facebook/yoga/YogaDimension.java index b0d89226..3a950e01 100644 --- a/java/com/facebook/yoga/YogaDimension.java +++ b/java/com/facebook/yoga/YogaDimension.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaDirection.java b/java/com/facebook/yoga/YogaDirection.java index dd6444e1..ccd46e84 100644 --- a/java/com/facebook/yoga/YogaDirection.java +++ b/java/com/facebook/yoga/YogaDirection.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaDisplay.java b/java/com/facebook/yoga/YogaDisplay.java index e6e52aad..75c2b687 100644 --- a/java/com/facebook/yoga/YogaDisplay.java +++ b/java/com/facebook/yoga/YogaDisplay.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaEdge.java b/java/com/facebook/yoga/YogaEdge.java index 053490da..36a893f6 100644 --- a/java/com/facebook/yoga/YogaEdge.java +++ b/java/com/facebook/yoga/YogaEdge.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaExperimentalFeature.java b/java/com/facebook/yoga/YogaExperimentalFeature.java index a8a4be14..790bd056 100644 --- a/java/com/facebook/yoga/YogaExperimentalFeature.java +++ b/java/com/facebook/yoga/YogaExperimentalFeature.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaFlexDirection.java b/java/com/facebook/yoga/YogaFlexDirection.java index cf192d6c..5c66d92f 100644 --- a/java/com/facebook/yoga/YogaFlexDirection.java +++ b/java/com/facebook/yoga/YogaFlexDirection.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaJustify.java b/java/com/facebook/yoga/YogaJustify.java index 9e15dc4a..13d3a001 100644 --- a/java/com/facebook/yoga/YogaJustify.java +++ b/java/com/facebook/yoga/YogaJustify.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaLogLevel.java b/java/com/facebook/yoga/YogaLogLevel.java index 458e1b95..0cf7f70c 100644 --- a/java/com/facebook/yoga/YogaLogLevel.java +++ b/java/com/facebook/yoga/YogaLogLevel.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaLogger.java b/java/com/facebook/yoga/YogaLogger.java index 66f62c89..6d1a6a1e 100644 --- a/java/com/facebook/yoga/YogaLogger.java +++ b/java/com/facebook/yoga/YogaLogger.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaMeasureFunction.java b/java/com/facebook/yoga/YogaMeasureFunction.java index 2d2b304d..cc54caec 100644 --- a/java/com/facebook/yoga/YogaMeasureFunction.java +++ b/java/com/facebook/yoga/YogaMeasureFunction.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaMeasureMode.java b/java/com/facebook/yoga/YogaMeasureMode.java index 97193776..5cfc24a4 100644 --- a/java/com/facebook/yoga/YogaMeasureMode.java +++ b/java/com/facebook/yoga/YogaMeasureMode.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaMeasureOutput.java b/java/com/facebook/yoga/YogaMeasureOutput.java index 1d2141d1..e68af410 100644 --- a/java/com/facebook/yoga/YogaMeasureOutput.java +++ b/java/com/facebook/yoga/YogaMeasureOutput.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; /** diff --git a/java/com/facebook/yoga/YogaNodeCloneFunction.java b/java/com/facebook/yoga/YogaNodeCloneFunction.java index 0733776a..ccf7f5c5 100644 --- a/java/com/facebook/yoga/YogaNodeCloneFunction.java +++ b/java/com/facebook/yoga/YogaNodeCloneFunction.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaNodeType.java b/java/com/facebook/yoga/YogaNodeType.java index fb767b05..7eb7246c 100644 --- a/java/com/facebook/yoga/YogaNodeType.java +++ b/java/com/facebook/yoga/YogaNodeType.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaOverflow.java b/java/com/facebook/yoga/YogaOverflow.java index 9563d303..85bc8b20 100644 --- a/java/com/facebook/yoga/YogaOverflow.java +++ b/java/com/facebook/yoga/YogaOverflow.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaPositionType.java b/java/com/facebook/yoga/YogaPositionType.java index be42a999..17073f47 100644 --- a/java/com/facebook/yoga/YogaPositionType.java +++ b/java/com/facebook/yoga/YogaPositionType.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaPrintOptions.java b/java/com/facebook/yoga/YogaPrintOptions.java index 5a804adf..3b59960d 100644 --- a/java/com/facebook/yoga/YogaPrintOptions.java +++ b/java/com/facebook/yoga/YogaPrintOptions.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaUnit.java b/java/com/facebook/yoga/YogaUnit.java index 8eb2b316..e4002dd0 100644 --- a/java/com/facebook/yoga/YogaUnit.java +++ b/java/com/facebook/yoga/YogaUnit.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaValue.java b/java/com/facebook/yoga/YogaValue.java index a99d5641..c0bb6e22 100644 --- a/java/com/facebook/yoga/YogaValue.java +++ b/java/com/facebook/yoga/YogaValue.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; diff --git a/java/com/facebook/yoga/YogaWrap.java b/java/com/facebook/yoga/YogaWrap.java index 1eaa9f7a..3c10dd3a 100644 --- a/java/com/facebook/yoga/YogaWrap.java +++ b/java/com/facebook/yoga/YogaWrap.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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; From 89ba4f282dc6ec71ae66038f044b309d5bcde083 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Wed, 11 Jul 2018 20:05:22 -0700 Subject: [PATCH 016/189] Removed misleading comment in YGPersistenceTest Summary: Trivial... but quite confusing. :) Created from Diffusion's 'Open in Editor' feature. Reviewed By: priteshrnandgaonkar Differential Revision: D7151891 fbshipit-source-id: d09a6434d6327736c2d5ce672b3e9c5b5573508a --- tests/YGPersistenceTest.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/YGPersistenceTest.cpp b/tests/YGPersistenceTest.cpp index 9df861a8..d7fb98d4 100644 --- a/tests/YGPersistenceTest.cpp +++ b/tests/YGPersistenceTest.cpp @@ -5,8 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -// @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html - #include #include From a7f430a5ef391f830f7828c01002c0c42a5c9c97 Mon Sep 17 00:00:00 2001 From: Marc Terns Date: Thu, 12 Jul 2018 07:26:17 -0700 Subject: [PATCH 017/189] Feature podspec modules (#793) Summary: This PR adds support for using Yoga Swift dependents when Yoga is pulled as a static library. Currently swift projects trying to pull static libraries are unable to import the module. The reason for that is because the `DEFINES_MODULES` build setting is set to`NO`. If a Swift Framework is trying to `pod spec lint --use-libraries` with `Yoga` as a dependency, the validation will fail. With the `DEFINES_MODULE` enabled, the product will be treated as defining its own module. This enables automatic production of LLVM module map files when appropriate, and allows the product to be imported as a module. A workaround to this issue would be passing the `:modular_headers` flag to the `Podfile`, but that would not fix the `pod spec lint` validation for framework/library dependencies, it would just allow consuming applications to build and run. An example of this issue would be [SonarKit](https://github.com/facebook/Sonar/blob/master/iOS/SonarKit.podspec). `SonarKit` wasn't able to validate its podspec due to `YogaKit` (Swift Framework) depending on `Yoga` and SonarKit validating with the `--use-libraries` flag due to the c++ dependencies. We had to create a new version of [Yoga 1.9 podspec](https://github.com/facebook/Sonar/blob/master/Specs/Yoga/1.9/Yoga.podspec.json) and make sure to set the `DEFINES_MODULE` flag of the pod target. After that, we were able to `pod spec lint` `SonarKit.podspec` successfully. After merging a new `tag` should be created and the new podspec should be pushed to cocoapods master repository. Pull Request resolved: https://github.com/facebook/yoga/pull/793 Reviewed By: passy Differential Revision: D8820126 Pulled By: priteshrnandgaonkar fbshipit-source-id: 98eae3c31ec67a03c0fe97e05ab9e79446fa9f78 --- Yoga.podspec | 7 +++++-- YogaKit.podspec | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Yoga.podspec b/Yoga.podspec index 7d4553e8..a13fb02f 100644 --- a/Yoga.podspec +++ b/Yoga.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'Yoga' - spec.version = '1.8.1' + spec.version = '1.9.0' spec.license = { :type => 'MIT', :file => "LICENSE" } spec.homepage = 'https://yogalayout.com/' spec.documentation_url = 'https://yogalayout.com/docs' @@ -11,11 +11,14 @@ Pod::Spec.new do |spec| spec.authors = 'Facebook' spec.source = { :git => 'https://github.com/facebook/yoga.git', - :tag => '1.8.0', + :tag => spec.version.to_s, } spec.platforms = { :ios => "8.0", :tvos => "10.0" } spec.module_name = 'yoga' spec.requires_arc = false + spec.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES' + } spec.compiler_flags = [ '-fno-omit-frame-pointer', '-fexceptions', diff --git a/YogaKit.podspec b/YogaKit.podspec index e21f6808..59af6974 100644 --- a/YogaKit.podspec +++ b/YogaKit.podspec @@ -1,6 +1,6 @@ podspec = Pod::Spec.new do |spec| spec.name = 'YogaKit' - spec.version = '1.8.1' + spec.version = '1.9.0' spec.license = { :type => 'MIT', :file => "LICENSE" } spec.homepage = 'https://facebook.github.io/yoga/' spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/yogakit/' @@ -11,14 +11,14 @@ podspec = Pod::Spec.new do |spec| spec.authors = 'Facebook' spec.source = { :git => 'https://github.com/facebook/yoga.git', - :tag => '1.7.0', + :tag => spec.version.to_s, } spec.platform = :ios spec.ios.deployment_target = '8.0' spec.ios.frameworks = 'UIKit' - spec.dependency 'Yoga', '~> 1.8.1' + spec.dependency 'Yoga', '~> 1.9' spec.source_files = 'YogaKit/Source/*.{h,m,swift}' spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h' spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h' From 4ed3dd4b822232ded081259d5015d496cd5b2674 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 12 Jul 2018 07:55:17 -0700 Subject: [PATCH 018/189] Add `YogaNodeProperties` interface Summary: `YogaNodeProperties` will serve as abstraction over JNI adapters / storage backends in follow-ups. @public Reviewed By: IanChilds Differential Revision: D8818805 fbshipit-source-id: 7998a56daebea60dd13b07228dffdf14be852554 --- .../com/facebook/yoga/YogaNodeProperties.java | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 java/com/facebook/yoga/YogaNodeProperties.java diff --git a/java/com/facebook/yoga/YogaNodeProperties.java b/java/com/facebook/yoga/YogaNodeProperties.java new file mode 100644 index 00000000..fbad2ea2 --- /dev/null +++ b/java/com/facebook/yoga/YogaNodeProperties.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +public interface YogaNodeProperties { + + YogaNodeProperties clone(YogaNode node); + + long getNativePointer(); + + void onAfterCalculateLayout(); + + void reset(); + + boolean hasNewLayout(); + + boolean isDirty(); + + void markLayoutSeen(); + + YogaDirection getStyleDirection(); + + void setDirection(YogaDirection direction); + + YogaFlexDirection getFlexDirection(); + + void setFlexDirection(YogaFlexDirection flexDirection); + + YogaJustify getJustifyContent(); + + void setJustifyContent(YogaJustify justifyContent); + + YogaAlign getAlignItems(); + + void setAlignItems(YogaAlign alignItems); + + YogaAlign getAlignSelf(); + + void setAlignSelf(YogaAlign alignSelf); + + YogaAlign getAlignContent(); + + void setAlignContent(YogaAlign alignContent); + + YogaPositionType getPositionType(); + + void setPositionType(YogaPositionType positionType); + + void setWrap(YogaWrap flexWrap); + + YogaOverflow getOverflow(); + + void setOverflow(YogaOverflow overflow); + + YogaDisplay getDisplay(); + + void setDisplay(YogaDisplay display); + + void setFlex(float flex); + + float getFlexGrow(); + + void setFlexGrow(float flexGrow); + + float getFlexShrink(); + + void setFlexShrink(float flexShrink); + + YogaValue getFlexBasis(); + + void setFlexBasis(float flexBasis); + + void setFlexBasisPercent(float percent); + + void setFlexBasisAuto(); + + YogaValue getMargin(YogaEdge edge); + + void setMargin(YogaEdge edge, float margin); + + void setMarginPercent(YogaEdge edge, float percent); + + void setMarginAuto(YogaEdge edge); + + YogaValue getPadding(YogaEdge edge); + + void setPadding(YogaEdge edge, float padding); + + void setPaddingPercent(YogaEdge edge, float percent); + + float getBorder(YogaEdge edge); + + void setBorder(YogaEdge edge, float border); + + YogaValue getPosition(YogaEdge edge); + + void setPosition(YogaEdge edge, float position); + + void setPositionPercent(YogaEdge edge, float percent); + + YogaValue getWidth(); + + void setWidth(float width); + + void setWidthPercent(float percent); + + void setWidthAuto(); + + YogaValue getHeight(); + + void setHeight(float height); + + void setHeightPercent(float percent); + + void setHeightAuto(); + + YogaValue getMinWidth(); + + void setMinWidth(float minWidth); + + void setMinWidthPercent(float percent); + + YogaValue getMinHeight(); + + void setMinHeight(float minHeight); + + void setMinHeightPercent(float percent); + + YogaValue getMaxWidth(); + + void setMaxWidth(float maxWidth); + + void setMaxWidthPercent(float percent); + + YogaValue getMaxHeight(); + + void setMaxHeight(float maxheight); + + void setMaxHeightPercent(float percent); + + float getAspectRatio(); + + void setAspectRatio(float aspectRatio); + + float getLayoutX(); + + float getLayoutY(); + + float getLayoutWidth(); + + float getLayoutHeight(); + + boolean getDoesLegacyStretchFlagAffectsLayout(); + + float getLayoutMargin(YogaEdge edge); + + float getLayoutPadding(YogaEdge edge); + + float getLayoutBorder(YogaEdge edge); + + YogaDirection getLayoutDirection(); +} From e9e2ae28e046758d4e457defdba74955a4b38a8c Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Thu, 12 Jul 2018 08:40:52 -0700 Subject: [PATCH 019/189] Tidy up YGFloatOptional Summary: Just some convention/weird style things. `float` should be passed by value, weird use of ?: operator instead of ||. Reviewed By: priteshrnandgaonkar Differential Revision: D8804407 fbshipit-source-id: e0d67363ccde36ec5bccec7497ed0ffd364b3fcf --- yoga/YGFloatOptional.cpp | 33 ++++++++++++--------------------- yoga/YGFloatOptional.h | 25 +++++++++++++++---------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index 00bfc71e..ceee1dc2 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -1,16 +1,16 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGFloatOptional.h" #include #include #include "Yoga.h" -YGFloatOptional::YGFloatOptional(const float& value) { +YGFloatOptional::YGFloatOptional(float value) { if (YGFloatIsUndefined(value)) { isUndefined_ = true; value_ = 0; @@ -31,18 +31,9 @@ const float& YGFloatOptional::getValue() const { return value_; } -void YGFloatOptional::setValue(const float& val) { - value_ = val; - isUndefined_ = false; -} - -const bool& YGFloatOptional::isUndefined() const { - return isUndefined_; -} - bool YGFloatOptional::operator==(const YGFloatOptional& op) const { if (isUndefined_ == op.isUndefined()) { - return isUndefined_ ? true : value_ == op.getValue(); + return isUndefined_ || value_ == op.getValue(); } return false; } @@ -51,14 +42,14 @@ bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { return !(*this == op); } -bool YGFloatOptional::operator==(const float& val) const { +bool YGFloatOptional::operator==(float val) const { if (YGFloatIsUndefined(val) == isUndefined_) { - return isUndefined_ ? true : val == value_; + return isUndefined_ || val == value_; } return false; } -bool YGFloatOptional::operator!=(const float& val) const { +bool YGFloatOptional::operator!=(float val) const { return !(*this == val); } @@ -84,9 +75,9 @@ bool YGFloatOptional::operator<(const YGFloatOptional& op) const { } bool YGFloatOptional::operator>=(const YGFloatOptional& op) const { - return *this == op ? true : *this > op; + return *this == op || *this > op; } bool YGFloatOptional::operator<=(const YGFloatOptional& op) const { - return *this == op ? true : *this < op; + return *this == op || *this < op; } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 21af2a80..d426d849 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #pragma once struct YGFloatOptional { @@ -13,7 +13,7 @@ struct YGFloatOptional { bool isUndefined_; public: - explicit YGFloatOptional(const float& value); + explicit YGFloatOptional(float value); explicit YGFloatOptional(); // Program will terminate if the value of an undefined is accessed. Please @@ -22,9 +22,14 @@ struct YGFloatOptional { const float& getValue() const; // Sets the value of float optional, and thus isUndefined is assigned false. - void setValue(const float& val); + void setValue(float val) { + value_ = val; + isUndefined_ = false; + } - const bool& isUndefined() const; + bool isUndefined() const { + return isUndefined_; + } YGFloatOptional operator+(const YGFloatOptional& op); bool operator>(const YGFloatOptional& op) const; @@ -34,6 +39,6 @@ struct YGFloatOptional { bool operator==(const YGFloatOptional& op) const; bool operator!=(const YGFloatOptional& op) const; - bool operator==(const float& val) const; - bool operator!=(const float& val) const; + bool operator==(float val) const; + bool operator!=(float val) const; }; From 0b1780a081ba4167030eac847c18737bca1cc2c8 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 13 Jul 2018 12:34:46 -0700 Subject: [PATCH 020/189] YGNode::getChildren() should return const ref Summary: It's wasteful to do it by value. I'm fairly sure this is safe, especially because https://github.com/facebook/yoga/commit/fbd332dee86237cae6f9c9bae8ea9a7bbe7c7d87#diff-ade2a4bbd6582e2898cbd9e0fa142ab5R215 shows that we did access by reference before. Reviewed By: priteshrnandgaonkar, davidaurelio Differential Revision: D8822697 fbshipit-source-id: 791bcf0fa37453f67795af727c85c8adce3b0f69 --- yoga/YGNode.h | 6 +----- yoga/Yoga.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/yoga/YGNode.h b/yoga/YGNode.h index ab302e06..c204d460 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -122,14 +122,10 @@ struct YGNode { return getOwner(); } - YGVector getChildren() const { + const YGVector& getChildren() const { return children_; } - uint32_t getChildrenCount() const { - return static_cast(children_.size()); - } - YGNodeRef getChild(uint32_t index) const { return children_.at(index); } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 5b5a9088..df186c7c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -264,7 +264,7 @@ static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) { YGVector vec = YGVector(); vec.reserve(oldNode->getChildren().size()); YGNodeRef childNode = nullptr; - for (auto& item : oldNode->getChildren()) { + for (auto* item : oldNode->getChildren()) { childNode = YGNodeDeepClone(item); childNode->setOwner(node); vec.push_back(childNode); @@ -301,8 +301,8 @@ static void YGConfigFreeRecursive(const YGNodeRef root) { delete root->getConfig(); } // Delete configs recursively for childrens - for (uint32_t i = 0; i < root->getChildrenCount(); ++i) { - YGConfigFreeRecursive(root->getChild(i)); + for (auto* child : root->getChildren()) { + YGConfigFreeRecursive(child); } } @@ -1868,7 +1868,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( // Add items to the current line until it's full or we run out of items. uint32_t endOfLineIndex = startOfLineIndex; - for (; endOfLineIndex < node->getChildrenCount(); endOfLineIndex++) { + for (; endOfLineIndex < node->getChildren().size(); endOfLineIndex++) { const YGNodeRef child = node->getChild(endOfLineIndex); if (child->getStyle().display == YGDisplayNone || child->getStyle().positionType == YGPositionTypeAbsolute) { From 2562c029b1cf95e8119eaf6505bed224d3c1ec6b Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 13 Jul 2018 12:34:49 -0700 Subject: [PATCH 021/189] Tidy up YGFloatOptional further Summary: I missed these two things: inline default ctor, getValue() should return a float. Reviewed By: priteshrnandgaonkar Differential Revision: D8826640 fbshipit-source-id: e6324dea0268ef276e6fa1722e72dffb5241e676 --- yoga/YGFloatOptional.cpp | 4 +--- yoga/YGFloatOptional.h | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index ceee1dc2..d3407fa2 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -20,9 +20,7 @@ YGFloatOptional::YGFloatOptional(float value) { } } -YGFloatOptional::YGFloatOptional() : value_(0), isUndefined_(true) {} - -const float& YGFloatOptional::getValue() const { +float YGFloatOptional::getValue() const { if (isUndefined_) { // Abort, accessing a value of an undefined float optional std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index d426d849..114f3577 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -14,12 +14,12 @@ struct YGFloatOptional { public: explicit YGFloatOptional(float value); - explicit YGFloatOptional(); + explicit YGFloatOptional() : value_(0), isUndefined_(true) {} // Program will terminate if the value of an undefined is accessed. Please // make sure to check if the optional is defined before calling this function. // To check if float optional is defined, use `isUndefined()`. - const float& getValue() const; + float getValue() const; // Sets the value of float optional, and thus isUndefined is assigned false. void setValue(float val) { From 910aa77c0189bce6cc7d45875aeb7c080407171d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 13 Jul 2018 12:34:51 -0700 Subject: [PATCH 022/189] Remove some unnecessary `const float &` uses Summary: Holding floats by reference is unnecessary at best and may be detrimental to performance. Reviewed By: davidaurelio Differential Revision: D8826496 fbshipit-source-id: 2391f8aa26ebfbb440f6e4b7d57975be688f791c --- yoga/Yoga.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index df186c7c..1ea109e2 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1249,9 +1249,9 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, childWidthMeasureMode = YGMeasureModeUndefined; childHeightMeasureMode = YGMeasureModeUndefined; - const float& marginRow = YGUnwrapFloatOptional( + auto marginRow = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float& marginColumn = YGUnwrapFloatOptional( + auto marginColumn = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); if (isRowStyleDimDefined) { @@ -1377,9 +1377,9 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined; YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; - const float& marginRow = + auto marginRow = YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width)); - const float& marginColumn = YGUnwrapFloatOptional( + auto marginColumn = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionColumn, width)); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { @@ -1679,9 +1679,9 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node, heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { - const float& marginAxisColumn = YGUnwrapFloatOptional( + auto marginAxisColumn = YGUnwrapFloatOptional( node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); - const float& marginAxisRow = YGUnwrapFloatOptional( + auto marginAxisRow = YGUnwrapFloatOptional( node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); node->setLayoutMeasuredDimension( From 896cfbdfdedc3a0ed0a95357173704bde8f5a7f2 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sat, 14 Jul 2018 00:14:58 -0700 Subject: [PATCH 023/189] Skylarkify yoga build defs. Summary: Top-level `if` statements are not allowed in a new Buck parser - Skylark. https://buckbuild.com/concept/skylark.html Reviewed By: grzmiel Differential Revision: D8849590 fbshipit-source-id: 6648135f23e058adfeddf574932f8a98c7831fee --- csharp/BUCK | 48 +++++++++--------------------------------------- yoga_defs.bzl | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/csharp/BUCK b/csharp/BUCK index d29f35a3..e679803a 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -3,7 +3,14 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "is_apple_platform", "yoga_cxx_library", "yoga_dep") +load( + "//:yoga_defs.bzl", + "BASE_COMPILER_FLAGS", + "is_apple_platform", + "yoga_cxx_library", + "yoga_dep", + "yoga_apple_binary", +) COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"] @@ -32,41 +39,4 @@ yoga_cxx_library( deps = [yoga_dep(":yoga")], ) -if is_apple_platform(): - yoganet_ios_srcs = [] - for arch in [ - "iphonesimulator-x86_64", - "iphoneos-arm64", - ]: - name = "yoganet-" + arch - yoganet_ios_srcs.append(":" + name) - genrule( - name = name, - srcs = [ - yoga_dep(":yogaApple#%s,static" % arch), - yoga_dep("YogaKit:YogaKitApple#%s,static" % arch), - yoga_dep("csharp:yoganetApple#%s,static" % arch), - ], - out = "libyoga-%s.a" % arch, - cmd = "libtool -static -o $OUT $SRCS", - visibility = [yoga_dep("csharp:yoganet-ios")], - ) - - genrule( - name = "yoganet-ios", - srcs = yoganet_ios_srcs, - out = "libyoga.a", - cmd = "lipo $SRCS -create -output $OUT", - visibility = ["PUBLIC"], - ) - - yoganet_macosx_target = "csharp:yoganetAppleMac#macosx-%s,dynamic" - genrule( - name = "yoganet-macosx", - srcs = [ - yoga_dep(yoganet_macosx_target % "x86_64"), - ], - out = "libyoga.dylib", - cmd = "lipo $SRCS -create -output $OUT", - visibility = ["PUBLIC"], - ) +yoga_apple_binary() diff --git a/yoga_defs.bzl b/yoga_defs.bzl index 9f33a825..1a574c04 100644 --- a/yoga_defs.bzl +++ b/yoga_defs.bzl @@ -190,3 +190,43 @@ def yoga_prebuilt_jar(*args, **kwargs): def is_apple_platform(): return True + +def yoga_apple_binary(): + if is_apple_platform(): + yoganet_ios_srcs = [] + for arch in [ + "iphonesimulator-x86_64", + "iphoneos-arm64", + ]: + name = "yoganet-" + arch + yoganet_ios_srcs.append(":" + name) + native.genrule( + name = name, + srcs = [ + yoga_dep(":yogaApple#%s,static" % arch), + yoga_dep("YogaKit:YogaKitApple#%s,static" % arch), + yoga_dep("csharp:yoganetApple#%s,static" % arch), + ], + out = "libyoga-%s.a" % arch, + cmd = "libtool -static -o $OUT $SRCS", + visibility = [yoga_dep("csharp:yoganet-ios")], + ) + + native.genrule( + name = "yoganet-ios", + srcs = yoganet_ios_srcs, + out = "libyoga.a", + cmd = "lipo $SRCS -create -output $OUT", + visibility = ["PUBLIC"], + ) + + yoganet_macosx_target = "csharp:yoganetAppleMac#macosx-%s,dynamic" + native.genrule( + name = "yoganet-macosx", + srcs = [ + yoga_dep(yoganet_macosx_target % "x86_64"), + ], + out = "libyoga.dylib", + cmd = "lipo $SRCS -create -output $OUT", + visibility = ["PUBLIC"], + ) From 1b32c4f0546cabcc0d71a09bbca44eab8fbfe317 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 18 Jul 2018 00:57:52 -0700 Subject: [PATCH 024/189] Lint Utils.cpp YGLayout.cpp YGNode.cpp Yoga-internal.h Summary: @public Auto-fixes formatting of YGLayout.cpp YGNode.cpp Yoga-internal.h Reviewed By: astreet Differential Revision: D8875514 fbshipit-source-id: 38d709831349c4ad015f20451421aea89fc6f007 --- yoga/Utils.cpp | 10 +++++----- yoga/YGLayout.cpp | 10 +++++----- yoga/YGNode.cpp | 14 ++++++-------- yoga/Yoga-internal.h | 20 ++++++++++---------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 6fa8df82..5f6c960d 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "Utils.h" YGFlexDirection YGFlexDirectionCross( diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index 6e367bd5..604d7109 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGLayout.h" #include "Utils.h" diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 13571a9d..9e7a182b 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGNode.h" #include #include "Utils.h" @@ -97,8 +97,6 @@ YGFloatOptional YGNode::getMarginForAxis( // Setters - - void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { if (measureFunc == nullptr) { measure_ = nullptr; @@ -396,7 +394,7 @@ void YGNode::resolveDimension() { YGDirection YGNode::resolveDirection(const YGDirection ownerDirection) { if (style_.direction == YGDirectionInherit) { return ownerDirection > YGDirectionInherit ? ownerDirection - : YGDirectionLTR; + : YGDirectionLTR; } else { return style_.direction; } diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index be1d9632..84c4596b 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 #include @@ -16,10 +16,11 @@ using YGVector = std::vector; YG_EXTERN_C_BEGIN -WIN_EXPORT float YGRoundValueToPixelGrid(const float value, - const float pointScaleFactor, - const bool forceCeil, - const bool forceFloor); +WIN_EXPORT float YGRoundValueToPixelGrid( + const float value, + const float pointScaleFactor, + const bool forceCeil, + const bool forceFloor); YG_EXTERN_C_END @@ -87,7 +88,6 @@ struct YGCachedMeasurement { // layouts should not require more than 16 entries to fit within the cache. #define YG_MAX_CACHED_RESULT_COUNT 16 - static const float kDefaultFlexGrow = 0.0f; static const float kDefaultFlexShrink = 0.0f; static const float kWebDefaultFlexShrink = 1.0f; From c1a9f6120a92bb6b1f1fa4306e45a3b30e1f2333 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 18 Jul 2018 02:23:58 -0700 Subject: [PATCH 025/189] Make `YGFloatIsUndefined` inlineable Summary: @public Makes `YGFloatIsUndefined` inlineable Reviewed By: swolchok Differential Revision: D8875520 fbshipit-source-id: 7ac653e002512b1a8d5f9c04e0a21381aeb02e67 --- yoga/Utils.cpp | 18 ++++++++++-------- yoga/YGFloatOptional.cpp | 7 +++++-- yoga/YGLayout.cpp | 10 ++++++---- yoga/YGNode.cpp | 6 ++++-- yoga/Yoga-internal.h | 36 ++++++++++++++++++++++++++++-------- yoga/Yoga.cpp | 10 +--------- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 5f6c960d..83995221 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -7,6 +7,8 @@ */ #include "Utils.h" +using namespace facebook; + YGFlexDirection YGFlexDirectionCross( const YGFlexDirection flexDirection, const YGDirection direction) { @@ -16,18 +18,18 @@ YGFlexDirection YGFlexDirectionCross( } float YGFloatMax(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fmaxf(a, b); } - return YGFloatIsUndefined(a) ? b : a; + return yoga::isUndefined(a) ? b : a; } float YGFloatMin(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fminf(a, b); } - return YGFloatIsUndefined(a) ? b : a; + return yoga::isUndefined(a) ? b : a; } bool YGValueEqual(const YGValue a, const YGValue b) { @@ -36,7 +38,7 @@ bool YGValueEqual(const YGValue a, const YGValue b) { } if (a.unit == YGUnitUndefined || - (YGFloatIsUndefined(a.value) && YGFloatIsUndefined(b.value))) { + (yoga::isUndefined(a.value) && yoga::isUndefined(b.value))) { return true; } @@ -44,14 +46,14 @@ bool YGValueEqual(const YGValue a, const YGValue b) { } bool YGFloatsEqual(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fabs(a - b) < 0.0001f; } - return YGFloatIsUndefined(a) && YGFloatIsUndefined(b); + return yoga::isUndefined(a) && yoga::isUndefined(b); } float YGFloatSanitize(const float& val) { - return YGFloatIsUndefined(val) ? 0 : val; + return yoga::isUndefined(val) ? 0 : val; } float YGUnwrapFloatOptional(const YGFloatOptional& op) { diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index d3407fa2..cb867f3a 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -9,9 +9,12 @@ #include #include #include "Yoga.h" +#include "Yoga-internal.h" + +using namespace facebook; YGFloatOptional::YGFloatOptional(float value) { - if (YGFloatIsUndefined(value)) { + if (yoga::isUndefined(value)) { isUndefined_ = true; value_ = 0; } else { @@ -41,7 +44,7 @@ bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { } bool YGFloatOptional::operator==(float val) const { - if (YGFloatIsUndefined(val) == isUndefined_) { + if (yoga::isUndefined(val) == isUndefined_) { return isUndefined_ || val == value_; } return false; diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index 604d7109..dfd7be08 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -8,6 +8,8 @@ #include "YGLayout.h" #include "Utils.h" +using namespace facebook; + const std::array kYGDefaultDimensionValues = { {YGUndefined, YGUndefined}}; @@ -46,13 +48,13 @@ bool YGLayout::operator==(YGLayout layout) const { isEqual = isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i]; } - if (!YGFloatIsUndefined(measuredDimensions[0]) || - !YGFloatIsUndefined(layout.measuredDimensions[0])) { + if (!yoga::isUndefined(measuredDimensions[0]) || + !yoga::isUndefined(layout.measuredDimensions[0])) { isEqual = isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]); } - if (!YGFloatIsUndefined(measuredDimensions[1]) || - !YGFloatIsUndefined(layout.measuredDimensions[1])) { + if (!yoga::isUndefined(measuredDimensions[1]) || + !yoga::isUndefined(layout.measuredDimensions[1])) { isEqual = isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]); } diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 9e7a182b..70dd655d 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -9,6 +9,8 @@ #include #include "Utils.h" +using namespace facebook; + YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection& axis, const float& axisSize) const { @@ -500,7 +502,7 @@ bool YGNode::isNodeFlexible() { float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { if (YGFlexDirectionIsRow(axis) && style_.border[YGEdgeStart].unit != YGUnitUndefined && - !YGFloatIsUndefined(style_.border[YGEdgeStart].value) && + !yoga::isUndefined(style_.border[YGEdgeStart].value) && style_.border[YGEdgeStart].value >= 0.0f) { return style_.border[YGEdgeStart].value; } @@ -513,7 +515,7 @@ float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { if (YGFlexDirectionIsRow(flexDirection) && style_.border[YGEdgeEnd].unit != YGUnitUndefined && - !YGFloatIsUndefined(style_.border[YGEdgeEnd].value) && + !yoga::isUndefined(style_.border[YGEdgeEnd].value) && style_.border[YGEdgeEnd].value >= 0.0f) { return style_.border[YGEdgeEnd].value; } diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 84c4596b..941147e8 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -24,6 +24,26 @@ WIN_EXPORT float YGRoundValueToPixelGrid( YG_EXTERN_C_END +namespace facebook { +namespace yoga { + +inline bool isUndefined(float value) { + // Value of a float in the case of it being not defined is 10.1E20. Earlier + // it used to be NAN, the benefit of which was that if NAN is involved in any + // mathematical expression the result was NAN. But since we want to have + // `-ffast-math` flag being used by compiler which assumes that the floating + // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But + // now if YGUndefined is involved in any mathematical operations this + // value(10.1E20) would change. So the following check makes sure that if the + // value is outside a range (-10E8, 10E8) then it is undefined. + return value >= 10E8 || value <= -10E8; +} + +} // namespace yoga +} // namespace facebook + +using namespace facebook; + extern const std::array trailing; extern const std::array leading; extern bool YGValueEqual(const YGValue a, const YGValue b); @@ -63,20 +83,20 @@ struct YGCachedMeasurement { bool isEqual = widthMeasureMode == measurement.widthMeasureMode && heightMeasureMode == measurement.heightMeasureMode; - if (!YGFloatIsUndefined(availableWidth) || - !YGFloatIsUndefined(measurement.availableWidth)) { + if (!yoga::isUndefined(availableWidth) || + !yoga::isUndefined(measurement.availableWidth)) { isEqual = isEqual && availableWidth == measurement.availableWidth; } - if (!YGFloatIsUndefined(availableHeight) || - !YGFloatIsUndefined(measurement.availableHeight)) { + if (!yoga::isUndefined(availableHeight) || + !yoga::isUndefined(measurement.availableHeight)) { isEqual = isEqual && availableHeight == measurement.availableHeight; } - if (!YGFloatIsUndefined(computedWidth) || - !YGFloatIsUndefined(measurement.computedWidth)) { + if (!yoga::isUndefined(computedWidth) || + !yoga::isUndefined(measurement.computedWidth)) { isEqual = isEqual && computedWidth == measurement.computedWidth; } - if (!YGFloatIsUndefined(computedHeight) || - !YGFloatIsUndefined(measurement.computedHeight)) { + if (!yoga::isUndefined(computedHeight) || + !yoga::isUndefined(measurement.computedHeight)) { isEqual = isEqual && computedHeight == measurement.computedHeight; } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 1ea109e2..fe419207 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -104,15 +104,7 @@ static int YGDefaultLog(const YGConfigRef config, #endif bool YGFloatIsUndefined(const float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier - // it used to be NAN, the benefit of which was that if NAN is involved in any - // mathematical expression the result was NAN. But since we want to have - // `-ffast-math` flag being used by compiler which assumes that the floating - // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But - // now if YGUndefined is involved in any mathematical operations this - // value(10.1E20) would change. So the following check makes sure that if the - // value is outside a range (-10E8, 10E8) then it is undefined. - return value >= 10E8 || value <= -10E8; + return facebook::yoga::isUndefined(value); } const YGValue* YGComputedEdgeValue( From 4c47dcbd0f4446d504d94de3e10aa5e2e6444a8d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 18 Jul 2018 15:45:34 -0700 Subject: [PATCH 026/189] Delete YGNode ctor w/arg per member Summary: It doesn't seem to be used internally, it hurts greppability, and there are setters for these properties as needed anyway. Reviewed By: davidaurelio Differential Revision: D8842084 fbshipit-source-id: f0275b490e585ea94df341c97c34b441ed91c4fb --- yoga/YGNode.cpp | 32 -------------------------------- yoga/YGNode.h | 16 ---------------- 2 files changed, 48 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 70dd655d..dda20a55 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -292,38 +292,6 @@ YGNode::YGNode(const YGConfigRef newConfig) : YGNode() { config_ = newConfig; } -YGNode::YGNode( - void* context, - YGPrintFunc print, - bool hasNewLayout, - YGNodeType nodeType, - YGMeasureFunc measure, - YGBaselineFunc baseline, - YGDirtiedFunc dirtied, - YGStyle style, - const YGLayout& layout, - uint32_t lineIndex, - YGNodeRef owner, - const YGVector& children, - YGConfigRef config, - bool isDirty, - std::array resolvedDimensions) - : context_(context), - print_(print), - hasNewLayout_(hasNewLayout), - nodeType_(nodeType), - measure_(measure), - baseline_(baseline), - dirtied_(dirtied), - style_(style), - layout_(layout), - lineIndex_(lineIndex), - owner_(owner), - children_(children), - config_(config), - isDirty_(isDirty), - resolvedDimensions_(resolvedDimensions) {} - YGNode& YGNode::operator=(const YGNode& node) { if (&node == this) { return *this; diff --git a/yoga/YGNode.h b/yoga/YGNode.h index c204d460..cba72163 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -40,22 +40,6 @@ struct YGNode { explicit YGNode(const YGConfigRef newConfig); YGNode(const YGNode& node); YGNode& operator=(const YGNode& node); - YGNode( - void* context, - YGPrintFunc print, - bool hasNewLayout, - YGNodeType nodeType, - YGMeasureFunc measure, - YGBaselineFunc baseline, - YGDirtiedFunc dirtied, - YGStyle style, - const YGLayout& layout, - uint32_t lineIndex, - YGNodeRef owner, - const YGVector& children, - YGConfigRef config, - bool isDirty, - std::array resolvedDimensions); // Getters void* getContext() const { From 0bc4d23e2e7f942e0699b3bd6ac31660698e0e85 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 18 Jul 2018 15:45:36 -0700 Subject: [PATCH 027/189] Explicitly default YGNode copy ctor Summary: No need to type out the old version. This is exactly equivalent (unless I've misread and the old version did something other than memberwise copy). Reviewed By: davidaurelio Differential Revision: D8842326 fbshipit-source-id: c575ea4cee6caef9ea15aaf5967597385ed26ec3 --- yoga/YGNode.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index dda20a55..fc97e172 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -271,22 +271,7 @@ YGNode::YGNode() isDirty_(false), resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {} -YGNode::YGNode(const YGNode& node) - : context_(node.context_), - print_(node.print_), - hasNewLayout_(node.hasNewLayout_), - nodeType_(node.nodeType_), - measure_(node.measure_), - baseline_(node.baseline_), - dirtied_(node.dirtied_), - style_(node.style_), - layout_(node.layout_), - lineIndex_(node.lineIndex_), - owner_(node.owner_), - children_(node.children_), - config_(node.config_), - isDirty_(node.isDirty_), - resolvedDimensions_(node.resolvedDimensions_) {} +YGNode::YGNode(const YGNode& node) = default; YGNode::YGNode(const YGConfigRef newConfig) : YGNode() { config_ = newConfig; From 51a4601e18b5dabd70245fbb5e08190a40a99dea Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 19 Jul 2018 06:43:06 -0700 Subject: [PATCH 028/189] Update soloader to 0.5.1 Summary: There's been a breaking change in 0.5 and old versions are ABI-incompatible with new ones. Reviewed By: muraziz Differential Revision: D8913456 fbshipit-source-id: 89221c5ac95c7c2197083a5390403c72e7e33af1 --- java/build.gradle | 2 +- lib/fb/build.gradle | 2 +- lib/soloader/BUCK | 2 +- lib/soloader/soloader-0.1.0.aar | Bin 41801 -> 0 bytes lib/soloader/soloader-0.5.1.aar | Bin 0 -> 58583 bytes 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/soloader/soloader-0.1.0.aar create mode 100644 lib/soloader/soloader-0.5.1.aar diff --git a/java/build.gradle b/java/build.gradle index da30fe9b..21034e42 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -52,7 +52,7 @@ android { dependencies { compileOnly 'com.google.code.findbugs:jsr305:3.0.1' compileOnly project(':yoga:proguard-annotations') - implementation 'com.facebook.soloader:soloader:0.2.0' + implementation 'com.facebook.soloader:soloader:0.5.1' testImplementation 'junit:junit:4.12' } diff --git a/lib/fb/build.gradle b/lib/fb/build.gradle index 7a419b0b..fde3f88a 100644 --- a/lib/fb/build.gradle +++ b/lib/fb/build.gradle @@ -26,7 +26,7 @@ android { } dependencies { - implementation 'com.facebook.soloader:soloader:0.2.0' + implementation 'com.facebook.soloader:soloader:0.5.1' compileOnly 'com.google.code.findbugs:jsr305:3.0.1' compileOnly project(':yoga:proguard-annotations') } diff --git a/lib/soloader/BUCK b/lib/soloader/BUCK index 595c35eb..7ab9627f 100644 --- a/lib/soloader/BUCK +++ b/lib/soloader/BUCK @@ -7,6 +7,6 @@ load("//:yoga_defs.bzl", "YOGA_ROOTS") android_prebuilt_aar( name = "soloader", - aar = "soloader-0.1.0.aar", + aar = "soloader-0.5.1.aar", visibility = YOGA_ROOTS, ) diff --git a/lib/soloader/soloader-0.1.0.aar b/lib/soloader/soloader-0.1.0.aar deleted file mode 100644 index 497494a925fac15188520c32e25417fef4c58c8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41801 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
K!~cZ(eNd=n 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 literal 0 HcmV?d00001 From 5e1796505d8cf9113ad9e176f71c3d8862caa00e Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 19 Jul 2018 09:00:03 -0700 Subject: [PATCH 029/189] v1.9.0 Summary: New release against soloader ~0.5.0. Reviewed By: muraziz Differential Revision: D8914103 fbshipit-source-id: b1eb3f608ac7cf3791fefe88e596383483ae3474 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 85411523..d645737a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1536M -VERSION_NAME=1.8.1-SNAPSHOT +VERSION_NAME=1.9.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 From 7be9fd1a795f6a83827f2f5e959d469a97904a79 Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 19 Jul 2018 09:00:05 -0700 Subject: [PATCH 030/189] 1.9.1-SNAPSHOT Summary: Reenable snapshot releases. Reviewed By: muraziz Differential Revision: D8914105 fbshipit-source-id: f9fcd74912f3ef2f9fb94ec832c41353e3f890bb --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d645737a..51ca14c1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1536M -VERSION_NAME=1.9.0 +VERSION_NAME=1.9.1-SNAPSHOT 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 From f172d5d41c6f5a5e35c6fee949e62c8192770e4b Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:51:23 -0700 Subject: [PATCH 031/189] auto-lint YGLayout.h YGNode.h YGStyle.cpp YGStyle.h Summary: @public automatically applies lint fixes to YGLayout.h YGNode.h YGStyle.cpp YGStyle.h Reviewed By: astreet Differential Revision: D8913432 fbshipit-source-id: 488bf25db041ddb527565c26c1762c6ee4cae736 --- yoga/YGLayout.h | 10 +++++----- yoga/YGNode.h | 49 ++++++++++++++++++++++++------------------------ yoga/YGStyle.cpp | 10 +++++----- yoga/YGStyle.h | 10 +++++----- 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 46ca130d..ebd93433 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 "YGFloatOptional.h" #include "Yoga-internal.h" diff --git a/yoga/YGNode.h b/yoga/YGNode.h index cba72163..b02c02cb 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 #include "YGConfig.h" @@ -53,23 +53,23 @@ struct YGNode { bool getHasNewLayout() const { return hasNewLayout_; } - + YGNodeType getNodeType() const { return nodeType_; } - + YGMeasureFunc getMeasure() const { return measure_; } - + YGBaselineFunc getBaseline() const { return baseline_; } - + YGDirtiedFunc getDirtied() const { return dirtied_; } - + // For Performance reasons passing as reference. YGStyle& getStyle() { return style_; @@ -87,11 +87,11 @@ struct YGNode { const YGLayout& getLayout() const { return layout_; } - + uint32_t getLineIndex() const { return lineIndex_; } - + // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. // This method will return the parent of the YGNode when a YGNode only belongs @@ -100,16 +100,16 @@ struct YGNode { YGNodeRef getOwner() const { return owner_; } - + // Deprecated, use getOwner() instead. YGNodeRef getParent() const { return getOwner(); } - + const YGVector& getChildren() const { return children_; } - + YGNodeRef getChild(uint32_t index) const { return children_.at(index); } @@ -117,21 +117,22 @@ struct YGNode { YGConfigRef getConfig() const { return config_; } - + bool isDirty() const { return isDirty_; } - + std::array getResolvedDimensions() const { return resolvedDimensions_; } - + YGValue getResolvedDimension(int index) const { return resolvedDimensions_[index]; } // Methods related to positions, margin, padding and border - YGFloatOptional getLeadingPosition(const YGFlexDirection& axis, + YGFloatOptional getLeadingPosition( + const YGFlexDirection& axis, const float& axisSize) const; bool isLeadingPositionDefined(const YGFlexDirection& axis) const; bool isTrailingPosDefined(const YGFlexDirection& axis) const; @@ -174,7 +175,7 @@ struct YGNode { void setHasNewLayout(bool hasNewLayout) { hasNewLayout_ = hasNewLayout; } - + void setNodeType(YGNodeType nodeType) { nodeType_ = nodeType; } @@ -200,15 +201,15 @@ struct YGNode { void setStyle(const YGStyle& style) { style_ = style; } - + void setLayout(const YGLayout& layout) { layout_ = layout; } - + void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; } - + void setOwner(YGNodeRef owner) { owner_ = owner; } @@ -218,7 +219,7 @@ struct YGNode { } // TODO: rvalue override for setChildren - + void setConfig(YGConfigRef config) { config_ = config; } diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 7664dcf8..738d36fb 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGStyle.h" const YGValue kYGValueUndefined = {0, YGUnitUndefined}; diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index f0f97bd8..b18ac0a6 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 "YGFloatOptional.h" #include "Yoga-internal.h" From f95e3b49e9c19e1e4f925955cf358ffdf4e90630 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:51:25 -0700 Subject: [PATCH 032/189] inline trivial constructors / methods Summary: @public inlines some trivial constructors, destructors, and methods. Reviewed By: astreet Differential Revision: D8912691 fbshipit-source-id: 79840ef3322676deebed99391390d6c1796963b5 --- yoga/YGLayout.cpp | 4 ---- yoga/YGLayout.h | 4 +++- yoga/YGNode.cpp | 28 ---------------------------- yoga/YGNode.h | 39 ++++++++++++++++++++------------------- yoga/YGStyle.cpp | 6 ------ yoga/YGStyle.h | 8 +++++--- 6 files changed, 28 insertions(+), 61 deletions(-) diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index dfd7be08..03933ac9 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -61,7 +61,3 @@ bool YGLayout::operator==(YGLayout layout) const { return isEqual; } - -bool YGLayout::operator!=(YGLayout layout) const { - return !(*this == layout); -} diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index ebd93433..1df905d0 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -38,5 +38,7 @@ struct YGLayout { YGLayout(); bool operator==(YGLayout layout) const; - bool operator!=(YGLayout layout) const; + bool operator!=(YGLayout layout) const { + return !(*this == layout); + } }; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index fc97e172..a80484f1 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -254,29 +254,6 @@ void YGNode::setPosition( trailing[crossAxis]); } -YGNode::YGNode() - : context_(nullptr), - print_(nullptr), - hasNewLayout_(true), - nodeType_(YGNodeTypeDefault), - measure_(nullptr), - baseline_(nullptr), - dirtied_(nullptr), - style_(YGStyle()), - layout_(YGLayout()), - lineIndex_(0), - owner_(nullptr), - children_(YGVector()), - config_(nullptr), - isDirty_(false), - resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {} - -YGNode::YGNode(const YGNode& node) = default; - -YGNode::YGNode(const YGConfigRef newConfig) : YGNode() { - config_ = newConfig; -} - YGNode& YGNode::operator=(const YGNode& node) { if (&node == this) { return *this; @@ -360,11 +337,6 @@ void YGNode::clearChildren() { children_.shrink_to_fit(); } -YGNode::~YGNode() { - // All the member variables are deallocated externally, so no need to - // deallocate here -} - // Other Methods void YGNode::cloneChildrenIfNeeded() { diff --git a/yoga/YGNode.h b/yoga/YGNode.h index b02c02cb..7120846e 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -14,31 +14,32 @@ struct YGNode { private: - void* context_; - YGPrintFunc print_; - bool hasNewLayout_; - YGNodeType nodeType_; - YGMeasureFunc measure_; - YGBaselineFunc baseline_; - YGDirtiedFunc dirtied_; - YGStyle style_; - YGLayout layout_; - uint32_t lineIndex_; - YGNodeRef owner_; - YGVector children_; - YGConfigRef config_; - bool isDirty_; - std::array resolvedDimensions_; + void* context_ = nullptr; + YGPrintFunc print_ = nullptr; + bool hasNewLayout_ = true; + YGNodeType nodeType_ = YGNodeTypeDefault; + YGMeasureFunc measure_ = nullptr; + YGBaselineFunc baseline_ = nullptr; + YGDirtiedFunc dirtied_ = nullptr; + YGStyle style_ = {}; + YGLayout layout_ = {}; + uint32_t lineIndex_ = 0; + YGNodeRef owner_ = nullptr; + YGVector children_ = {}; + YGConfigRef config_ = nullptr; + bool isDirty_ = false; + std::array resolvedDimensions_ = { + {YGValueUndefined, YGValueUndefined}}; YGFloatOptional relativePosition( const YGFlexDirection& axis, const float& axisSize) const; public: - YGNode(); - ~YGNode(); - explicit YGNode(const YGConfigRef newConfig); - YGNode(const YGNode& node); + YGNode() = default; + ~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree + explicit YGNode(const YGConfigRef newConfig) : config_(newConfig){}; + YGNode(const YGNode& node) = default; YGNode& operator=(const YGNode& node); // Getters diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 738d36fb..06d0f2a4 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -98,9 +98,3 @@ bool YGStyle::operator==(const YGStyle& style) { return areNonFloatValuesEqual; } - -bool YGStyle::operator!=(YGStyle style) { - return !(*this == style); -} - -YGStyle::~YGStyle() {} diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index b18ac0a6..3f4bbd34 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -32,12 +32,14 @@ struct YGStyle { std::array dimensions; std::array minDimensions; std::array maxDimensions; + // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio; YGStyle(); - // Yoga specific properties, not compatible with flexbox specification bool operator==(const YGStyle& style); - bool operator!=(YGStyle style); - ~YGStyle(); + bool operator!=(YGStyle style) { + return !(*this == style); + } + ~YGStyle() = default; }; From 389f2fd85ddd28c3fc65a050291aa9601e7ec863 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:57:04 -0700 Subject: [PATCH 033/189] Run lint on `Yoga.cpp`/`Yoga.h` Summary: @public auto-fixes formatting for `Yoga.cpp`/`Yoga.h`. Submitted separately to keep other diffs cleaner. Reviewed By: astreet Differential Revision: D8868179 fbshipit-source-id: d0667f8bb909bb5ada1263aac6e22b0a8f8875ad --- yoga/Yoga.cpp | 1128 ++++++++++++++++++++++++++++--------------------- yoga/Yoga.h | 231 +++++----- 2 files changed, 789 insertions(+), 570 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index fe419207..c9404dec 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -29,17 +29,19 @@ __forceinline const float fmaxf(const float a, const float b) { #endif #ifdef ANDROID -static int YGAndroidLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args); +static int YGAndroidLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args); #else -static int YGDefaultLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args); +static int YGDefaultLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args); #endif const YGValue YGValueZero = {0, YGUnitPoint}; @@ -48,11 +50,12 @@ const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; #ifdef ANDROID #include -static int YGAndroidLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGAndroidLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { int androidLevel = YGLogLevelDebug; switch (level) { case YGLogLevelFatal: @@ -80,11 +83,12 @@ static int YGAndroidLog(const YGConfigRef config, #else #define YG_UNUSED(x) (void)(x); -static int YGDefaultLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGDefaultLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { YG_UNUSED(config); YG_UNUSED(node); switch (level) { @@ -120,7 +124,8 @@ const YGValue* YGComputedEdgeValue( return &edges[YGEdgeVertical]; } - if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) && + if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || + edge == YGEdgeEnd) && edges[YGEdgeHorizontal].unit != YGUnitUndefined) { return &edges[YGEdgeHorizontal]; } @@ -312,9 +317,10 @@ void YGNodeFreeRecursive(const YGNodeRef root) { } void YGNodeReset(const YGNodeRef node) { - YGAssertWithNode(node, - YGNodeGetChildCount(node) == 0, - "Cannot reset a node which still has children attached"); + YGAssertWithNode( + node, + YGNodeGetChildCount(node) == 0, + "Cannot reset a node which still has children attached"); YGAssertWithNode( node, node->getOwner() == nullptr, @@ -340,11 +346,11 @@ int32_t YGConfigGetInstanceCount(void) { } YGConfigRef YGConfigNew(void) { - #ifdef ANDROID +#ifdef ANDROID const YGConfigRef config = new YGConfig(YGAndroidLog); - #else +#else const YGConfigRef config = new YGConfig(YGDefaultLog); - #endif +#endif gConfigInstanceCount++; return config; } @@ -358,7 +364,10 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) { memcpy(dest, src, sizeof(YGConfig)); } -void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) { +void YGNodeInsertChild( + const YGNodeRef node, + const YGNodeRef child, + const uint32_t index) { YGAssertWithNode( node, child->getOwner() == nullptr, @@ -401,8 +410,8 @@ void YGNodeRemoveChild(const YGNodeRef owner, const YGNodeRef excludedChild) { } const YGNodeRef firstChild = YGNodeGetChild(owner, 0); if (firstChild->getOwner() == owner) { - // If the first child has this node as its owner, we assume that it is already unique. - // We can now try to delete a child in this list. + // If the first child has this node as its owner, we assume that it is + // already unique. We can now try to delete a child in this list. if (owner->removeChild(excludedChild)) { excludedChild->setLayout( YGNode().getLayout()); // layout is no longer valid @@ -411,18 +420,18 @@ void YGNodeRemoveChild(const YGNodeRef owner, const YGNodeRef excludedChild) { } return; } - // Otherwise we have to clone the node list except for the child we're trying to delete. - // We don't want to simply clone all children, because then the host will need to free - // the clone of the child that was just deleted. + // Otherwise we have to clone the node list except for the child we're trying + // to delete. We don't want to simply clone all children, because then the + // host will need to free the clone of the child that was just deleted. const YGCloneNodeFunc cloneNodeCallback = owner->getConfig()->cloneNodeCallback; uint32_t nextInsertIndex = 0; for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef oldChild = owner->getChild(i); if (excludedChild == oldChild) { - // Ignore the deleted child. Don't reset its layout or owner since it is still valid - // in the other owner. However, since this owner has now changed, we need to mark it - // as dirty. + // Ignore the deleted child. Don't reset its layout or owner since it is + // still valid in the other owner. However, since this owner has now + // changed, we need to mark it as dirty. owner->markDirtyAndPropogate(); continue; } @@ -452,7 +461,8 @@ void YGNodeRemoveAllChildren(const YGNodeRef owner) { } const YGNodeRef firstChild = YGNodeGetChild(owner, 0); if (firstChild->getOwner() == owner) { - // If the first child has this node as its owner, we assume that this child set is unique. + // If the first child has this node as its owner, we assume that this child + // set is unique. for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef oldChild = YGNodeGetChild(owner, i); oldChild->setLayout(YGNode().getLayout()); // layout is no longer valid @@ -462,13 +472,15 @@ void YGNodeRemoveAllChildren(const YGNodeRef owner) { owner->markDirtyAndPropogate(); return; } - // Otherwise, we are not the owner of the child set. We don't have to do anything to clear it. + // Otherwise, we are not the owner of the child set. We don't have to do + // anything to clear it. owner->setChildren(YGVector()); owner->markDirtyAndPropogate(); } -static void YGNodeSetChildrenInternal(YGNodeRef const owner, const std::vector &children) -{ +static void YGNodeSetChildrenInternal( + YGNodeRef const owner, + const std::vector& children) { if (!owner) { return; } @@ -484,8 +496,10 @@ static void YGNodeSetChildrenInternal(YGNodeRef const owner, const std::vector 0) { for (YGNodeRef const oldChild : owner->getChildren()) { - // Our new children may have nodes in common with the old children. We don't reset these common nodes. - if (std::find(children.begin(), children.end(), oldChild) == children.end()) { + // Our new children may have nodes in common with the old children. We + // don't reset these common nodes. + if (std::find(children.begin(), children.end(), oldChild) == + children.end()) { oldChild->setLayout(YGLayout()); oldChild->setOwner(nullptr); } @@ -499,13 +513,17 @@ static void YGNodeSetChildrenInternal(YGNodeRef const owner, const std::vector &children) -{ +void YGNodeSetChildren( + YGNodeRef const owner, + const std::vector& children) { YGNodeSetChildrenInternal(owner, children); } @@ -766,12 +784,24 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { // YG_NODE_PROPERTY_IMPL(YGNodeType, NodeType, nodeType, nodeType); YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction); -YG_NODE_STYLE_PROPERTY_IMPL(YGFlexDirection, FlexDirection, flexDirection, flexDirection); -YG_NODE_STYLE_PROPERTY_IMPL(YGJustify, JustifyContent, justifyContent, justifyContent); +YG_NODE_STYLE_PROPERTY_IMPL( + YGFlexDirection, + FlexDirection, + flexDirection, + flexDirection); +YG_NODE_STYLE_PROPERTY_IMPL( + YGJustify, + JustifyContent, + justifyContent, + justifyContent); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf); -YG_NODE_STYLE_PROPERTY_IMPL(YGPositionType, PositionType, positionType, positionType); +YG_NODE_STYLE_PROPERTY_IMPL( + YGPositionType, + PositionType, + positionType, + positionType); YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap); YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow); YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display); @@ -925,12 +955,36 @@ void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) { } } -YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinWidth, minWidth, minDimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinHeight, minHeight, minDimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( + YGValue, + Width, + width, + dimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( + YGValue, + Height, + height, + dimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MinWidth, + minWidth, + minDimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MinHeight, + minHeight, + minDimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MaxWidth, + maxWidth, + maxDimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MaxHeight, + maxHeight, + maxDimensions[YGDimensionHeight]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]); @@ -950,20 +1004,22 @@ bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) { uint32_t gCurrentGenerationCount = 0; -bool YGLayoutNodeInternal(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight, - const bool performLayout, - const char *reason, - const YGConfigRef config); +bool YGLayoutNodeInternal( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight, + const bool performLayout, + const char* reason, + const YGConfigRef config); -static void YGNodePrintInternal(const YGNodeRef node, - const YGPrintOptions options) { +static void YGNodePrintInternal( + const YGNodeRef node, + const YGPrintOptions options) { std::string str; facebook::yoga::YGNodeToString(&str, node, options, 0); YGLog(node, YGLogLevelDebug, str.c_str()); @@ -988,15 +1044,18 @@ static const std::array pos = {{ static const std::array dim = { {YGDimensionHeight, YGDimensionHeight, YGDimensionWidth, YGDimensionWidth}}; -static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { +static inline float YGNodePaddingAndBorderForAxis( + const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { return YGUnwrapFloatOptional( node->getLeadingPaddingAndBorder(axis, widthSize) + node->getTrailingPaddingAndBorder(axis, widthSize)); } -static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) { +static inline YGAlign YGNodeAlignItem( + const YGNodeRef node, + const YGNodeRef child) { const YGAlign align = child->getStyle().alignSelf == YGAlignAuto ? node->getStyle().alignItems : child->getStyle().alignSelf; @@ -1013,9 +1072,10 @@ static float YGBaseline(const YGNodeRef node) { node, node->getLayout().measuredDimensions[YGDimensionWidth], node->getLayout().measuredDimensions[YGDimensionHeight]); - YGAssertWithNode(node, - !YGFloatIsUndefined(baseline), - "Expect custom baseline function to not return NaN"); + YGAssertWithNode( + node, + !YGFloatIsUndefined(baseline), + "Expect custom baseline function to not return NaN"); return baseline; } @@ -1066,18 +1126,20 @@ static bool YGIsBaselineLayout(const YGNodeRef node) { return false; } -static inline float YGNodeDimWithMargin(const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { +static inline float YGNodeDimWithMargin( + const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { return node->getLayout().measuredDimensions[dim[axis]] + YGUnwrapFloatOptional( node->getLeadingMargin(axis, widthSize) + node->getTrailingMargin(axis, widthSize)); } -static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, - const YGFlexDirection axis, - const float ownerSize) { +static inline bool YGNodeIsStyleDimDefined( + const YGNodeRef node, + const YGFlexDirection axis, + const float ownerSize) { bool isUndefined = YGFloatIsUndefined(node->getResolvedDimension(dim[axis]).value); return !( @@ -1091,7 +1153,9 @@ static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, YGFloatIsUndefined(ownerSize)))); } -static inline bool YGNodeIsLayoutDimDefined(const YGNodeRef node, const YGFlexDirection axis) { +static inline bool YGNodeIsLayoutDimDefined( + const YGNodeRef node, + const YGFlexDirection axis) { const float value = node->getLayout().measuredDimensions[dim[axis]]; return !YGFloatIsUndefined(value) && value >= 0.0f; } @@ -1127,23 +1191,24 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( return YGFloatOptional(value); } -// Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't go -// below the -// padding and border amount. -static inline float YGNodeBoundAxis(const YGNodeRef node, - const YGFlexDirection axis, - const float value, - const float axisSize, - const float widthSize) { +// Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't +// go below the padding and border amount. +static inline float YGNodeBoundAxis( + const YGNodeRef node, + const YGFlexDirection axis, + const float value, + const float axisSize, + const float widthSize) { return YGFloatMax( YGUnwrapFloatOptional( YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } -static void YGNodeSetChildTrailingPosition(const YGNodeRef node, - const YGNodeRef child, - const YGFlexDirection axis) { +static void YGNodeSetChildTrailingPosition( + const YGNodeRef node, + const YGNodeRef child, + const YGFlexDirection axis) { const float size = child->getLayout().measuredDimensions[dim[axis]]; child->setLayoutPosition( node->getLayout().measuredDimensions[dim[axis]] - size - @@ -1151,15 +1216,15 @@ static void YGNodeSetChildTrailingPosition(const YGNodeRef node, trailing[axis]); } -static void YGConstrainMaxSizeForMode(const YGNodeRef node, - const enum YGFlexDirection axis, - const float ownerAxisSize, - const float ownerWidth, - YGMeasureMode *mode, - float *size) { +static void YGConstrainMaxSizeForMode( + const YGNodeRef node, + const enum YGFlexDirection axis, + const float ownerAxisSize, + const float ownerWidth, + YGMeasureMode* mode, + float* size) { const YGFloatOptional maxSize = - YGResolveValue( - node->getStyle().maxDimensions[dim[axis]], ownerAxisSize) + + YGResolveValue(node->getStyle().maxDimensions[dim[axis]], ownerAxisSize) + YGFloatOptional(node->getMarginForAxis(axis, ownerWidth)); switch (*mode) { case YGMeasureModeExactly: @@ -1177,16 +1242,17 @@ static void YGConstrainMaxSizeForMode(const YGNodeRef node, } } -static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, - const YGNodeRef child, - const float width, - const YGMeasureMode widthMode, - const float height, - const float ownerWidth, - const float ownerHeight, - const YGMeasureMode heightMode, - const YGDirection direction, - const YGConfigRef config) { +static void YGNodeComputeFlexBasisForChild( + const YGNodeRef node, + const YGNodeRef child, + const float width, + const YGMeasureMode widthMode, + const float height, + const float ownerWidth, + const float ownerHeight, + const YGMeasureMode heightMode, + const YGDirection direction, + const YGConfigRef config) { const YGFlexDirection mainAxis = YGResolveFlexDirection(node->getStyle().flexDirection, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); @@ -1200,7 +1266,8 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, const YGFloatOptional resolvedFlexBasis = YGResolveValue(child->resolveFlexBasisPtr(), mainAxisownerSize); - const bool isRowStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, ownerWidth); + const bool isRowStyleDimDefined = + YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, ownerWidth); const bool isColumnStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, ownerHeight); @@ -1284,7 +1351,8 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, childHeight = marginColumn + (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); childHeightMeasureMode = YGMeasureModeExactly; - } else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { + } else if ( + isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { childWidth = marginRow + (childHeight - marginColumn) * child->getStyle().aspectRatio.getValue(); @@ -1296,10 +1364,13 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, // set the cross // axis to be measured exactly with the available inner width - const bool hasExactWidth = !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly; - const bool childWidthStretch = YGNodeAlignItem(node, child) == YGAlignStretch && - childWidthMeasureMode != YGMeasureModeExactly; - if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && childWidthStretch) { + const bool hasExactWidth = + !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly; + const bool childWidthStretch = + YGNodeAlignItem(node, child) == YGAlignStretch && + childWidthMeasureMode != YGMeasureModeExactly; + if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && + childWidthStretch) { childWidth = width; childWidthMeasureMode = YGMeasureModeExactly; if (!child->getStyle().aspectRatio.isUndefined()) { @@ -1309,10 +1380,13 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, } } - const bool hasExactHeight = !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly; - const bool childHeightStretch = YGNodeAlignItem(node, child) == YGAlignStretch && - childHeightMeasureMode != YGMeasureModeExactly; - if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && childHeightStretch) { + const bool hasExactHeight = + !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly; + const bool childHeightStretch = + YGNodeAlignItem(node, child) == YGAlignStretch && + childHeightMeasureMode != YGMeasureModeExactly; + if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && + childHeightStretch) { childHeight = height; childHeightMeasureMode = YGMeasureModeExactly; @@ -1324,26 +1398,33 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, } YGConstrainMaxSizeForMode( - child, YGFlexDirectionRow, ownerWidth, ownerWidth, &childWidthMeasureMode, &childWidth); - YGConstrainMaxSizeForMode(child, - YGFlexDirectionColumn, - ownerHeight, - ownerWidth, - &childHeightMeasureMode, - &childHeight); + child, + YGFlexDirectionRow, + ownerWidth, + ownerWidth, + &childWidthMeasureMode, + &childWidth); + YGConstrainMaxSizeForMode( + child, + YGFlexDirectionColumn, + ownerHeight, + ownerWidth, + &childHeightMeasureMode, + &childHeight); // Measure the child - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - childWidthMeasureMode, - childHeightMeasureMode, - ownerWidth, - ownerHeight, - false, - "measure", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + childWidthMeasureMode, + childHeightMeasureMode, + ownerWidth, + ownerHeight, + false, + "measure", + config); child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax( child->getLayout().measuredDimensions[dim[mainAxis]], @@ -1352,13 +1433,14 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); } -static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, - const YGNodeRef child, - const float width, - const YGMeasureMode widthMode, - const float height, - const YGDirection direction, - const YGConfigRef config) { +static void YGNodeAbsoluteLayoutChild( + const YGNodeRef node, + const YGNodeRef child, + const float width, + const YGMeasureMode widthMode, + const float height, + const YGDirection direction, + const YGConfigRef config) { const YGFlexDirection mainAxis = YGResolveFlexDirection(node->getStyle().flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); @@ -1375,8 +1457,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->getMarginForAxis(YGFlexDirectionColumn, width)); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { - childWidth = - YGUnwrapFloatOptional(YGResolveValue(child->getResolvedDimension(YGDimensionWidth), width)) + + childWidth = YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionWidth), width)) + marginRow; } else { // If the child doesn't have a specified width, compute the width based @@ -1390,13 +1472,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGUnwrapFloatOptional( child->getLeadingPosition(YGFlexDirectionRow, width) + child->getTrailingPosition(YGFlexDirectionRow, width)); - childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); + childWidth = + YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) { - childHeight = - YGUnwrapFloatOptional(YGResolveValue(child->getResolvedDimension(YGDimensionHeight), height)) + + childHeight = YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionHeight), height)) + marginColumn; } else { // If the child doesn't have a specified height, compute the height @@ -1411,12 +1494,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGUnwrapFloatOptional( child->getLeadingPosition(YGFlexDirectionColumn, height) + child->getTrailingPosition(YGFlexDirectionColumn, height)); - childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight, height, width); + childHeight = YGNodeBoundAxis( + child, YGFlexDirectionColumn, childHeight, height, width); } } - // Exactly one dimension needs to be defined for us to be able to do aspect ratio - // calculation. One dimension being the anchor and the other being flexible. + // Exactly one dimension needs to be defined for us to be able to do aspect + // ratio calculation. One dimension being the anchor and the other being + // flexible. if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) { if (!child->getStyle().aspectRatio.isUndefined()) { if (YGFloatIsUndefined(childWidth)) { @@ -1432,14 +1517,17 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, // If we're still missing one or the other dimension, measure the content. if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) { - childWidthMeasureMode = - YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; - childHeightMeasureMode = - YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; + childWidthMeasureMode = YGFloatIsUndefined(childWidth) + ? YGMeasureModeUndefined + : YGMeasureModeExactly; + childHeightMeasureMode = YGFloatIsUndefined(childHeight) + ? YGMeasureModeUndefined + : YGMeasureModeExactly; - // If the size of the owner is defined then try to constrain the absolute child to that size - // as well. This allows text within the absolute child to wrap to the size of its owner. - // This is the same behavior as many browsers implement. + // If the size of the owner is defined then try to constrain the absolute + // child to that size as well. This allows text within the absolute child to + // wrap to the size of its owner. This is the same behavior as many browsers + // implement. if (!isMainAxisRow && YGFloatIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined && !YGFloatIsUndefined(width) && width > 0) { @@ -1447,17 +1535,18 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, childWidthMeasureMode = YGMeasureModeAtMost; } - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - childWidthMeasureMode, - childHeightMeasureMode, - childWidth, - childHeight, - false, - "abs-measure", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + childWidthMeasureMode, + childHeightMeasureMode, + childWidth, + childHeight, + false, + "abs-measure", + config); childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionRow, width)); @@ -1466,17 +1555,18 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->getMarginForAxis(YGFlexDirectionColumn, width)); } - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - YGMeasureModeExactly, - YGMeasureModeExactly, - childWidth, - childHeight, - true, - "abs-layout", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + YGMeasureModeExactly, + YGMeasureModeExactly, + childWidth, + childHeight, + true, + "abs-layout", + config); if (child->isTrailingPosDefined(mainAxis) && !child->isLeadingPositionDefined(mainAxis)) { @@ -1535,13 +1625,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, } } -static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight) { +static void YGNodeWithMeasureFuncSetMeasuredDimensions( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight) { YGAssertWithNode( node, node->getMeasure() != nullptr, @@ -1549,8 +1640,8 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); - const float paddingAndBorderAxisColumn = - YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, availableWidth); + const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis( + node, YGFlexDirectionColumn, availableWidth); const float marginAxisRow = YGUnwrapFloatOptional( node->getMarginForAxis(YGFlexDirectionRow, availableWidth)); const float marginAxisColumn = YGUnwrapFloatOptional( @@ -1617,13 +1708,14 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, // For nodes with no children, use the available values if they were provided, // or the minimum size as indicated by the padding and border sizes. -static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight) { +static void YGNodeEmptyContainerSetMeasuredDimensions( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight) { const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth); const float paddingAndBorderAxisColumn = @@ -1658,13 +1750,14 @@ static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, YGDimensionHeight); } -static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight) { +static bool YGNodeFixedSizeSetMeasuredDimensions( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight) { if ((!YGFloatIsUndefined(availableWidth) && widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) || (!YGFloatIsUndefined(availableHeight) && @@ -1739,12 +1832,14 @@ static float YGNodeCalculateAvailableInnerDim( if (!YGFloatIsUndefined(availableInnerDim)) { // We want to make sure our available height does not violate min and max // constraints - const YGFloatOptional minDimensionOptional = YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); + const YGFloatOptional minDimensionOptional = + YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); const float minInnerDim = minDimensionOptional.isUndefined() ? 0.0f : minDimensionOptional.getValue() - paddingAndBorder; - const YGFloatOptional maxDimensionOptional = YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim) ; + const YGFloatOptional maxDimensionOptional = + YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim); const float maxInnerDim = maxDimensionOptional.isUndefined() ? FLT_MAX @@ -2523,37 +2618,42 @@ static void YGJustifyMainAxis( // - YGMeasureModeExactly: fill available // - YGMeasureModeAtMost: fit content // -// When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller passes -// an available size of -// undefined then it must also pass a measure mode of YGMeasureModeUndefined -// in that dimension. +// When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller +// passes an available size of undefined then it must also pass a measure +// mode of YGMeasureModeUndefined in that dimension. // -static void YGNodelayoutImpl(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight, - const bool performLayout, - const YGConfigRef config) { - YGAssertWithNode(node, - YGFloatIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined - : true, - "availableWidth is indefinite so widthMeasureMode must be " - "YGMeasureModeUndefined"); - YGAssertWithNode(node, - YGFloatIsUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined - : true, - "availableHeight is indefinite so heightMeasureMode must be " - "YGMeasureModeUndefined"); +static void YGNodelayoutImpl( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight, + const bool performLayout, + const YGConfigRef config) { + YGAssertWithNode( + node, + YGFloatIsUndefined(availableWidth) + ? widthMeasureMode == YGMeasureModeUndefined + : true, + "availableWidth is indefinite so widthMeasureMode must be " + "YGMeasureModeUndefined"); + YGAssertWithNode( + node, + YGFloatIsUndefined(availableHeight) + ? heightMeasureMode == YGMeasureModeUndefined + : true, + "availableHeight is indefinite so heightMeasureMode must be " + "YGMeasureModeUndefined"); // Set the resolved resolution in the node's layout. const YGDirection direction = node->resolveDirection(ownerDirection); node->setLayoutDirection(direction); - const YGFlexDirection flexRowDirection = YGResolveFlexDirection(YGFlexDirectionRow, direction); + const YGFlexDirection flexRowDirection = + YGResolveFlexDirection(YGFlexDirectionRow, direction); const YGFlexDirection flexColumnDirection = YGResolveFlexDirection(YGFlexDirectionColumn, direction); @@ -2598,41 +2698,46 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGEdgeBottom); if (node->getMeasure() != nullptr) { - YGNodeWithMeasureFuncSetMeasuredDimensions(node, - availableWidth, - availableHeight, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight); + YGNodeWithMeasureFuncSetMeasuredDimensions( + node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight); return; } const uint32_t childCount = YGNodeGetChildCount(node); if (childCount == 0) { - YGNodeEmptyContainerSetMeasuredDimensions(node, - availableWidth, - availableHeight, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight); + YGNodeEmptyContainerSetMeasuredDimensions( + node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight); return; } - // If we're not being asked to perform a full layout we can skip the algorithm if we already know - // the size - if (!performLayout && YGNodeFixedSizeSetMeasuredDimensions(node, - availableWidth, - availableHeight, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight)) { + // If we're not being asked to perform a full layout we can skip the algorithm + // if we already know the size + if (!performLayout && + YGNodeFixedSizeSetMeasuredDimensions( + node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight)) { return; } - // At this point we know we're going to perform work. Ensure that each child has a mutable copy. + // At this point we know we're going to perform work. Ensure that each child + // has a mutable copy. node->cloneChildrenIfNeeded(); // Reset layout flags, as they could have changed. node->setLayoutHadOverflow(false); @@ -2649,12 +2754,15 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float leadingPaddingAndBorderCross = YGUnwrapFloatOptional( node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)); - const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); + const float paddingAndBorderAxisMain = + YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); const float paddingAndBorderAxisCross = YGNodePaddingAndBorderForAxis(node, crossAxis, ownerWidth); - YGMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; - YGMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode; + YGMeasureMode measureModeMainDim = + isMainAxisRow ? widthMeasureMode : heightMeasureMode; + YGMeasureMode measureModeCrossDim = + isMainAxisRow ? heightMeasureMode : widthMeasureMode; const float paddingAndBorderAxisRow = isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross; @@ -2667,13 +2775,16 @@ static void YGNodelayoutImpl(const YGNodeRef node, node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); const float minInnerWidth = - YGUnwrapFloatOptional(YGResolveValue(node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - paddingAndBorderAxisRow; const float maxInnerWidth = - YGUnwrapFloatOptional(YGResolveValue(node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - paddingAndBorderAxisRow; const float minInnerHeight = - YGUnwrapFloatOptional(YGResolveValue(node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - paddingAndBorderAxisColumn; const float maxInnerHeight = YGUnwrapFloatOptional(YGResolveValue( @@ -2756,7 +2867,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, // the line length, so there's no more space left to distribute. bool sizeBasedOnContent = false; - // If we don't measure with exact main dimension we want to ensure we don't violate min and max + // If we don't measure with exact main dimension we want to ensure we don't + // violate min and max if (measureModeMainDim != YGMeasureModeExactly) { if (!YGFloatIsUndefined(minInnerMainDim) && collectedFlexItemsValues.sizeConsumedOnCurrentLine < @@ -2792,10 +2904,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, collectedFlexItemsValues.remainingFreeSpace = availableInnerMainDim - collectedFlexItemsValues.sizeConsumedOnCurrentLine; } else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0) { - // availableInnerMainDim is indefinite which means the node is being sized based on its - // content. - // sizeConsumedOnCurrentLine is negative which means the node will allocate 0 points for - // its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine. + // availableInnerMainDim is indefinite which means the node is being sized + // based on its content. sizeConsumedOnCurrentLine is negative which means + // the node will allocate 0 points for its content. Consequently, + // remainingFreeSpace is 0 - sizeConsumedOnCurrentLine. collectedFlexItemsValues.remainingFreeSpace = -collectedFlexItemsValues.sizeConsumedOnCurrentLine; } @@ -2897,7 +3009,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, crossAxis, availableInnerWidth)), pos[crossAxis]); } - // If leading position is not defined or calculations result in Nan, default to border + margin + // If leading position is not defined or calculations result in Nan, + // default to border + margin if (!isChildLeadingPosDefined || YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( @@ -2923,7 +3036,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, child->marginTrailingValue(crossAxis).unit != YGUnitAuto) { // If the child defines a definite size for its cross axis, there's // no need to stretch. - if (!YGNodeIsStyleDimDefined(child, crossAxis, availableInnerCrossDim)) { + if (!YGNodeIsStyleDimDefined( + child, crossAxis, availableInnerCrossDim)) { float childMainSize = child->getLayout().measuredDimensions[dim[mainAxis]]; float childCrossSize = @@ -2941,21 +3055,25 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGMeasureMode childMainMeasureMode = YGMeasureModeExactly; YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly; - YGConstrainMaxSizeForMode(child, - mainAxis, - availableInnerMainDim, - availableInnerWidth, - &childMainMeasureMode, - &childMainSize); - YGConstrainMaxSizeForMode(child, - crossAxis, - availableInnerCrossDim, - availableInnerWidth, - &childCrossMeasureMode, - &childCrossSize); + YGConstrainMaxSizeForMode( + child, + mainAxis, + availableInnerMainDim, + availableInnerWidth, + &childMainMeasureMode, + &childMainSize); + YGConstrainMaxSizeForMode( + child, + crossAxis, + availableInnerCrossDim, + availableInnerWidth, + &childCrossMeasureMode, + &childCrossSize); - const float childWidth = isMainAxisRow ? childMainSize : childCrossSize; - const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize; + const float childWidth = + isMainAxisRow ? childMainSize : childCrossSize; + const float childHeight = + !isMainAxisRow ? childMainSize : childCrossSize; const YGMeasureMode childWidthMeasureMode = YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined @@ -3015,7 +3133,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, // STEP 8: MULTI-LINE CONTENT ALIGNMENT if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node)) && !YGFloatIsUndefined(availableInnerCrossDim)) { - const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; + const float remainingAlignContentDim = + availableInnerCrossDim - totalLineCrossDim; float crossDimLead = 0; float currentLead = leadingPaddingAndBorderCross; @@ -3140,9 +3259,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, crossAxis, availableInnerWidth)), pos[crossAxis]); - // Remeasure child with the line height as it as been only measured with the - // owners height yet. - if (!YGNodeIsStyleDimDefined(child, crossAxis, availableInnerCrossDim)) { + // Remeasure child with the line height as it as been only + // measured with the owners height yet. + if (!YGNodeIsStyleDimDefined( + child, crossAxis, availableInnerCrossDim)) { const float childWidth = isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionWidth] + @@ -3165,17 +3285,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, childHeight, child->getLayout() .measuredDimensions[YGDimensionHeight]))) { - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - YGMeasureModeExactly, - YGMeasureModeExactly, - availableInnerWidth, - availableInnerHeight, - true, - "multiline-stretch", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + YGMeasureModeExactly, + YGMeasureModeExactly, + availableInnerWidth, + availableInnerHeight, + true, + "multiline-stretch", + config); } } break; @@ -3278,7 +3399,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, dim[crossAxis]); } - // As we only wrapped in normal direction yet, we need to reverse the positions on wrap-reverse. + // As we only wrapped in normal direction yet, we need to reverse the + // positions on wrap-reverse. if (performLayout && node->getStyle().flexWrap == YGWrapWrapReverse) { for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); @@ -3309,10 +3431,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN - const bool needsMainTrailingPos = - mainAxis == YGFlexDirectionRowReverse || mainAxis == YGFlexDirectionColumnReverse; - const bool needsCrossTrailingPos = - crossAxis == YGFlexDirectionRowReverse || crossAxis == YGFlexDirectionColumnReverse; + const bool needsMainTrailingPos = mainAxis == YGFlexDirectionRowReverse || + mainAxis == YGFlexDirectionColumnReverse; + const bool needsCrossTrailingPos = crossAxis == YGFlexDirectionRowReverse || + crossAxis == YGFlexDirectionColumnReverse; // Set trailing position if necessary. if (needsMainTrailingPos || needsCrossTrailingPos) { @@ -3338,9 +3460,10 @@ bool gPrintTree = false; bool gPrintChanges = false; bool gPrintSkips = false; -static const char *spacer = " "; +static const char* spacer = + " "; -static const char *YGSpacer(const unsigned long level) { +static const char* YGSpacer(const unsigned long level) { const size_t spacerLen = strlen(spacer); if (level > spacerLen) { return &spacer[0]; @@ -3349,9 +3472,12 @@ static const char *YGSpacer(const unsigned long level) { } } -static const char *YGMeasureModeName(const YGMeasureMode mode, const bool performLayout) { - const char *kMeasureModeNames[YGMeasureModeCount] = {"UNDEFINED", "EXACTLY", "AT_MOST"}; - const char *kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", +static const char* YGMeasureModeName( + const YGMeasureMode mode, + const bool performLayout) { + const char* kMeasureModeNames[YGMeasureModeCount] = { + "UNDEFINED", "EXACTLY", "AT_MOST"}; + const char* kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_" "MOST"}; @@ -3363,25 +3489,30 @@ static const char *YGMeasureModeName(const YGMeasureMode mode, const bool perfor return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode]; } -static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(YGMeasureMode sizeMode, - float size, - float lastComputedSize) { - return sizeMode == YGMeasureModeExactly && YGFloatsEqual(size, lastComputedSize); +static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize( + YGMeasureMode sizeMode, + float size, + float lastComputedSize) { + return sizeMode == YGMeasureModeExactly && + YGFloatsEqual(size, lastComputedSize); } -static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits(YGMeasureMode sizeMode, - float size, - YGMeasureMode lastSizeMode, - float lastComputedSize) { - return sizeMode == YGMeasureModeAtMost && lastSizeMode == YGMeasureModeUndefined && - (size >= lastComputedSize || YGFloatsEqual(size, lastComputedSize)); +static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits( + YGMeasureMode sizeMode, + float size, + YGMeasureMode lastSizeMode, + float lastComputedSize) { + return sizeMode == YGMeasureModeAtMost && + lastSizeMode == YGMeasureModeUndefined && + (size >= lastComputedSize || YGFloatsEqual(size, lastComputedSize)); } -static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureMode sizeMode, - float size, - YGMeasureMode lastSizeMode, - float lastSize, - float lastComputedSize) { +static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid( + YGMeasureMode sizeMode, + float size, + YGMeasureMode lastSizeMode, + float lastSize, + float lastComputedSize) { return lastSizeMode == YGMeasureModeAtMost && sizeMode == YGMeasureModeAtMost && !YGFloatIsUndefined(lastSize) && !YGFloatIsUndefined(size) && !YGFloatIsUndefined(lastComputedSize) && @@ -3389,10 +3520,11 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureM (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize)); } -float YGRoundValueToPixelGrid(const float value, - const float pointScaleFactor, - const bool forceCeil, - const bool forceFloor) { +float YGRoundValueToPixelGrid( + const float value, + const float pointScaleFactor, + const bool forceCeil, + const bool forceFloor) { float scaledValue = value * pointScaleFactor; float fractial = fmodf(scaledValue, 1.0f); if (YGFloatsEqual(fractial, 0)) { @@ -3419,66 +3551,74 @@ float YGRoundValueToPixelGrid(const float value, : scaledValue / pointScaleFactor; } -bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, - const float width, - const YGMeasureMode heightMode, - const float height, - const YGMeasureMode lastWidthMode, - const float lastWidth, - const YGMeasureMode lastHeightMode, - const float lastHeight, - const float lastComputedWidth, - const float lastComputedHeight, - const float marginRow, - const float marginColumn, - const YGConfigRef config) { +bool YGNodeCanUseCachedMeasurement( + const YGMeasureMode widthMode, + const float width, + const YGMeasureMode heightMode, + const float height, + const YGMeasureMode lastWidthMode, + const float lastWidth, + const YGMeasureMode lastHeightMode, + const float lastHeight, + const float lastComputedWidth, + const float lastComputedHeight, + const float marginRow, + const float marginColumn, + const YGConfigRef config) { if ((!YGFloatIsUndefined(lastComputedHeight) && lastComputedHeight < 0) || (!YGFloatIsUndefined(lastComputedWidth) && lastComputedWidth < 0)) { return false; } bool useRoundedComparison = config != nullptr && config->pointScaleFactor != 0; - const float effectiveWidth = - useRoundedComparison ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false) - : width; - const float effectiveHeight = - useRoundedComparison ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false) - : height; - const float effectiveLastWidth = - useRoundedComparison - ? YGRoundValueToPixelGrid(lastWidth, config->pointScaleFactor, false, false) - : lastWidth; - const float effectiveLastHeight = - useRoundedComparison - ? YGRoundValueToPixelGrid(lastHeight, config->pointScaleFactor, false, false) - : lastHeight; + const float effectiveWidth = useRoundedComparison + ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false) + : width; + const float effectiveHeight = useRoundedComparison + ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false) + : height; + const float effectiveLastWidth = useRoundedComparison + ? YGRoundValueToPixelGrid( + lastWidth, config->pointScaleFactor, false, false) + : lastWidth; + const float effectiveLastHeight = useRoundedComparison + ? YGRoundValueToPixelGrid( + lastHeight, config->pointScaleFactor, false, false) + : lastHeight; - const bool hasSameWidthSpec = - lastWidthMode == widthMode && YGFloatsEqual(effectiveLastWidth, effectiveWidth); - const bool hasSameHeightSpec = - lastHeightMode == heightMode && YGFloatsEqual(effectiveLastHeight, effectiveHeight); + const bool hasSameWidthSpec = lastWidthMode == widthMode && + YGFloatsEqual(effectiveLastWidth, effectiveWidth); + const bool hasSameHeightSpec = lastHeightMode == heightMode && + YGFloatsEqual(effectiveLastHeight, effectiveHeight); const bool widthIsCompatible = - hasSameWidthSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(widthMode, - width - marginRow, - lastComputedWidth) || - YGMeasureModeOldSizeIsUnspecifiedAndStillFits(widthMode, - width - marginRow, - lastWidthMode, - lastComputedWidth) || + hasSameWidthSpec || + YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize( + widthMode, width - marginRow, lastComputedWidth) || + YGMeasureModeOldSizeIsUnspecifiedAndStillFits( + widthMode, width - marginRow, lastWidthMode, lastComputedWidth) || YGMeasureModeNewMeasureSizeIsStricterAndStillValid( - widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth); + widthMode, + width - marginRow, + lastWidthMode, + lastWidth, + lastComputedWidth); const bool heightIsCompatible = - hasSameHeightSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(heightMode, - height - marginColumn, - lastComputedHeight) || - YGMeasureModeOldSizeIsUnspecifiedAndStillFits(heightMode, - height - marginColumn, - lastHeightMode, - lastComputedHeight) || + hasSameHeightSpec || + YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize( + heightMode, height - marginColumn, lastComputedHeight) || + YGMeasureModeOldSizeIsUnspecifiedAndStillFits( + heightMode, + height - marginColumn, + lastHeightMode, + lastComputedHeight) || YGMeasureModeNewMeasureSizeIsStricterAndStillValid( - heightMode, height - marginColumn, lastHeightMode, lastHeight, lastComputedHeight); + heightMode, + height - marginColumn, + lastHeightMode, + lastHeight, + lastComputedHeight); return widthIsCompatible && heightIsCompatible; } @@ -3491,17 +3631,18 @@ bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, // Input parameters are the same as YGNodelayoutImpl (see above) // Return parameter is true if layout was performed, false if skipped // -bool YGLayoutNodeInternal(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight, - const bool performLayout, - const char *reason, - const YGConfigRef config) { +bool YGLayoutNodeInternal( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight, + const bool performLayout, + const char* reason, + const YGConfigRef config) { YGLayout* layout = &node->getLayout(); gDepth++; @@ -3513,8 +3654,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node, if (needToVisitNode) { // Invalidate the cached results. layout->nextCachedMeasurementsIndex = 0; - layout->cachedLayout.widthMeasureMode = (YGMeasureMode) -1; - layout->cachedLayout.heightMeasureMode = (YGMeasureMode) -1; + layout->cachedLayout.widthMeasureMode = (YGMeasureMode)-1; + layout->cachedLayout.heightMeasureMode = (YGMeasureMode)-1; layout->cachedLayout.computedWidth = -1; layout->cachedLayout.computedHeight = -1; } @@ -3540,36 +3681,38 @@ bool YGLayoutNodeInternal(const YGNodeRef node, node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); // First, try to use the layout cache. - if (YGNodeCanUseCachedMeasurement(widthMeasureMode, - availableWidth, - heightMeasureMode, - availableHeight, - layout->cachedLayout.widthMeasureMode, - layout->cachedLayout.availableWidth, - layout->cachedLayout.heightMeasureMode, - layout->cachedLayout.availableHeight, - layout->cachedLayout.computedWidth, - layout->cachedLayout.computedHeight, - marginAxisRow, - marginAxisColumn, - config)) { + if (YGNodeCanUseCachedMeasurement( + widthMeasureMode, + availableWidth, + heightMeasureMode, + availableHeight, + layout->cachedLayout.widthMeasureMode, + layout->cachedLayout.availableWidth, + layout->cachedLayout.heightMeasureMode, + layout->cachedLayout.availableHeight, + layout->cachedLayout.computedWidth, + layout->cachedLayout.computedHeight, + marginAxisRow, + marginAxisColumn, + config)) { cachedResults = &layout->cachedLayout; } else { // Try to use the measurement cache. for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { - if (YGNodeCanUseCachedMeasurement(widthMeasureMode, - availableWidth, - heightMeasureMode, - availableHeight, - layout->cachedMeasurements[i].widthMeasureMode, - layout->cachedMeasurements[i].availableWidth, - layout->cachedMeasurements[i].heightMeasureMode, - layout->cachedMeasurements[i].availableHeight, - layout->cachedMeasurements[i].computedWidth, - layout->cachedMeasurements[i].computedHeight, - marginAxisRow, - marginAxisColumn, - config)) { + if (YGNodeCanUseCachedMeasurement( + widthMeasureMode, + availableWidth, + heightMeasureMode, + availableHeight, + layout->cachedMeasurements[i].widthMeasureMode, + layout->cachedMeasurements[i].availableWidth, + layout->cachedMeasurements[i].heightMeasureMode, + layout->cachedMeasurements[i].availableHeight, + layout->cachedMeasurements[i].computedWidth, + layout->cachedMeasurements[i].computedHeight, + marginAxisRow, + marginAxisColumn, + config)) { cachedResults = &layout->cachedMeasurements[i]; break; } @@ -3584,10 +3727,13 @@ bool YGLayoutNodeInternal(const YGNodeRef node, } } else { for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { - if (YGFloatsEqual(layout->cachedMeasurements[i].availableWidth, availableWidth) && - YGFloatsEqual(layout->cachedMeasurements[i].availableHeight, availableHeight) && + if (YGFloatsEqual( + layout->cachedMeasurements[i].availableWidth, availableWidth) && + YGFloatsEqual( + layout->cachedMeasurements[i].availableHeight, availableHeight) && layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode && - layout->cachedMeasurements[i].heightMeasureMode == heightMeasureMode) { + layout->cachedMeasurements[i].heightMeasureMode == + heightMeasureMode) { cachedResults = &layout->cachedMeasurements[i]; break; } @@ -3596,10 +3742,16 @@ bool YGLayoutNodeInternal(const YGNodeRef node, if (!needToVisitNode && cachedResults != nullptr) { layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth; - layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight; + layout->measuredDimensions[YGDimensionHeight] = + cachedResults->computedHeight; if (gPrintChanges && gPrintSkips) { - YGLog(node, YGLogLevelVerbose, "%s%d.{[skipped] ", YGSpacer(gDepth), gDepth); + YGLog( + node, + YGLogLevelVerbose, + "%s%d.{[skipped] ", + YGSpacer(gDepth), + gDepth); if (node->getPrintFunc() != nullptr) { node->getPrintFunc()(node); } @@ -3638,16 +3790,17 @@ bool YGLayoutNodeInternal(const YGNodeRef node, reason); } - YGNodelayoutImpl(node, - availableWidth, - availableHeight, - ownerDirection, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight, - performLayout, - config); + YGNodelayoutImpl( + node, + availableWidth, + availableHeight, + ownerDirection, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight, + performLayout, + config); if (gPrintChanges) { YGLog( @@ -3681,13 +3834,14 @@ bool YGLayoutNodeInternal(const YGNodeRef node, layout->nextCachedMeasurementsIndex = 0; } - YGCachedMeasurement *newCacheEntry; + YGCachedMeasurement* newCacheEntry; if (performLayout) { // Use the single layout cache entry. newCacheEntry = &layout->cachedLayout; } else { // Allocate a new measurement cache entry. - newCacheEntry = &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex]; + newCacheEntry = + &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex]; layout->nextCachedMeasurementsIndex++; } @@ -3695,8 +3849,10 @@ bool YGLayoutNodeInternal(const YGNodeRef node, newCacheEntry->availableHeight = availableHeight; newCacheEntry->widthMeasureMode = widthMeasureMode; newCacheEntry->heightMeasureMode = heightMeasureMode; - newCacheEntry->computedWidth = layout->measuredDimensions[YGDimensionWidth]; - newCacheEntry->computedHeight = layout->measuredDimensions[YGDimensionHeight]; + newCacheEntry->computedWidth = + layout->measuredDimensions[YGDimensionWidth]; + newCacheEntry->computedHeight = + layout->measuredDimensions[YGDimensionHeight]; } } @@ -3717,8 +3873,13 @@ bool YGLayoutNodeInternal(const YGNodeRef node, return (needToVisitNode || cachedResults == nullptr); } -void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint) { - YGAssertWithConfig(config, pixelsInPoint >= 0.0f, "Scale factor should not be less than zero"); +void YGConfigSetPointScaleFactor( + const YGConfigRef config, + const float pixelsInPoint) { + YGAssertWithConfig( + config, + pixelsInPoint >= 0.0f, + "Scale factor should not be less than zero"); // We store points for Pixel as we will use it for rounding if (pixelsInPoint == 0.0f) { @@ -3729,10 +3890,11 @@ void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInP } } -static void YGRoundToPixelGrid(const YGNodeRef node, - const float pointScaleFactor, - const float absoluteLeft, - const float absoluteTop) { +static void YGRoundToPixelGrid( + const YGNodeRef node, + const float pointScaleFactor, + const float absoluteLeft, + const float absoluteTop) { if (pointScaleFactor == 0.0f) { return; } @@ -3749,8 +3911,8 @@ static void YGRoundToPixelGrid(const YGNodeRef node, const float absoluteNodeRight = absoluteNodeLeft + nodeWidth; const float absoluteNodeBottom = absoluteNodeTop + nodeHeight; - // If a node has a custom measure function we never want to round down its size as this could - // lead to unwanted text truncation. + // If a node has a custom measure function we never want to round down its + // size as this could lead to unwanted text truncation. const bool textRounding = node->getNodeType() == YGNodeTypeText; node->setLayoutPosition( @@ -3761,13 +3923,15 @@ static void YGRoundToPixelGrid(const YGNodeRef node, YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding), YGEdgeTop); - // We multiply dimension by scale factor and if the result is close to the whole number, we don't - // have any fraction - // To verify if the result is close to whole number we want to check both floor and ceil numbers - const bool hasFractionalWidth = !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) && - !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0); - const bool hasFractionalHeight = !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 0) && - !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0); + // We multiply dimension by scale factor and if the result is close to the + // whole number, we don't have any fraction To verify if the result is close + // to whole number we want to check both floor and ceil numbers + const bool hasFractionalWidth = + !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) && + !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0); + const bool hasFractionalHeight = + !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 0) && + !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0); node->setLayoutDimension( YGRoundValueToPixelGrid( @@ -3844,7 +4008,8 @@ void YGNodeCalculateLayout( node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) .isUndefined()) { - height = YGUnwrapFloatOptional(YGResolveValue(node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); + height = YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); heightMeasureMode = YGMeasureModeAtMost; } else { height = ownerHeight; @@ -3950,12 +4115,14 @@ void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( config->shouldDiffLayoutWithoutLegacyStretchBehaviour = shouldDiffLayout; } -static void YGVLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { - const YGConfigRef logConfig = config != nullptr ? config : YGConfigGetDefault(); +static void YGVLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { + const YGConfigRef logConfig = + config != nullptr ? config : YGConfigGetDefault(); logConfig->logger(logConfig, node, level, format, args); if (level == YGLogLevelFatal) { @@ -3963,14 +4130,18 @@ static void YGVLog(const YGConfigRef config, } } -void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...) { +void YGLogWithConfig( + const YGConfigRef config, + YGLogLevel level, + const char* format, + ...) { va_list args; va_start(args, format); YGVLog(config, nullptr, level, format, args); va_end(args); } -void YGLog(const YGNodeRef node, YGLogLevel level, const char *format, ...) { +void YGLog(const YGNodeRef node, YGLogLevel level, const char* format, ...) { va_list args; va_start(args, format); YGVLog( @@ -3978,32 +4149,40 @@ void YGLog(const YGNodeRef node, YGLogLevel level, const char *format, ...) { va_end(args); } -void YGAssert(const bool condition, const char *message) { +void YGAssert(const bool condition, const char* message) { if (!condition) { YGLog(nullptr, YGLogLevelFatal, "%s\n", message); } } -void YGAssertWithNode(const YGNodeRef node, const bool condition, const char *message) { +void YGAssertWithNode( + const YGNodeRef node, + const bool condition, + const char* message) { if (!condition) { YGLog(node, YGLogLevelFatal, "%s\n", message); } } -void YGAssertWithConfig(const YGConfigRef config, const bool condition, const char *message) { +void YGAssertWithConfig( + const YGConfigRef config, + const bool condition, + const char* message) { if (!condition) { YGLogWithConfig(config, YGLogLevelFatal, "%s\n", message); } } -void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature, - const bool enabled) { +void YGConfigSetExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature, + const bool enabled) { config->experimentalFeatures[feature] = enabled; } -inline bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature) { +inline bool YGConfigIsExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature) { return config->experimentalFeatures[feature]; } @@ -4011,8 +4190,9 @@ void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled) { config->useWebDefaults = enabled; } -void YGConfigSetUseLegacyStretchBehaviour(const YGConfigRef config, - const bool useLegacyStretchBehaviour) { +void YGConfigSetUseLegacyStretchBehaviour( + const YGConfigRef config, + const bool useLegacyStretchBehaviour) { config->useLegacyStretchBehaviour = useLegacyStretchBehaviour; } @@ -4020,26 +4200,32 @@ bool YGConfigGetUseWebDefaults(const YGConfigRef config) { return config->useWebDefaults; } -void YGConfigSetContext(const YGConfigRef config, void *context) { +void YGConfigSetContext(const YGConfigRef config, void* context) { config->context = context; } -void *YGConfigGetContext(const YGConfigRef config) { +void* YGConfigGetContext(const YGConfigRef config) { return config->context; } -void YGConfigSetCloneNodeFunc(const YGConfigRef config, const YGCloneNodeFunc callback) { +void YGConfigSetCloneNodeFunc( + const YGConfigRef config, + const YGCloneNodeFunc callback) { config->cloneNodeCallback = callback; } -static void YGTraverseChildrenPreOrder(const YGVector& children, const std::function& f) { +static void YGTraverseChildrenPreOrder( + const YGVector& children, + const std::function& f) { for (YGNodeRef node : children) { f(node); YGTraverseChildrenPreOrder(node->getChildren(), f); } } -void YGTraversePreOrder(YGNodeRef const node, std::function&& f) { +void YGTraversePreOrder( + YGNodeRef const node, + std::function&& f) { if (!node) { return; } diff --git a/yoga/Yoga.h b/yoga/Yoga.h index a9fc89d7..fee2e328 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -45,23 +45,26 @@ typedef struct YGValue { extern const YGValue YGValueUndefined; extern const YGValue YGValueAuto; -typedef struct YGConfig *YGConfigRef; +typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; -typedef YGSize (*YGMeasureFunc)(YGNodeRef node, - float width, - YGMeasureMode widthMode, - float height, - YGMeasureMode heightMode); -typedef float (*YGBaselineFunc)(YGNodeRef node, const float width, const float height); +typedef YGSize (*YGMeasureFunc)( + YGNodeRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode); +typedef float ( + *YGBaselineFunc)(YGNodeRef node, const float width, const float height); typedef void (*YGDirtiedFunc)(YGNodeRef node); typedef void (*YGPrintFunc)(YGNodeRef node); -typedef int (*YGLogger)(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args); +typedef int (*YGLogger)( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args); typedef YGNodeRef ( *YGCloneNodeFunc)(YGNodeRef oldNode, YGNodeRef owner, int childIndex); @@ -74,9 +77,10 @@ WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node); WIN_EXPORT void YGNodeReset(const YGNodeRef node); WIN_EXPORT int32_t YGNodeGetInstanceCount(void); -WIN_EXPORT void YGNodeInsertChild(const YGNodeRef node, - const YGNodeRef child, - const uint32_t index); +WIN_EXPORT void YGNodeInsertChild( + const YGNodeRef node, + const YGNodeRef child, + const uint32_t index); // This function inserts the child YGNodeRef as a children of the node received // by parameter and set the Owner of the child object to null. This function is @@ -99,10 +103,11 @@ WIN_EXPORT void YGNodeSetChildren( const YGNodeRef children[], const uint32_t count); -WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection); +WIN_EXPORT void YGNodeCalculateLayout( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection); // Mark a node as dirty. Only valid for nodes with a custom measure function // set. @@ -112,70 +117,78 @@ WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node, // marking manually. WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node); -// This function marks the current node and all its descendants as dirty. This function is added to test yoga benchmarks. -// This function is not expected to be used in production as calling `YGCalculateLayout` will cause the recalculation of each and every node. +// This function marks the current node and all its descendants as dirty. This +// function is added to test yoga benchmarks. This function is not expected to +// be used in production as calling `YGCalculateLayout` will cause the +// recalculation of each and every node. WIN_EXPORT void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node); WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options); WIN_EXPORT bool YGFloatIsUndefined(const float value); -WIN_EXPORT bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, - const float width, - const YGMeasureMode heightMode, - const float height, - const YGMeasureMode lastWidthMode, - const float lastWidth, - const YGMeasureMode lastHeightMode, - const float lastHeight, - const float lastComputedWidth, - const float lastComputedHeight, - const float marginRow, - const float marginColumn, - const YGConfigRef config); +WIN_EXPORT bool YGNodeCanUseCachedMeasurement( + const YGMeasureMode widthMode, + const float width, + const YGMeasureMode heightMode, + const float height, + const YGMeasureMode lastWidthMode, + const float lastWidth, + const YGMeasureMode lastHeightMode, + const float lastHeight, + const float lastComputedWidth, + const float lastComputedHeight, + const float marginRow, + const float marginColumn, + const YGConfigRef config); -WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode); +WIN_EXPORT void YGNodeCopyStyle( + const YGNodeRef dstNode, + const YGNodeRef srcNode); #define YG_NODE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeSet##name(const YGNodeRef node, type paramName); \ WIN_EXPORT type YGNodeGet##name(const YGNodeRef node); -#define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const type paramName); \ +#define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); -#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, const float paramName); \ +#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const float paramName); \ + WIN_EXPORT void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const float paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); #define YG_NODE_STYLE_PROPERTY_UNIT_AUTO(type, name, paramName) \ YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node); -#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ - const YGEdge edge, \ - const type paramName); \ +#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const YGEdge edge, const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ - const YGEdge edge, \ - const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, \ - const YGEdge edge, \ - const float paramName); \ - WIN_EXPORT WIN_STRUCT(type) YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const YGEdge edge, const float paramName); \ + WIN_EXPORT void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const YGEdge edge, const float paramName); \ + WIN_EXPORT WIN_STRUCT(type) \ + YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \ - WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge); + WIN_EXPORT void YGNodeStyleSet##name##Auto( \ + const YGNodeRef node, const YGEdge edge); #define YG_NODE_LAYOUT_PROPERTY(type, name) \ WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); #define YG_NODE_LAYOUT_EDGE_PROPERTY(type, name) \ - WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge); + WIN_EXPORT type YGNodeLayoutGet##name( \ + const YGNodeRef node, const YGEdge edge); void* YGNodeGetContext(YGNodeRef node); void YGNodeSetContext(YGNodeRef node, void* context); @@ -224,16 +237,18 @@ YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node. -// Aspect ratio is encoded as a floating point value width/height. e.g. A value of 2 leads to a node -// with a width twice the size of its height while a value of 0.5 gives the opposite effect. +// Aspect ratio is encoded as a floating point value width/height. e.g. A value +// of 2 leads to a node with a width twice the size of its height while a value +// of 0.5 gives the opposite effect. // -// - On a node with a set width/height aspect ratio control the size of the unset dimension -// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if -// unset -// - On a node with a measure function aspect ratio works as though the measure function measures -// the flex basis -// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if -// unset +// - On a node with a set width/height aspect ratio control the size of the +// unset dimension +// - On a node with a set flex basis aspect ratio controls the size of the node +// in the cross axis if unset +// - On a node with a measure function aspect ratio works as though the measure +// function measures the flex basis +// - On a node with flex grow/shrink aspect ratio controls the size of the node +// in the cross axis if unset // - Aspect ratio takes min/max dimensions into account YG_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio); @@ -247,37 +262,48 @@ YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); YG_NODE_LAYOUT_PROPERTY(bool, HadOverflow); bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node); -// Get the computed values for these nodes after performing layout. If they were set using -// point values then the returned value will be the same as YGNodeStyleGetXXX. However if -// they were set using a percentage value then the returned value is the computed value used -// during layout. +// Get the computed values for these nodes after performing layout. If they were +// set using point values then the returned value will be the same as +// YGNodeStyleGetXXX. However if they were set using a percentage value then the +// returned value is the computed value used during layout. YG_NODE_LAYOUT_EDGE_PROPERTY(float, Margin); YG_NODE_LAYOUT_EDGE_PROPERTY(float, Border); YG_NODE_LAYOUT_EDGE_PROPERTY(float, Padding); WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger); -WIN_EXPORT void YGLog(const YGNodeRef node, YGLogLevel level, const char *message, ...); -WIN_EXPORT void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...); -WIN_EXPORT void YGAssert(const bool condition, const char *message); -WIN_EXPORT void YGAssertWithNode(const YGNodeRef node, const bool condition, const char *message); -WIN_EXPORT void YGAssertWithConfig(const YGConfigRef config, - const bool condition, - const char *message); +WIN_EXPORT void +YGLog(const YGNodeRef node, YGLogLevel level, const char* message, ...); +WIN_EXPORT void YGLogWithConfig( + const YGConfigRef config, + YGLogLevel level, + const char* format, + ...); +WIN_EXPORT void YGAssert(const bool condition, const char* message); +WIN_EXPORT void YGAssertWithNode( + const YGNodeRef node, + const bool condition, + const char* message); +WIN_EXPORT void YGAssertWithConfig( + const YGConfigRef config, + const bool condition, + const char* message); // Set this to number of pixels in 1 point to round calculation results // If you want to avoid rounding - set PointScaleFactor to 0 -WIN_EXPORT void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint); +WIN_EXPORT void YGConfigSetPointScaleFactor( + const YGConfigRef config, + const float pixelsInPoint); void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( const YGConfigRef config, const bool shouldDiffLayout); -// Yoga previously had an error where containers would take the maximum space possible instead of -// the minimum -// like they are supposed to. In practice this resulted in implicit behaviour similar to align-self: -// stretch; -// Because this was such a long-standing bug we must allow legacy users to switch back to this -// behaviour. -WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour(const YGConfigRef config, - const bool useLegacyStretchBehaviour); +// Yoga previously had an error where containers would take the maximum space +// possible instead of the minimum like they are supposed to. In practice this +// resulted in implicit behaviour similar to align-self: stretch; Because this +// was such a long-standing bug we must allow legacy users to switch back to +// this behaviour. +WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour( + const YGConfigRef config, + const bool useLegacyStretchBehaviour); // YGConfig WIN_EXPORT YGConfigRef YGConfigNew(void); @@ -285,25 +311,30 @@ WIN_EXPORT void YGConfigFree(const YGConfigRef config); WIN_EXPORT void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src); WIN_EXPORT int32_t YGConfigGetInstanceCount(void); -WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature, - const bool enabled); -WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature); +WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature, + const bool enabled); +WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature); // Using the web defaults is the prefered configuration for new projects. // Usage of non web defaults should be considered as legacy. -WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled); +WIN_EXPORT void YGConfigSetUseWebDefaults( + const YGConfigRef config, + const bool enabled); WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config); -WIN_EXPORT void YGConfigSetCloneNodeFunc(const YGConfigRef config, - const YGCloneNodeFunc callback); +WIN_EXPORT void YGConfigSetCloneNodeFunc( + const YGConfigRef config, + const YGCloneNodeFunc callback); // Export only for C# WIN_EXPORT YGConfigRef YGConfigGetDefault(void); -WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void *context); -WIN_EXPORT void *YGConfigGetContext(const YGConfigRef config); +WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void* context); +WIN_EXPORT void* YGConfigGetContext(const YGConfigRef config); WIN_EXPORT float YGRoundValueToPixelGrid( const float value, @@ -319,7 +350,9 @@ YG_EXTERN_C_END #include // Calls f on each node in the tree including the given node argument. -extern void YGTraversePreOrder(YGNodeRef const node, std::function&& f); +extern void YGTraversePreOrder( + YGNodeRef const node, + std::function&& f); extern void YGNodeSetChildren( YGNodeRef const owner, From 4be229059c75d01542be6af35f422debb5e07623 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:57:06 -0700 Subject: [PATCH 034/189] Yoga.h: inline function declaring macros Summary: @public Inlines macros used for declarations of `YGNodeStyle*` and `YGNodeLayout*` functions. Benefits easier grepping and code base navigation. Reviewed By: astreet Differential Revision: D8868168 fbshipit-source-id: d6b1b70981a59a2214dc7d166435a1d1a844e1b7 --- yoga/Yoga.h | 255 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 174 insertions(+), 81 deletions(-) diff --git a/yoga/Yoga.h b/yoga/Yoga.h index fee2e328..d6b12d29 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -146,50 +146,6 @@ WIN_EXPORT void YGNodeCopyStyle( const YGNodeRef dstNode, const YGNodeRef srcNode); -#define YG_NODE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeSet##name(const YGNodeRef node, type paramName); \ - WIN_EXPORT type YGNodeGet##name(const YGNodeRef node); - -#define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const type paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); - -#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const float paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); - -#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO(type, name, paramName) \ - YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node); - -#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const YGEdge edge, const type paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); - -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const YGEdge edge, const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const YGEdge edge, const float paramName); \ - WIN_EXPORT WIN_STRUCT(type) \ - YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); - -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \ - WIN_EXPORT void YGNodeStyleSet##name##Auto( \ - const YGNodeRef node, const YGEdge edge); - -#define YG_NODE_LAYOUT_PROPERTY(type, name) \ - WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); - -#define YG_NODE_LAYOUT_EDGE_PROPERTY(type, name) \ - WIN_EXPORT type YGNodeLayoutGet##name( \ - const YGNodeRef node, const YGEdge edge); - void* YGNodeGetContext(YGNodeRef node); void YGNodeSetContext(YGNodeRef node, void* context); YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node); @@ -207,33 +163,165 @@ void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType); bool YGNodeIsDirty(YGNodeRef node); bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node); -YG_NODE_STYLE_PROPERTY(YGDirection, Direction, direction); -YG_NODE_STYLE_PROPERTY(YGFlexDirection, FlexDirection, flexDirection); -YG_NODE_STYLE_PROPERTY(YGJustify, JustifyContent, justifyContent); -YG_NODE_STYLE_PROPERTY(YGAlign, AlignContent, alignContent); -YG_NODE_STYLE_PROPERTY(YGAlign, AlignItems, alignItems); -YG_NODE_STYLE_PROPERTY(YGAlign, AlignSelf, alignSelf); -YG_NODE_STYLE_PROPERTY(YGPositionType, PositionType, positionType); -YG_NODE_STYLE_PROPERTY(YGWrap, FlexWrap, flexWrap); -YG_NODE_STYLE_PROPERTY(YGOverflow, Overflow, overflow); -YG_NODE_STYLE_PROPERTY(YGDisplay, Display, display); -YG_NODE_STYLE_PROPERTY(float, Flex, flex); -YG_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow); -YG_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, FlexBasis, flexBasis); +WIN_EXPORT void YGNodeStyleSetDirection( + const YGNodeRef node, + const YGDirection direction); +WIN_EXPORT YGDirection YGNodeStyleGetDirection(const YGNodeRef node); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Position, position); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Margin, margin); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(YGValue, Margin); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Padding, padding); -YG_NODE_STYLE_EDGE_PROPERTY(float, Border, border); +WIN_EXPORT void YGNodeStyleSetFlexDirection( + const YGNodeRef node, + const YGFlexDirection flexDirection); +WIN_EXPORT YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Width, width); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Height, height); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinWidth, minWidth); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinHeight, minHeight); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxWidth, maxWidth); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); +WIN_EXPORT void YGNodeStyleSetJustifyContent( + const YGNodeRef node, + const YGJustify justifyContent); +WIN_EXPORT YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetAlignContent( + const YGNodeRef node, + const YGAlign alignContent); +WIN_EXPORT YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetAlignItems( + const YGNodeRef node, + const YGAlign alignItems); +WIN_EXPORT YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetAlignSelf( + const YGNodeRef node, + const YGAlign alignSelf); +WIN_EXPORT YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetPositionType( + const YGNodeRef node, + const YGPositionType positionType); +WIN_EXPORT YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexWrap( + const YGNodeRef node, + const YGWrap flexWrap); +WIN_EXPORT YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetOverflow( + const YGNodeRef node, + const YGOverflow overflow); +WIN_EXPORT YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetDisplay( + const YGNodeRef node, + const YGDisplay display); +WIN_EXPORT YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlex(const YGNodeRef node, const float flex); +WIN_EXPORT float YGNodeStyleGetFlex(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexGrow( + const YGNodeRef node, + const float flexGrow); +WIN_EXPORT float YGNodeStyleGetFlexGrow(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexShrink( + const YGNodeRef node, + const float flexShrink); +WIN_EXPORT float YGNodeStyleGetFlexShrink(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexBasis( + const YGNodeRef node, + const float flexBasis); +WIN_EXPORT void YGNodeStyleSetFlexBasisPercent( + const YGNodeRef node, + const float flexBasis); +WIN_EXPORT void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node); +WIN_EXPORT YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetPosition( + const YGNodeRef node, + const YGEdge edge, + const float position); +WIN_EXPORT void YGNodeStyleSetPositionPercent( + const YGNodeRef node, + const YGEdge edge, + const float position); +WIN_EXPORT WIN_STRUCT(YGValue) + YGNodeStyleGetPosition(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetMargin( + const YGNodeRef node, + const YGEdge edge, + const float margin); +WIN_EXPORT void YGNodeStyleSetMarginPercent( + const YGNodeRef node, + const YGEdge edge, + const float margin); +WIN_EXPORT void YGNodeStyleSetMarginAuto( + const YGNodeRef node, + const YGEdge edge); +WIN_EXPORT YGValue +YGNodeStyleGetMargin(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetPadding( + const YGNodeRef node, + const YGEdge edge, + const float padding); +WIN_EXPORT void YGNodeStyleSetPaddingPercent( + const YGNodeRef node, + const YGEdge edge, + const float padding); +WIN_EXPORT YGValue +YGNodeStyleGetPadding(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetBorder( + const YGNodeRef node, + const YGEdge edge, + const float border); +WIN_EXPORT float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetWidth(const YGNodeRef node, const float width); +WIN_EXPORT void YGNodeStyleSetWidthPercent( + const YGNodeRef node, + const float width); +WIN_EXPORT void YGNodeStyleSetWidthAuto(const YGNodeRef node); +WIN_EXPORT YGValue YGNodeStyleGetWidth(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetHeight(const YGNodeRef node, const float height); +WIN_EXPORT void YGNodeStyleSetHeightPercent( + const YGNodeRef node, + const float height); +WIN_EXPORT void YGNodeStyleSetHeightAuto(const YGNodeRef node); +WIN_EXPORT YGValue YGNodeStyleGetHeight(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMinWidth( + const YGNodeRef node, + const float minWidth); +WIN_EXPORT void YGNodeStyleSetMinWidthPercent( + const YGNodeRef node, + const float minWidth); +WIN_EXPORT YGValue YGNodeStyleGetMinWidth(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMinHeight( + const YGNodeRef node, + const float minHeight); +WIN_EXPORT void YGNodeStyleSetMinHeightPercent( + const YGNodeRef node, + const float minHeight); +WIN_EXPORT YGValue YGNodeStyleGetMinHeight(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMaxWidth( + const YGNodeRef node, + const float maxWidth); +WIN_EXPORT void YGNodeStyleSetMaxWidthPercent( + const YGNodeRef node, + const float maxWidth); +WIN_EXPORT YGValue YGNodeStyleGetMaxWidth(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMaxHeight( + const YGNodeRef node, + const float maxHeight); +WIN_EXPORT void YGNodeStyleSetMaxHeightPercent( + const YGNodeRef node, + const float maxHeight); +WIN_EXPORT YGValue YGNodeStyleGetMaxHeight(const YGNodeRef node); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node. @@ -250,25 +338,30 @@ YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); // - On a node with flex grow/shrink aspect ratio controls the size of the node // in the cross axis if unset // - Aspect ratio takes min/max dimensions into account -YG_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio); +WIN_EXPORT void YGNodeStyleSetAspectRatio( + const YGNodeRef node, + const float aspectRatio); +WIN_EXPORT float YGNodeStyleGetAspectRatio(const YGNodeRef node); -YG_NODE_LAYOUT_PROPERTY(float, Left); -YG_NODE_LAYOUT_PROPERTY(float, Top); -YG_NODE_LAYOUT_PROPERTY(float, Right); -YG_NODE_LAYOUT_PROPERTY(float, Bottom); -YG_NODE_LAYOUT_PROPERTY(float, Width); -YG_NODE_LAYOUT_PROPERTY(float, Height); -YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); -YG_NODE_LAYOUT_PROPERTY(bool, HadOverflow); +WIN_EXPORT float YGNodeLayoutGetLeft(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetTop(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetRight(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetBottom(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetWidth(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetHeight(const YGNodeRef node); +WIN_EXPORT YGDirection YGNodeLayoutGetDirection(const YGNodeRef node); +WIN_EXPORT bool YGNodeLayoutGetHadOverflow(const YGNodeRef node); bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node); // Get the computed values for these nodes after performing layout. If they were // set using point values then the returned value will be the same as // YGNodeStyleGetXXX. However if they were set using a percentage value then the // returned value is the computed value used during layout. -YG_NODE_LAYOUT_EDGE_PROPERTY(float, Margin); -YG_NODE_LAYOUT_EDGE_PROPERTY(float, Border); -YG_NODE_LAYOUT_EDGE_PROPERTY(float, Padding); +WIN_EXPORT float YGNodeLayoutGetMargin(const YGNodeRef node, const YGEdge edge); +WIN_EXPORT float YGNodeLayoutGetBorder(const YGNodeRef node, const YGEdge edge); +WIN_EXPORT float YGNodeLayoutGetPadding( + const YGNodeRef node, + const YGEdge edge); WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger); WIN_EXPORT void From 4caed8feb5189fdcae9c9a7f8b3e3c995093f708 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:57:08 -0700 Subject: [PATCH 035/189] Replace `YG_NODE_STYLE_PROPERTY_IMPL` macro with template Summary: @public Replacing the `YG_NODE_STYLE_PROPERTY_IMPL` macro with template code, in order to make code easier to edit and grep. Reviewed By: astreet Differential Revision: D8868184 fbshipit-source-id: f52537376fa8d4dd53aa98bb43e93279699dbdd5 --- yoga/Yoga.cpp | 137 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 42 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index c9404dec..c9799c3c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -576,16 +576,24 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { : node->getStyle().flexShrink.getValue(); } -#define YG_NODE_STYLE_PROPERTY_SETTER_IMPL( \ - type, name, paramName, instanceName) \ - void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ - if (node->getStyle().instanceName != paramName) { \ - YGStyle style = node->getStyle(); \ - style.instanceName = paramName; \ - node->setStyle(style); \ - node->markDirtyAndPropogate(); \ - } \ +namespace { + +template +struct StyleProp { + static T get(YGNodeRef node) { + return node->getStyle().*P; } + static void set(YGNodeRef node, T newValue) { + if (node->getStyle().*P != newValue) { + YGStyle style = node->getStyle(); + style.*P = newValue; + node->setStyle(style); + node->markDirtyAndPropogate(); + } + } +}; + +} // namespace #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ type, name, paramName, instanceName) \ @@ -661,13 +669,6 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { } \ } -#define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \ - YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \ - \ - type YGNodeStyleGet##name(const YGNodeRef node) { \ - return node->getStyle().instanceName; \ - } - #define YG_NODE_STYLE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName) \ YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ float, name, paramName, instanceName) \ @@ -778,33 +779,85 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { return node->getLayout().instanceName[edge]; \ } -// YG_NODE_PROPERTY_IMPL(void *, Context, context, context); -// YG_NODE_PROPERTY_IMPL(YGPrintFunc, PrintFunc, printFunc, print); -// YG_NODE_PROPERTY_IMPL(bool, HasNewLayout, hasNewLayout, hasNewLayout); -// YG_NODE_PROPERTY_IMPL(YGNodeType, NodeType, nodeType, nodeType); +void YGNodeStyleSetDirection( + const YGNodeRef node, + const YGDirection direction) { + StyleProp::set(node, direction); +} +YGDirection YGNodeStyleGetDirection(const YGNodeRef node) { + return StyleProp::get(node); +} -YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction); -YG_NODE_STYLE_PROPERTY_IMPL( - YGFlexDirection, - FlexDirection, - flexDirection, - flexDirection); -YG_NODE_STYLE_PROPERTY_IMPL( - YGJustify, - JustifyContent, - justifyContent, - justifyContent); -YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent); -YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems); -YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf); -YG_NODE_STYLE_PROPERTY_IMPL( - YGPositionType, - PositionType, - positionType, - positionType); -YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap); -YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow); -YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display); +void YGNodeStyleSetFlexDirection( + const YGNodeRef node, + const YGFlexDirection flexDirection) { + StyleProp::set(node, flexDirection); +} +YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetJustifyContent( + const YGNodeRef node, + const YGJustify justifyContent) { + StyleProp::set(node, justifyContent); +} +YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetAlignContent( + const YGNodeRef node, + const YGAlign alignContent) { + StyleProp::set(node, alignContent); +} +YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { + StyleProp::set(node, alignItems); +} +YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { + StyleProp::set(node, alignSelf); +} +YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetPositionType( + const YGNodeRef node, + const YGPositionType positionType) { + StyleProp::set(node, positionType); +} +YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { + StyleProp::set(node, flexWrap); +} +YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { + StyleProp::set(node, overflow); +} +YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { + StyleProp::set(node, display); +} +YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) { + return StyleProp::get(node); +} // TODO(T26792433): Change the API to accept YGFloatOptional. void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { From eaaf0fdfe29d47d76135222d3500d0426992b149 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 23 Jul 2018 13:24:21 -0700 Subject: [PATCH 036/189] Implementation of `operator==` for YGValue Summary: @public It's very useful sometimes for product code to compare `YGValue`s (e.g. in Fabric). Reviewed By: priteshrnandgaonkar Differential Revision: D8937594 fbshipit-source-id: b93e1ab4a6419ada6746f233b587e8c9cb32c6d4 --- yoga/Yoga.cpp | 13 +++++++++++++ yoga/Yoga.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index c9799c3c..b9a5f781 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -48,6 +48,19 @@ const YGValue YGValueZero = {0, YGUnitPoint}; const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; +bool operator==(const YGValue& lhs, const YGValue& rhs) { + if ((lhs.unit == YGUnitUndefined && rhs.unit == YGUnitUndefined) || + (lhs.unit == YGUnitAuto && rhs.unit == YGUnitAuto)) { + return true; + } + + return lhs.unit == rhs.unit && lhs.value == rhs.value; +} + +bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} + #ifdef ANDROID #include static int YGAndroidLog( diff --git a/yoga/Yoga.h b/yoga/Yoga.h index d6b12d29..5bcbe2ab 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -45,6 +45,13 @@ typedef struct YGValue { extern const YGValue YGValueUndefined; extern const YGValue YGValueAuto; +#ifdef __cplusplus + +extern bool operator==(const YGValue& lhs, const YGValue& rhs); +extern bool operator!=(const YGValue& lhs, const YGValue& rhs); + +#endif + typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; From 7b87ded288dbdb5c44a7cb52ef9643a58ce76623 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 23 Jul 2018 14:50:46 -0700 Subject: [PATCH 037/189] Add tests for style properties Summary: @public The existing test suite does not check every single style property settable in Java for defaults, reads, and effect on layout. Here, we add these test, in order to make evolving the Java/C++ bridge as safe as possible. Reviewed By: pasqualeanatriello Differential Revision: D8952470 fbshipit-source-id: a94933adff01c313b3f440eb5207d2cb6a54a85d --- .../yoga/YogaNodeStylePropertiesTest.java | 983 ++++++++++++++++++ 1 file changed, 983 insertions(+) create mode 100644 java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java diff --git a/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java b/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java new file mode 100644 index 00000000..8efcdd13 --- /dev/null +++ b/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java @@ -0,0 +1,983 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class YogaNodeStylePropertiesTest { + + private static final float UNDEFINED = YogaValue.UNDEFINED.value; + + @Test + public void testDirectionDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(node.getStyleDirection(), YogaDirection.INHERIT); + assertEquals(node.getLayoutDirection(), YogaDirection.INHERIT); + } + + @Test + public void testDirectionAssignment() { + final YogaNode node = new YogaNode(); + node.setDirection(YogaDirection.LTR); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(YogaDirection.LTR, node.getStyleDirection()); + assertEquals(YogaDirection.LTR, node.getLayoutDirection()); + } + + @Test + public void testDirectionAffectsLayout() { + final YogaNode node = + style().direction(YogaDirection.RTL).width(200).children(style().widthPercent(40)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(120, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testFlexDirectionDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaFlexDirection.COLUMN, node.getFlexDirection()); + } + + @Test + public void testFlexDirectionAssignment() { + final YogaNode node = style().flexDirection(YogaFlexDirection.COLUMN_REVERSE).node(); + + assertEquals(YogaFlexDirection.COLUMN_REVERSE, node.getFlexDirection()); + } + + @Test + public void testFlexDirectionAffectsLayout() { + final YogaNode node = + style() + .flexDirection(YogaFlexDirection.ROW_REVERSE) + .width(200) + .children(style().widthPercent(40)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(120, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testJustifyContentDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaJustify.FLEX_START, node.getJustifyContent()); + } + + @Test + public void testJustifyContentAssignment() { + final YogaNode node = new YogaNode(); + node.setJustifyContent(YogaJustify.SPACE_EVENLY); + + assertEquals(YogaJustify.SPACE_EVENLY, node.getJustifyContent()); + } + + @Test + public void testJustifyContentAffectsLayout() { + final YogaNode node = + style() + .justifyContent(YogaJustify.CENTER) + .height(200) + .children(style().heightPercent(40)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(60, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testAlignItemsDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaAlign.STRETCH, node.getAlignItems()); + } + + @Test + public void testAlignItemsAssignment() { + final YogaNode node = new YogaNode(); + node.setAlignItems(YogaAlign.SPACE_AROUND); + + assertEquals(YogaAlign.SPACE_AROUND, node.getAlignItems()); + } + + @Test + public void testAlignItemsAffectsLayout() { + final YogaNode node = + style().alignItems(YogaAlign.CENTER).height(200).children(style().widthPercent(40)).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(60, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testAlignSelfDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaAlign.AUTO, node.getAlignSelf()); + } + + @Test + public void testAlignSelfAssignment() { + final YogaNode node = new YogaNode(); + node.setAlignSelf(YogaAlign.FLEX_END); + + assertEquals(YogaAlign.FLEX_END, node.getAlignSelf()); + } + + @Test + public void testAlignSelfAffectsLayout() { + final YogaNode node = + style().height(200).children(style().alignSelf(YogaAlign.CENTER).widthPercent(40)).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(60, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testAlignContentDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaAlign.FLEX_START, node.getAlignContent()); + } + + @Test + public void testAlignContentAssignment() { + final YogaNode node = new YogaNode(); + node.setAlignContent(YogaAlign.BASELINE); + + assertEquals(YogaAlign.BASELINE, node.getAlignContent()); + } + + @Test + public void testAlignContentAffectsLayout() { + final YogaNode node = + style() + .alignContent(YogaAlign.SPACE_AROUND) + .flexWrap(YogaWrap.WRAP) + .height(200) + .width(200) + .children( + style().widthPercent(20).heightPercent(60), + style().widthPercent(20).heightPercent(60)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(30, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testPositionTypeDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaPositionType.RELATIVE, node.getPositionType()); + } + + @Test + public void testPositionTypeAssignment() { + final YogaNode node = new YogaNode(); + node.setPositionType(YogaPositionType.ABSOLUTE); + + assertEquals(YogaPositionType.ABSOLUTE, node.getPositionType()); + } + + @Test + public void testPositionTypeAffectsLayout() { + final YogaNode node = + style() + .height(200) + .children( + style().height(100), style().height(100).positionType(YogaPositionType.ABSOLUTE)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(0, node.getChildAt(1).getLayoutY(), 0); + } + + @Test + public void testWrapAffectsLayout() { + final YogaNode node = + style() + .width(200) + .height(200) + .flexWrap(YogaWrap.WRAP_REVERSE) + .children(style().width(10).heightPercent(60), style().heightPercent(60)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(190, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testOverflowDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaOverflow.VISIBLE, node.getOverflow()); + } + + @Test + public void testOverflowAssignment() { + final YogaNode node = new YogaNode(); + node.setOverflow(YogaOverflow.SCROLL); + + assertEquals(YogaOverflow.SCROLL, node.getOverflow()); + } + + // TODO add testOverflowAffectsLayout() + + @Test + public void testDisplayDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaDisplay.FLEX, node.getDisplay()); + } + + @Test + public void testDisplayAssignment() { + final YogaNode node = new YogaNode(); + node.setDisplay(YogaDisplay.NONE); + + assertEquals(YogaDisplay.NONE, node.getDisplay()); + } + + @Test + public void testDisplayAffectsLayout() { + final YogaNode node = + style().children(style().flexGrow(1).display(YogaDisplay.NONE), style().flexGrow(1)).node(); + node.calculateLayout(200, 200); + + assertEquals(200, node.getChildAt(1).getLayoutHeight(), 0); + } + + @Test + public void testFlexAffectsLayoutGrowing() { + final YogaNode node = style().height(200).children(style().height(100).flex(1.25f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(200, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexAffectsLayoutShrinking() { + final YogaNode node = style().height(200).children(style().height(300).flex(1.25f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(200, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexGrowDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(0, node.getFlexGrow(), 0); + } + + @Test + public void testFlexGrowAssignment() { + final YogaNode node = new YogaNode(); + node.setFlexGrow(2.5f); + + assertEquals(2.5f, node.getFlexGrow(), 0); + } + + @Test + public void testFlexGrowAffectsLayout() { + final YogaNode node = + style().height(200).children(style().height(50).flexGrow(1), style().height(50)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(150, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexShrinkDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(0, node.getFlexShrink(), 0); + } + + @Test + public void testFlexShrinkAssignment() { + final YogaNode node = new YogaNode(); + node.setFlexShrink(2.5f); + + assertEquals(2.5f, node.getFlexShrink(), 0); + } + + @Test + public void testFlexShrinkAffectsLayout() { + final YogaNode node = + style().height(200).children(style().height(150).flexShrink(1), style().height(150)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(50, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexBasisDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.AUTO, node.getFlexBasis()); + } + + @Test + public void testFlexBasisAssignment() { + final YogaNode node = new YogaNode(); + node.setFlexBasis(50); + assertEquals(new YogaValue(50, YogaUnit.POINT), node.getFlexBasis()); + + node.setFlexBasisPercent(20); + assertEquals(new YogaValue(20, YogaUnit.PERCENT), node.getFlexBasis()); + + node.setFlexBasisAuto(); + assertEquals(YogaValue.AUTO, node.getFlexBasis()); + } + + @Test + public void testFlexBasisAffectsLayout() { + final YogaNode node = + style() + .height(200) + .children(style().flexBasis(150).flexShrink(1), style().flexBasis(150).flexShrink(1)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(100, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexBasisPercentAffectsLayout() { + final YogaNode node = + style() + .height(200) + .children(style().flexBasisPercent(60), style().flexBasisPercent(40)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(80, node.getChildAt(1).getLayoutHeight(), 0); + } + + @Test + public void testMarginDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(YogaValue.UNDEFINED, node.getMargin(edge)); + } + } + + @Test + public void testMarginAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setMargin(edge, 25); + assertEquals(new YogaValue(25, YogaUnit.POINT), node.getMargin(edge)); + + node.setMarginPercent(edge, 5); + assertEquals(new YogaValue(5, YogaUnit.PERCENT), node.getMargin(edge)); + + node.setMarginAuto(edge); + assertEquals(YogaValue.AUTO, node.getMargin(edge)); + } + } + + @Test + public void testMarginPointAffectsLayout() { + final YogaNode node = style().margin(YogaEdge.TOP, 42).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(42, node.getLayoutY(), 0); + } + + @Test + public void testMarginPercentAffectsLayout() { + final YogaNode node = + style().height(200).children(style().flexGrow(1).marginPercent(YogaEdge.TOP, 20)).node(); + node.calculateLayout(200, 200); + + assertEquals(40, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testMarginAutoAffectsLayout() { + final YogaNode node = + style() + .width(200) + .flexDirection(YogaFlexDirection.ROW) + .children(style().marginAuto(YogaEdge.LEFT).marginAuto(YogaEdge.RIGHT).width(100)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(50, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testPaddingDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(YogaValue.UNDEFINED, node.getPadding(edge)); + } + } + + @Test + public void testPaddingAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setPadding(edge, 25); + assertEquals(new YogaValue(25, YogaUnit.POINT), node.getPadding(edge)); + + node.setPaddingPercent(edge, 5); + assertEquals(new YogaValue(5, YogaUnit.PERCENT), node.getPadding(edge)); + } + } + + @Test + public void testPaddingPointAffectsLayout() { + final YogaNode node = style().padding(YogaEdge.TOP, 42).children(style()).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(42, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testPaddingPercentAffectsLayout() { + final YogaNode node = + style().height(200).paddingPercent(YogaEdge.TOP, 20).children(style().flexGrow(1)).node(); + node.calculateLayout(200, 200); + + assertEquals(40, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testBorderDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(UNDEFINED, node.getBorder(edge), 0); + } + } + + @Test + public void testBorderAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setBorder(edge, 2.5f); + assertEquals(2.5f, node.getBorder(edge), 0); + } + } + + @Test + public void testBorderAffectsLayout() { + final YogaNode node = style().border(YogaEdge.TOP, 42).children(style()).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(42, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testPositionDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(YogaValue.UNDEFINED, node.getPosition(edge)); + } + } + + @Test + public void testPositionAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setPosition(edge, 25); + assertEquals(new YogaValue(25, YogaUnit.POINT), node.getPosition(edge)); + + node.setPositionPercent(edge, 5); + assertEquals(new YogaValue(5, YogaUnit.PERCENT), node.getPosition(edge)); + } + } + + @Test + public void testPositionAffectsLayout() { + final YogaNode node = + style() + .height(100) + .children( + style() + .positionType(YogaPositionType.ABSOLUTE) + .position(YogaEdge.TOP, 11) + .position(YogaEdge.BOTTOM, 22)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(67, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testPositionPercentAffectsLayout() { + final YogaNode node = + style() + .width(100) + .children( + style() + .positionType(YogaPositionType.ABSOLUTE) + .positionPercent(YogaEdge.LEFT, 11) + .positionPercent(YogaEdge.RIGHT, 22)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(67, node.getChildAt(0).getLayoutWidth(), 0); + } + + @Test + public void testWidthDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.AUTO, node.getWidth()); + } + + @Test + public void testWidthAssignment() { + final YogaNode node = new YogaNode(); + node.setWidth(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getWidth()); + + node.setWidthPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getWidth()); + } + + @Test + public void testWidthAffectsLayout() { + final YogaNode node = style().width(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutWidth(), 0); + } + + @Test + public void testWidthPercentAffectsLayout() { + final YogaNode node = style().widthPercent(75).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(150, node.getLayoutWidth(), 0); + } + + // TODO: testWidthAutoAffectsLayout + + @Test + public void testHeightDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.AUTO, node.getHeight()); + } + + @Test + public void testHeightAssignment() { + final YogaNode node = new YogaNode(); + node.setHeight(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getHeight()); + + node.setHeightPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getHeight()); + } + + @Test + public void testHeightAffectsLayout() { + final YogaNode node = style().height(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutHeight(), 0); + } + + @Test + public void testHeightPercentAffectsLayout() { + final YogaNode node = style().heightPercent(75).node(); + node.calculateLayout(UNDEFINED, 200); + + assertEquals(150, node.getLayoutHeight(), 0); + } + + // TODO: testHeightAutoAffectsLayout + + @Test + public void testMinWidthDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMinWidth()); + } + + @Test + public void testMinWidthAssignment() { + final YogaNode node = new YogaNode(); + node.setMinWidth(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMinWidth()); + + node.setMinWidthPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMinWidth()); + } + + @Test + public void testMinWidthAffectsLayout() { + final YogaNode node = style().minWidth(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutWidth(), 0); + } + + @Test + public void testMinWidthPercentAffectsLayout() { + final YogaNode node = style().minWidthPercent(120).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(240, node.getLayoutWidth(), 0); + } + + @Test + public void testMinHeightDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMinHeight()); + } + + @Test + public void testMinHeightAssignment() { + final YogaNode node = new YogaNode(); + node.setMinHeight(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMinHeight()); + + node.setMinHeightPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMinHeight()); + } + + @Test + public void testMinHeightAffectsLayout() { + final YogaNode node = style().minHeight(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutHeight(), 0); + } + + @Test + public void testMinHeightPercentAffectsLayout() { + final YogaNode node = style().minHeightPercent(120).node(); + node.calculateLayout(UNDEFINED, 200); + + assertEquals(240, node.getLayoutHeight(), 0); + } + + @Test + public void testMaxWidthDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMaxWidth()); + } + + @Test + public void testMaxWidthAssignment() { + final YogaNode node = new YogaNode(); + node.setMaxWidth(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMaxWidth()); + + node.setMaxWidthPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMaxWidth()); + } + + @Test + public void testMaxWidthAffectsLayout() { + final YogaNode node = style().width(200).children(style().maxWidth(123)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getChildAt(0).getLayoutWidth(), 0); + } + + @Test + public void testMaxWidthPercentAffectsLayout() { + final YogaNode node = style().width(200).children(style().maxWidthPercent(80)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(160, node.getChildAt(0).getLayoutWidth(), 0); + } + + @Test + public void testMaxHeightDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMaxHeight()); + } + + @Test + public void testMaxHeightAssignment() { + final YogaNode node = new YogaNode(); + node.setMaxHeight(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMaxHeight()); + + node.setMaxHeightPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMaxHeight()); + } + + @Test + public void testMaxHeightAffectsLayout() { + final YogaNode node = + style() + .height(200) + .flexDirection(YogaFlexDirection.ROW) + .children(style().maxHeight(123)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testMaxHeightPercentAffectsLayout() { + final YogaNode node = + style() + .flexDirection(YogaFlexDirection.ROW) + .height(200) + .children(style().maxHeightPercent(80)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(160, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testAspectRatioDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(UNDEFINED, node.getAspectRatio(), 0); + } + + @Test + public void testAspectRatioAssignment() { + final YogaNode node = new YogaNode(); + node.setAspectRatio(2.75f); + + assertEquals(2.75f, node.getAspectRatio(), 0); + } + + @Test + public void aspectRatioAffectsLayoutWithGivenWidth() { + final YogaNode node = style().children(style().width(300).aspectRatio(1.5f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(200, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void aspectRatioAffectsLayoutWithGivenHeight() { + final YogaNode node = style().children(style().height(300).aspectRatio(1.5f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(450, node.getChildAt(0).getLayoutWidth(), 0); + } + + private static StyledNode style() { + return new StyledNode(); + } + + private static class StyledNode { + + private YogaNode mNode = new YogaNode(); + + YogaNode node() { + return mNode; + } + + StyledNode children(StyledNode... children) { + for (int i = mNode.getChildCount(); --i >= 0; ) { + mNode.removeChildAt(i); + } + for (int i = 0; i < children.length; i++) { + mNode.addChildAt(children[i].node(), i); + } + return this; + } + + StyledNode direction(YogaDirection direction) { + mNode.setDirection(direction); + return this; + } + + StyledNode width(float width) { + mNode.setWidth(width); + return this; + } + + StyledNode widthPercent(float width) { + mNode.setWidthPercent(width); + return this; + } + + StyledNode flexDirection(YogaFlexDirection direction) { + mNode.setFlexDirection(direction); + return this; + } + + StyledNode justifyContent(YogaJustify justify) { + mNode.setJustifyContent(justify); + return this; + } + + StyledNode height(float height) { + mNode.setHeight(height); + return this; + } + + StyledNode heightPercent(float height) { + mNode.setHeightPercent(height); + return this; + } + + StyledNode alignItems(YogaAlign align) { + mNode.setAlignItems(align); + return this; + } + + StyledNode alignSelf(YogaAlign align) { + mNode.setAlignSelf(align); + return this; + } + + StyledNode alignContent(YogaAlign align) { + mNode.setAlignContent(align); + return this; + } + + StyledNode flexWrap(YogaWrap wrap) { + mNode.setWrap(wrap); + return this; + } + + StyledNode positionType(YogaPositionType positionType) { + mNode.setPositionType(positionType); + return this; + } + + StyledNode overflow(YogaOverflow overflow) { + mNode.setOverflow(overflow); + return this; + } + + StyledNode flexShrink(float flexShrink) { + mNode.setFlexShrink(flexShrink); + return this; + } + + StyledNode display(YogaDisplay display) { + mNode.setDisplay(display); + return this; + } + + StyledNode flexGrow(float flexGrow) { + mNode.setFlexGrow(flexGrow); + return this; + } + + StyledNode flex(float flex) { + mNode.setFlex(flex); + return this; + } + + StyledNode flexBasis(float flexBasis) { + mNode.setFlexBasis(flexBasis); + return this; + } + + StyledNode flexBasisPercent(float flexBasis) { + mNode.setFlexBasisPercent(flexBasis); + return this; + } + + StyledNode margin(YogaEdge edge, float margin) { + mNode.setMargin(edge, margin); + return this; + } + + StyledNode marginPercent(YogaEdge edge, float margin) { + mNode.setMarginPercent(edge, margin); + return this; + } + + StyledNode marginAuto(YogaEdge edge) { + mNode.setMarginAuto(edge); + return this; + } + + StyledNode padding(YogaEdge edge, float padding) { + mNode.setPadding(edge, padding); + return this; + } + + StyledNode paddingPercent(YogaEdge edge, float padding) { + mNode.setPaddingPercent(edge, padding); + return this; + } + + StyledNode border(YogaEdge edge, float border) { + mNode.setBorder(edge, border); + return this; + } + + StyledNode position(YogaEdge edge, float position) { + mNode.setPosition(edge, position); + return this; + } + + StyledNode positionPercent(YogaEdge edge, float position) { + mNode.setPositionPercent(edge, position); + return this; + } + + StyledNode minWidth(float minWidth) { + mNode.setMinWidth(minWidth); + return this; + } + + StyledNode minWidthPercent(float minWidth) { + mNode.setMinWidthPercent(minWidth); + return this; + } + + StyledNode minHeight(float minHeight) { + mNode.setMinHeight(minHeight); + return this; + } + + StyledNode minHeightPercent(float minHeight) { + mNode.setMinHeightPercent(minHeight); + return this; + } + + StyledNode maxWidth(float maxWidth) { + mNode.setMaxWidth(maxWidth); + return this; + } + + StyledNode maxWidthPercent(float maxWidth) { + mNode.setMaxWidthPercent(maxWidth); + return this; + } + + StyledNode maxHeight(float maxHeight) { + mNode.setMaxHeight(maxHeight); + return this; + } + + StyledNode maxHeightPercent(float maxHeight) { + mNode.setMaxHeightPercent(maxHeight); + return this; + } + + StyledNode aspectRatio(float aspectRatio) { + mNode.setAspectRatio(aspectRatio); + return this; + } + } +} From 9fe20fd2fc457178949ce3f9366fef69d6c4a5f1 Mon Sep 17 00:00:00 2001 From: Nate Stedman Date: Tue, 24 Jul 2018 06:47:20 -0700 Subject: [PATCH 038/189] Also ban +new on YGLayout Summary: `-init` is marked unavailable, but `+new` does the same thing and is not. Reviewed By: dshahidehpour Differential Revision: D8957391 fbshipit-source-id: 42fcfe845db79726d8724efd9f6a4d37c19938ad --- YogaKit/Source/YGLayout.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/YogaKit/Source/YGLayout.h b/YogaKit/Source/YGLayout.h index 7b9d583a..3bfb1b89 100644 --- a/YogaKit/Source/YGLayout.h +++ b/YogaKit/Source/YGLayout.h @@ -33,6 +33,13 @@ typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) { - (instancetype)init __attribute__((unavailable("you are not meant to initialise YGLayout"))); +/** + Make default init unavailable, as it will not initialise YGNode which is + required for the setters and getters of YGLayout's properties to work properly. + */ ++ (instancetype)new + __attribute__((unavailable("you are not meant to initialise YGLayout"))); + /** The property that decides if we should include this view when calculating layout. Defaults to YES. From db5bc092aa5ad6104dfe01968ac0aca52fc5a63d Mon Sep 17 00:00:00 2001 From: Zhaojun Zhang Date: Fri, 27 Jul 2018 10:51:27 -0700 Subject: [PATCH 039/189] Remove clang compiler warnings for Android: -Wno-unused-parameter Summary: att Reviewed By: gkmhub Differential Revision: D8972835 fbshipit-source-id: c8b893eefec6ccb5d8506c959bcf5c3f43701e81 --- .../main/cpp/include/fb/fbjni/CoreClasses-inl.h | 12 ++++++++---- lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h | 12 +++++++----- lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h | 9 +++++---- .../main/cpp/include/fb/fbjni/References-inl.h | 17 +++++++++-------- .../cpp/include/fb/fbjni/Registration-inl.h | 14 ++++++++------ 5 files changed, 37 insertions(+), 27 deletions(-) diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h index 1e00441a..51131f84 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2015-present, Facebook, Inc. + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -509,6 +509,8 @@ class PinnedCriticalAlloc { T** elements, size_t* size, jboolean* isCopy) { + (void)start; + (void)length; const auto env = internal::getEnv(); *elements = static_cast(env->GetPrimitiveArrayCritical(array.get(), isCopy)); FACEBOOK_JNI_THROW_EXCEPTION_IF(!elements); @@ -520,6 +522,8 @@ class PinnedCriticalAlloc { jint start, jint size, jint mode) { + (void)start; + (void)size; const auto env = internal::getEnv(); env->ReleasePrimitiveArrayCritical(array.get(), elements, mode); } diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h b/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h index f020826c..143ec3b3 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2015-present, Facebook, Inc. + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -188,7 +188,9 @@ public: // particular java class) to be hoisted to a common function. If // mapException returns, then the std::exception will be translated // to Java. - static void mapException(const std::exception& ex) {} + static void mapException(const std::exception& ex) { + (void)ex; + } }; template diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h index ff4c016b..197dd2b1 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2015-present, Facebook, Inc. + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -53,6 +53,7 @@ struct ArgsArraySetter { template struct ArgsArraySetter { static void set(alias_ref::javaobject> array) { + (void)array; } }; diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h index 6bdc1815..99e152e8 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2015-present, Facebook, Inc. + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -182,10 +182,11 @@ inline base_owned_ref::base_owned_ref() noexcept : base_owned_ref(nullptr) {} -template -inline base_owned_ref::base_owned_ref(std::nullptr_t t) noexcept - : base_owned_ref(static_cast(nullptr)) -{} +template +inline base_owned_ref::base_owned_ref(std::nullptr_t array) noexcept + : base_owned_ref(static_cast(nullptr)) { + (void)array; +} template inline base_owned_ref::base_owned_ref(const base_owned_ref& other) diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h index e2817473..f8203cad 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2015-present, Facebook, Inc. + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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" @@ -106,8 +106,10 @@ inline NativeMethodWrapper* exceptionWrapJNIMethod(R (*)(alias_ref, Args... a // registration wrappers for non-static methods, with autoconvertion of arguments. -template -inline NativeMethodWrapper* exceptionWrapJNIMethod(void (C::*method0)(Args... args)) { +template +inline NativeMethodWrapper* exceptionWrapJNIMethod( + void (C::*method0)(Args... args)) { + (void)method0; struct funcWrapper { JNI_ENTRY_POINT static void call(JNIEnv* env, jobject obj, typename Convert::type>::jniType... args) { From 006f6460a9d5b785654f122b5b05937149cc0729 Mon Sep 17 00:00:00 2001 From: Amir Shalem Date: Sun, 29 Jul 2018 14:02:27 -0700 Subject: [PATCH 040/189] Deallocate the YogaConfig memory with correct method Summary: We've mistakenly used `free()` to free the memory, where `delete` should have been used Reviewed By: davidaurelio Differential Revision: D9042347 fbshipit-source-id: e15cec0f498409066521a6de1e3fe4b7404ec46c --- yoga/Yoga.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index b9a5f781..a05ff852 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -369,7 +369,7 @@ YGConfigRef YGConfigNew(void) { } void YGConfigFree(const YGConfigRef config) { - free(config); + delete config; gConfigInstanceCount--; } From b1821ab4cd2e6377cb237d24c75a624fa95ec414 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 30 Jul 2018 09:30:50 -0700 Subject: [PATCH 041/189] move property storage into sub-object Summary: Here we introduce an abstraction over node property storage, in order to experiment with different approaches for Java/C integration. - interface `YogaNodeProperties` as abstraction - current JNI code factored into `YogaNodePropertiesJNI.java` - `YogaNode` delegates all calls, no API changes Reviewed By: astreet Differential Revision: D8769448 fbshipit-source-id: e67327ce41fa047a51a986c652b3d59992a510e2 --- java/com/facebook/yoga/YogaNode.java | 415 +++-------- .../com/facebook/yoga/YogaNodeProperties.java | 2 + .../facebook/yoga/YogaNodePropertiesJNI.java | 702 ++++++++++++++++++ java/jni/YGJNI.cpp | 97 ++- 4 files changed, 873 insertions(+), 343 deletions(-) create mode 100644 java/com/facebook/yoga/YogaNodePropertiesJNI.java diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 1565d4bb..18c49cfd 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -26,117 +26,35 @@ public class YogaNode implements Cloneable { */ static native int jni_YGNodeGetInstanceCount(); + private YogaNodeProperties mDelegate; private YogaNode mOwner; @Nullable private List mChildren; private YogaMeasureFunction mMeasureFunction; private YogaBaselineFunction mBaselineFunction; - private long mNativePointer; private Object mData; - /* Those flags needs be in sync with YGJNI.cpp */ - private static final int MARGIN = 1; - private static final int PADDING = 2; - private static final int BORDER = 4; - - @DoNotStrip - private int mEdgeSetFlag = 0; - - private boolean mHasSetPosition = false; - - @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; - - private native long jni_YGNodeNew(); public YogaNode() { - mNativePointer = jni_YGNodeNew(); - if (mNativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } + mDelegate = new YogaNodePropertiesJNI(this); } - private native long jni_YGNodeNewWithConfig(long configPointer); public YogaNode(YogaConfig config) { - mNativePointer = jni_YGNodeNewWithConfig(config.mNativePointer); - if (mNativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } + mDelegate = new YogaNodePropertiesJNI(this, config); } - private native void jni_YGNodeFree(long nativePointer); - @Override - protected void finalize() throws Throwable { - try { - jni_YGNodeFree(mNativePointer); - } finally { - super.finalize(); - } + public long getNativePointer() { + return mDelegate.getNativePointer(); + } + + /* frees the native underlying YGNode. Useful for testing. */ + public void freeNatives() { + mDelegate.freeNatives(); } - private native void jni_YGNodeReset(long nativePointer); public void reset() { - mEdgeSetFlag = 0; - mHasSetPosition = false; - 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; - mMeasureFunction = null; mBaselineFunction = null; mData = null; - mDoesLegacyStretchFlagAffectsLayout = false; - - jni_YGNodeReset(mNativePointer); + mDelegate.reset(); } public int getChildCount() { @@ -161,7 +79,7 @@ public class YogaNode implements Cloneable { } mChildren.add(i, child); child.mOwner = this; - jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i); + jni_YGNodeInsertChild(getNativePointer(), child.getNativePointer(), i); } private native void jni_YGNodeInsertSharedChild(long nativePointer, long childPointer, int index); @@ -172,27 +90,24 @@ public class YogaNode implements Cloneable { } mChildren.add(i, child); child.mOwner = null; - jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i); + jni_YGNodeInsertSharedChild(getNativePointer(), child.getNativePointer(), i); } private native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); - private native long jni_YGNodeClone(long nativePointer, Object newNode); - @Override public YogaNode clone() { try { YogaNode clonedYogaNode = (YogaNode) super.clone(); - long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); if (mChildren != null) { for (YogaNode child : mChildren) { - child.jni_YGNodeSetOwner(child.mNativePointer, 0); + child.jni_YGNodeSetOwner(child.getNativePointer(), 0); child.mOwner = null; } } - clonedYogaNode.mNativePointer = clonedNativePointer; + clonedYogaNode.mDelegate = mDelegate.clone(clonedYogaNode); clonedYogaNode.mOwner = null; clonedYogaNode.mChildren = mChildren != null ? (List) ((ArrayList) mChildren).clone() : null; @@ -211,9 +126,8 @@ public class YogaNode implements Cloneable { public YogaNode cloneWithNewChildren() { try { YogaNode clonedYogaNode = (YogaNode) super.clone(); - long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); + clonedYogaNode.mDelegate = mDelegate.clone(clonedYogaNode); clonedYogaNode.mOwner = null; - clonedYogaNode.mNativePointer = clonedNativePointer; clonedYogaNode.clearChildren(); return clonedYogaNode; } catch (CloneNotSupportedException ex) { @@ -226,7 +140,7 @@ public class YogaNode implements Cloneable { private void clearChildren() { mChildren = null; - jni_YGNodeClearChildren(mNativePointer); + jni_YGNodeClearChildren(getNativePointer()); } private native void jni_YGNodeRemoveChild(long nativePointer, long childPointer); @@ -237,7 +151,7 @@ public class YogaNode implements Cloneable { } final YogaNode child = mChildren.remove(i); child.mOwner = null; - jni_YGNodeRemoveChild(mNativePointer, child.mNativePointer); + jni_YGNodeRemoveChild(getNativePointer(), child.getNativePointer()); return child; } @@ -267,453 +181,326 @@ public class YogaNode implements Cloneable { private native void jni_YGNodeCalculateLayout(long nativePointer, float width, float height); public void calculateLayout(float width, float height) { - jni_YGNodeCalculateLayout(mNativePointer, width, height); + jni_YGNodeCalculateLayout(getNativePointer(), width, height); + mDelegate.onAfterCalculateLayout(); } public boolean hasNewLayout() { - return mHasNewLayout; + return mDelegate.hasNewLayout(); } private native void jni_YGNodeMarkDirty(long nativePointer); public void dirty() { - jni_YGNodeMarkDirty(mNativePointer); + jni_YGNodeMarkDirty(getNativePointer()); } private native void jni_YGNodeMarkDirtyAndPropogateToDescendants(long nativePointer); public void dirtyAllDescendants() { - jni_YGNodeMarkDirtyAndPropogateToDescendants(mNativePointer); + jni_YGNodeMarkDirtyAndPropogateToDescendants(getNativePointer()); } - private native boolean jni_YGNodeIsDirty(long nativePointer); public boolean isDirty() { - return jni_YGNodeIsDirty(mNativePointer); + return mDelegate.isDirty(); } private native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer); public void copyStyle(YogaNode srcNode) { - jni_YGNodeCopyStyle(mNativePointer, srcNode.mNativePointer); + jni_YGNodeCopyStyle(getNativePointer(), srcNode.getNativePointer()); } public void markLayoutSeen() { - mHasNewLayout = false; + mDelegate.markLayoutSeen(); } - private native int jni_YGNodeStyleGetDirection(long nativePointer); public YogaDirection getStyleDirection() { - return YogaDirection.fromInt(jni_YGNodeStyleGetDirection(mNativePointer)); + return mDelegate.getStyleDirection(); } - private native void jni_YGNodeStyleSetDirection(long nativePointer, int direction); public void setDirection(YogaDirection direction) { - jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue()); + mDelegate.setDirection(direction); } - private native int jni_YGNodeStyleGetFlexDirection(long nativePointer); public YogaFlexDirection getFlexDirection() { - return YogaFlexDirection.fromInt(jni_YGNodeStyleGetFlexDirection(mNativePointer)); + return mDelegate.getFlexDirection(); } - private native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection); public void setFlexDirection(YogaFlexDirection flexDirection) { - jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue()); + mDelegate.setFlexDirection(flexDirection); } - private native int jni_YGNodeStyleGetJustifyContent(long nativePointer); public YogaJustify getJustifyContent() { - return YogaJustify.fromInt(jni_YGNodeStyleGetJustifyContent(mNativePointer)); + return mDelegate.getJustifyContent(); } - private native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent); public void setJustifyContent(YogaJustify justifyContent) { - jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue()); + mDelegate.setJustifyContent(justifyContent); } - private native int jni_YGNodeStyleGetAlignItems(long nativePointer); public YogaAlign getAlignItems() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignItems(mNativePointer)); + return mDelegate.getAlignItems(); } - private native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems); public void setAlignItems(YogaAlign alignItems) { - jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue()); + mDelegate.setAlignItems(alignItems); } - private native int jni_YGNodeStyleGetAlignSelf(long nativePointer); public YogaAlign getAlignSelf() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignSelf(mNativePointer)); + return mDelegate.getAlignSelf(); } - private native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf); public void setAlignSelf(YogaAlign alignSelf) { - jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue()); + mDelegate.setAlignSelf(alignSelf); } - private native int jni_YGNodeStyleGetAlignContent(long nativePointer); public YogaAlign getAlignContent() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignContent(mNativePointer)); + return mDelegate.getAlignContent(); } - private native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent); public void setAlignContent(YogaAlign alignContent) { - jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue()); + mDelegate.setAlignContent(alignContent); } - private native int jni_YGNodeStyleGetPositionType(long nativePointer); public YogaPositionType getPositionType() { - return YogaPositionType.fromInt(jni_YGNodeStyleGetPositionType(mNativePointer)); + return mDelegate.getPositionType(); } - private native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType); public void setPositionType(YogaPositionType positionType) { - jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue()); + mDelegate.setPositionType(positionType); } - private native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType); public void setWrap(YogaWrap flexWrap) { - jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue()); + mDelegate.setWrap(flexWrap); } - private native int jni_YGNodeStyleGetOverflow(long nativePointer); public YogaOverflow getOverflow() { - return YogaOverflow.fromInt(jni_YGNodeStyleGetOverflow(mNativePointer)); + return mDelegate.getOverflow(); } - private native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow); public void setOverflow(YogaOverflow overflow) { - jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue()); + mDelegate.setOverflow(overflow); } - private native int jni_YGNodeStyleGetDisplay(long nativePointer); public YogaDisplay getDisplay() { - return YogaDisplay.fromInt(jni_YGNodeStyleGetDisplay(mNativePointer)); + return mDelegate.getDisplay(); } - private native void jni_YGNodeStyleSetDisplay(long nativePointer, int display); public void setDisplay(YogaDisplay display) { - jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue()); + mDelegate.setDisplay(display); } - private native void jni_YGNodeStyleSetFlex(long nativePointer, float flex); public void setFlex(float flex) { - jni_YGNodeStyleSetFlex(mNativePointer, flex); + mDelegate.setFlex(flex); } - private native float jni_YGNodeStyleGetFlexGrow(long nativePointer); public float getFlexGrow() { - return jni_YGNodeStyleGetFlexGrow(mNativePointer); + return mDelegate.getFlexGrow(); } - private native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); public void setFlexGrow(float flexGrow) { - jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow); + mDelegate.setFlexGrow(flexGrow); } - private native float jni_YGNodeStyleGetFlexShrink(long nativePointer); public float getFlexShrink() { - return jni_YGNodeStyleGetFlexShrink(mNativePointer); + return mDelegate.getFlexShrink(); } - private native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); public void setFlexShrink(float flexShrink) { - jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); + mDelegate.setFlexShrink(flexShrink); } - private native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); public YogaValue getFlexBasis() { - return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); + return mDelegate.getFlexBasis(); } - private native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); public void setFlexBasis(float flexBasis) { - jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); + mDelegate.setFlexBasis(flexBasis); } - private native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); public void setFlexBasisPercent(float percent) { - jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); + mDelegate.setFlexBasisPercent(percent); } - private native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); public void setFlexBasisAuto() { - jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); + mDelegate.setFlexBasisAuto(); } - private native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); public YogaValue getMargin(YogaEdge edge) { - if (!((mEdgeSetFlag & MARGIN) == MARGIN)) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); + return mDelegate.getMargin(edge); } - private native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); public void setMargin(YogaEdge edge, float margin) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); + mDelegate.setMargin(edge, margin); } - private native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); public void setMarginPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); + mDelegate.setMarginPercent(edge, percent); } - private native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); public void setMarginAuto(YogaEdge edge) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); + mDelegate.setMarginAuto(edge); } - private native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); public YogaValue getPadding(YogaEdge edge) { - if (!((mEdgeSetFlag & PADDING) == PADDING)) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); + return mDelegate.getPadding(edge); } - private native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); public void setPadding(YogaEdge edge, float padding) { - mEdgeSetFlag |= PADDING; - jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); + mDelegate.setPadding(edge, padding); } - private native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); public void setPaddingPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= PADDING; - jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); + mDelegate.setPaddingPercent(edge, percent); } - private native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); public float getBorder(YogaEdge edge) { - if (!((mEdgeSetFlag & BORDER) == BORDER)) { - return YogaConstants.UNDEFINED; - } - return jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); + return mDelegate.getBorder(edge); } - private native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); public void setBorder(YogaEdge edge, float border) { - mEdgeSetFlag |= BORDER; - jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); + mDelegate.setBorder(edge, border); } - private native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); public YogaValue getPosition(YogaEdge edge) { - if (!mHasSetPosition) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); + return mDelegate.getPosition(edge); } - private native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); public void setPosition(YogaEdge edge, float position) { - mHasSetPosition = true; - jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); + mDelegate.setPosition(edge, position); } - private native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent); public void setPositionPercent(YogaEdge edge, float percent) { - mHasSetPosition = true; - jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); + mDelegate.setPositionPercent(edge, percent); } - private native Object jni_YGNodeStyleGetWidth(long nativePointer); public YogaValue getWidth() { - return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); + return mDelegate.getWidth(); } - private native void jni_YGNodeStyleSetWidth(long nativePointer, float width); public void setWidth(float width) { - jni_YGNodeStyleSetWidth(mNativePointer, width); + mDelegate.setWidth(width); } - private native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); public void setWidthPercent(float percent) { - jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); + mDelegate.setWidthPercent(percent); } - private native void jni_YGNodeStyleSetWidthAuto(long nativePointer); public void setWidthAuto() { - jni_YGNodeStyleSetWidthAuto(mNativePointer); + mDelegate.setWidthAuto(); } - private native Object jni_YGNodeStyleGetHeight(long nativePointer); public YogaValue getHeight() { - return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); + return mDelegate.getHeight(); } - private native void jni_YGNodeStyleSetHeight(long nativePointer, float height); public void setHeight(float height) { - jni_YGNodeStyleSetHeight(mNativePointer, height); + mDelegate.setHeight(height); } - private native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); public void setHeightPercent(float percent) { - jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); + mDelegate.setHeightPercent(percent); } - private native void jni_YGNodeStyleSetHeightAuto(long nativePointer); public void setHeightAuto() { - jni_YGNodeStyleSetHeightAuto(mNativePointer); + mDelegate.setHeightAuto(); } - private native Object jni_YGNodeStyleGetMinWidth(long nativePointer); public YogaValue getMinWidth() { - return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); + return mDelegate.getMinWidth(); } - private native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); public void setMinWidth(float minWidth) { - jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); + mDelegate.setMinWidth(minWidth); } - private native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); public void setMinWidthPercent(float percent) { - jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); + mDelegate.setMinWidthPercent(percent); } - private native Object jni_YGNodeStyleGetMinHeight(long nativePointer); public YogaValue getMinHeight() { - return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); + return mDelegate.getMinHeight(); } - private native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); public void setMinHeight(float minHeight) { - jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); + mDelegate.setMinHeight(minHeight); } - private native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); public void setMinHeightPercent(float percent) { - jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); + mDelegate.setMinHeightPercent(percent); } - private native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); public YogaValue getMaxWidth() { - return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); + return mDelegate.getMaxWidth(); } - private native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); public void setMaxWidth(float maxWidth) { - jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); + mDelegate.setMaxWidth(maxWidth); } - private native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); public void setMaxWidthPercent(float percent) { - jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); + mDelegate.setMaxWidthPercent(percent); } - private native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); public YogaValue getMaxHeight() { - return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); + return mDelegate.getMaxHeight(); } - private native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); public void setMaxHeight(float maxheight) { - jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); + mDelegate.setMaxHeight(maxheight); } - private native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); public void setMaxHeightPercent(float percent) { - jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); + mDelegate.setMaxHeightPercent(percent); } - private native float jni_YGNodeStyleGetAspectRatio(long nativePointer); public float getAspectRatio() { - return jni_YGNodeStyleGetAspectRatio(mNativePointer); + return mDelegate.getAspectRatio(); } - private native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio); public void setAspectRatio(float aspectRatio) { - jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio); + mDelegate.setAspectRatio(aspectRatio); } public float getLayoutX() { - return mLeft; + return mDelegate.getLayoutX(); } public float getLayoutY() { - return mTop; + return mDelegate.getLayoutY(); } public float getLayoutWidth() { - return mWidth; + return mDelegate.getLayoutWidth(); } public float getLayoutHeight() { - return mHeight; + return mDelegate.getLayoutHeight(); } public boolean getDoesLegacyStretchFlagAffectsLayout() { - return mDoesLegacyStretchFlagAffectsLayout; + return mDelegate.getDoesLegacyStretchFlagAffectsLayout(); } 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"); - } + return mDelegate.getLayoutMargin(edge); } 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"); - } + return mDelegate.getLayoutPadding(edge); } 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"); - } + return mDelegate.getLayoutBorder(edge); } public YogaDirection getLayoutDirection() { - return YogaDirection.fromInt(mLayoutDirection); + return mDelegate.getLayoutDirection(); } private native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); public void setMeasureFunction(YogaMeasureFunction measureFunction) { mMeasureFunction = measureFunction; - jni_YGNodeSetHasMeasureFunc(mNativePointer, measureFunction != null); + jni_YGNodeSetHasMeasureFunc(getNativePointer(), measureFunction != null); } // Implementation Note: Why this method needs to stay final @@ -738,7 +525,7 @@ public class YogaNode implements Cloneable { private native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc); public void setBaselineFunction(YogaBaselineFunction baselineFunction) { mBaselineFunction = baselineFunction; - jni_YGNodeSetHasBaselineFunc(mNativePointer, baselineFunction != null); + jni_YGNodeSetHasBaselineFunc(getNativePointer(), baselineFunction != null); } @DoNotStrip @@ -765,7 +552,7 @@ public class YogaNode implements Cloneable { * layout of the tree rooted at this node. */ public void print() { - jni_YGNodePrint(mNativePointer); + jni_YGNodePrint(getNativePointer()); } /** @@ -783,6 +570,6 @@ public class YogaNode implements Cloneable { mChildren.remove(childIndex); mChildren.add(childIndex, newNode); newNode.mOwner = this; - return newNode.mNativePointer; + return newNode.getNativePointer(); } } diff --git a/java/com/facebook/yoga/YogaNodeProperties.java b/java/com/facebook/yoga/YogaNodeProperties.java index fbad2ea2..834aa833 100644 --- a/java/com/facebook/yoga/YogaNodeProperties.java +++ b/java/com/facebook/yoga/YogaNodeProperties.java @@ -164,4 +164,6 @@ public interface YogaNodeProperties { float getLayoutBorder(YogaEdge edge); YogaDirection getLayoutDirection(); + + void freeNatives(); } diff --git a/java/com/facebook/yoga/YogaNodePropertiesJNI.java b/java/com/facebook/yoga/YogaNodePropertiesJNI.java new file mode 100644 index 00000000..d44cd1d2 --- /dev/null +++ b/java/com/facebook/yoga/YogaNodePropertiesJNI.java @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; + +public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { + + static { + SoLoader.loadLibrary("yoga"); + } + + private long mNativePointer; + + /* Those flags needs be in sync with YGJNI.cpp */ + private static final int MARGIN = 1; + private static final int PADDING = 2; + private static final int BORDER = 4; + + @DoNotStrip private int mEdgeSetFlag = 0; + + private boolean mHasSetPosition = false; + + @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; + + private native long jni_YGNodeNew(YogaNode node); + + public YogaNodePropertiesJNI(YogaNode node) { + mNativePointer = jni_YGNodeNew(node); + if (mNativePointer == 0) { + throw new IllegalStateException("Failed to allocate native memory"); + } + } + + private native long jni_YGNodeNewWithConfig(YogaNode node, long configPointer); + + public YogaNodePropertiesJNI(YogaNode node, YogaConfig config) { + mNativePointer = jni_YGNodeNewWithConfig(node, config.mNativePointer); + if (mNativePointer == 0) { + throw new IllegalStateException("Failed to allocate native memory"); + } + } + + private native void jni_YGNodeFree(long nativePointer); + + @Override + public void freeNatives() { + jni_YGNodeFree(mNativePointer); + mNativePointer = 0; + } + + @Override + protected void finalize() throws Throwable { + try { + freeNatives(); + } finally { + super.finalize(); + } + } + + private static native long jni_YGNodeClone( + long nativePointer, YogaNode newNode, YogaNodePropertiesJNI newProps); + + @Override + public YogaNodeProperties clone(YogaNode node) { + try { + YogaNodePropertiesJNI clonedProperties = (YogaNodePropertiesJNI) clone(); + clonedProperties.mNativePointer = jni_YGNodeClone(getNativePointer(), node, clonedProperties); + return clonedProperties; + } catch (CloneNotSupportedException ex) { + // This class implements Cloneable, this should not happen + throw new RuntimeException(ex); + } + } + + @Override + public long getNativePointer() { + return mNativePointer; + } + + private static native void jni_YGTransferLayoutOutputsRecursive(long nativePointer); + + @Override + public void onAfterCalculateLayout() { + jni_YGTransferLayoutOutputsRecursive(mNativePointer); + } + + private native void jni_YGNodeReset(long nativePointer); + + @Override + public void reset() { + mHasSetPosition = false; + mEdgeSetFlag = 0; + mHasNewLayout = true; + mDoesLegacyStretchFlagAffectsLayout = false; + + 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; + jni_YGNodeReset(getNativePointer()); + } + + @Override + public boolean hasNewLayout() { + return mHasNewLayout; + } + + private native boolean jni_YGNodeIsDirty(long nativePointer); + + @Override + public boolean isDirty() { + return jni_YGNodeIsDirty(mNativePointer); + } + + @Override + public void markLayoutSeen() { + mHasNewLayout = false; + } + + private native int jni_YGNodeStyleGetDirection(long nativePointer); + + @Override + public YogaDirection getStyleDirection() { + return YogaDirection.fromInt(jni_YGNodeStyleGetDirection(mNativePointer)); + } + + private native void jni_YGNodeStyleSetDirection(long nativePointer, int direction); + + @Override + public void setDirection(YogaDirection direction) { + jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue()); + } + + private native int jni_YGNodeStyleGetFlexDirection(long nativePointer); + + @Override + public YogaFlexDirection getFlexDirection() { + return YogaFlexDirection.fromInt(jni_YGNodeStyleGetFlexDirection(mNativePointer)); + } + + private native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection); + + @Override + public void setFlexDirection(YogaFlexDirection flexDirection) { + jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue()); + } + + private native int jni_YGNodeStyleGetJustifyContent(long nativePointer); + + @Override + public YogaJustify getJustifyContent() { + return YogaJustify.fromInt(jni_YGNodeStyleGetJustifyContent(mNativePointer)); + } + + private native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent); + + @Override + public void setJustifyContent(YogaJustify justifyContent) { + jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue()); + } + + private native int jni_YGNodeStyleGetAlignItems(long nativePointer); + + @Override + public YogaAlign getAlignItems() { + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignItems(mNativePointer)); + } + + private native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems); + + @Override + public void setAlignItems(YogaAlign alignItems) { + jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue()); + } + + private native int jni_YGNodeStyleGetAlignSelf(long nativePointer); + + @Override + public YogaAlign getAlignSelf() { + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignSelf(mNativePointer)); + } + + private native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf); + + @Override + public void setAlignSelf(YogaAlign alignSelf) { + jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue()); + } + + private native int jni_YGNodeStyleGetAlignContent(long nativePointer); + + @Override + public YogaAlign getAlignContent() { + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignContent(mNativePointer)); + } + + private native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent); + + @Override + public void setAlignContent(YogaAlign alignContent) { + jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue()); + } + + private native int jni_YGNodeStyleGetPositionType(long nativePointer); + + @Override + public YogaPositionType getPositionType() { + return YogaPositionType.fromInt(jni_YGNodeStyleGetPositionType(mNativePointer)); + } + + private native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType); + + @Override + public void setPositionType(YogaPositionType positionType) { + jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue()); + } + + private native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType); + + @Override + public void setWrap(YogaWrap flexWrap) { + jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue()); + } + + private native int jni_YGNodeStyleGetOverflow(long nativePointer); + + @Override + public YogaOverflow getOverflow() { + return YogaOverflow.fromInt(jni_YGNodeStyleGetOverflow(mNativePointer)); + } + + private native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow); + + @Override + public void setOverflow(YogaOverflow overflow) { + jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue()); + } + + private native int jni_YGNodeStyleGetDisplay(long nativePointer); + + @Override + public YogaDisplay getDisplay() { + return YogaDisplay.fromInt(jni_YGNodeStyleGetDisplay(mNativePointer)); + } + + private native void jni_YGNodeStyleSetDisplay(long nativePointer, int display); + + @Override + public void setDisplay(YogaDisplay display) { + jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue()); + } + + private native void jni_YGNodeStyleSetFlex(long nativePointer, float flex); + + @Override + public void setFlex(float flex) { + jni_YGNodeStyleSetFlex(mNativePointer, flex); + } + + private native float jni_YGNodeStyleGetFlexGrow(long nativePointer); + + @Override + public float getFlexGrow() { + return jni_YGNodeStyleGetFlexGrow(mNativePointer); + } + + private native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); + + @Override + public void setFlexGrow(float flexGrow) { + jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow); + } + + private native float jni_YGNodeStyleGetFlexShrink(long nativePointer); + + @Override + public float getFlexShrink() { + return jni_YGNodeStyleGetFlexShrink(mNativePointer); + } + + private native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); + + @Override + public void setFlexShrink(float flexShrink) { + jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); + } + + private native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); + + @Override + public YogaValue getFlexBasis() { + return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); + } + + private native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); + + @Override + public void setFlexBasis(float flexBasis) { + jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); + } + + private native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); + + @Override + public void setFlexBasisPercent(float percent) { + jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); + } + + private native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); + + @Override + public void setFlexBasisAuto() { + jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); + } + + private native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); + + @Override + public YogaValue getMargin(YogaEdge edge) { + if (!((mEdgeSetFlag & MARGIN) == MARGIN)) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); + } + + private native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); + + @Override + public void setMargin(YogaEdge edge, float margin) { + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); + } + + private native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); + + @Override + public void setMarginPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); + } + + private native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); + + @Override + public void setMarginAuto(YogaEdge edge) { + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); + } + + private native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); + + @Override + public YogaValue getPadding(YogaEdge edge) { + if (!((mEdgeSetFlag & PADDING) == PADDING)) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); + } + + private native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); + + @Override + public void setPadding(YogaEdge edge, float padding) { + mEdgeSetFlag |= PADDING; + jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); + } + + private native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); + + @Override + public void setPaddingPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= PADDING; + jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); + } + + private native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); + + @Override + public float getBorder(YogaEdge edge) { + if (!((mEdgeSetFlag & BORDER) == BORDER)) { + return YogaConstants.UNDEFINED; + } + return jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); + } + + private native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); + + @Override + public void setBorder(YogaEdge edge, float border) { + mEdgeSetFlag |= BORDER; + jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); + } + + private native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); + + @Override + public YogaValue getPosition(YogaEdge edge) { + if (!mHasSetPosition) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); + } + + private native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); + + @Override + public void setPosition(YogaEdge edge, float position) { + mHasSetPosition = true; + jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); + } + + private native void jni_YGNodeStyleSetPositionPercent( + long nativePointer, int edge, float percent); + + @Override + public void setPositionPercent(YogaEdge edge, float percent) { + mHasSetPosition = true; + jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); + } + + private native Object jni_YGNodeStyleGetWidth(long nativePointer); + + @Override + public YogaValue getWidth() { + return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); + } + + private native void jni_YGNodeStyleSetWidth(long nativePointer, float width); + + @Override + public void setWidth(float width) { + jni_YGNodeStyleSetWidth(mNativePointer, width); + } + + private native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); + + @Override + public void setWidthPercent(float percent) { + jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); + } + + private native void jni_YGNodeStyleSetWidthAuto(long nativePointer); + + @Override + public void setWidthAuto() { + jni_YGNodeStyleSetWidthAuto(mNativePointer); + } + + private native Object jni_YGNodeStyleGetHeight(long nativePointer); + + @Override + public YogaValue getHeight() { + return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); + } + + private native void jni_YGNodeStyleSetHeight(long nativePointer, float height); + + @Override + public void setHeight(float height) { + jni_YGNodeStyleSetHeight(mNativePointer, height); + } + + private native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); + + @Override + public void setHeightPercent(float percent) { + jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); + } + + private native void jni_YGNodeStyleSetHeightAuto(long nativePointer); + + @Override + public void setHeightAuto() { + jni_YGNodeStyleSetHeightAuto(mNativePointer); + } + + private native Object jni_YGNodeStyleGetMinWidth(long nativePointer); + + @Override + public YogaValue getMinWidth() { + return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); + } + + private native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); + + @Override + public void setMinWidth(float minWidth) { + jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); + } + + private native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); + + @Override + public void setMinWidthPercent(float percent) { + jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMinHeight(long nativePointer); + + @Override + public YogaValue getMinHeight() { + return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); + } + + private native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); + + @Override + public void setMinHeight(float minHeight) { + jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); + } + + private native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); + + @Override + public void setMinHeightPercent(float percent) { + jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); + + @Override + public YogaValue getMaxWidth() { + return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); + } + + private native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); + + @Override + public void setMaxWidth(float maxWidth) { + jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); + } + + private native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); + + @Override + public void setMaxWidthPercent(float percent) { + jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); + + @Override + public YogaValue getMaxHeight() { + return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); + } + + private native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); + + @Override + public void setMaxHeight(float maxheight) { + jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); + } + + private native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); + + @Override + public void setMaxHeightPercent(float percent) { + jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); + } + + private native float jni_YGNodeStyleGetAspectRatio(long nativePointer); + + @Override + public float getAspectRatio() { + return jni_YGNodeStyleGetAspectRatio(mNativePointer); + } + + private native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio); + + @Override + public void setAspectRatio(float aspectRatio) { + jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio); + } + + @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); + } +} diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 0b552055..dc38500e 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -21,6 +21,11 @@ struct JYogaConfig : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaConfig;"; }; +struct JYogaNodePropertiesJNI : public JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/yoga/YogaNodePropertiesJNI;"; +}; + struct YGConfigContext { global_ref* logger; global_ref* config; @@ -33,16 +38,34 @@ struct YGConfigContext { } }; +struct JNINodeContext { + weak_ref node; + weak_ref props; +}; + static inline weak_ref* YGNodeJobject(YGNodeRef node) { - return reinterpret_cast*>(node->getContext()); + return &reinterpret_cast(node->getContext())->node; +} + +static inline weak_ref* YGNodePropsJObject( + YGNodeRef node) { + return &reinterpret_cast(node->getContext())->props; +} + +static inline void setNodeContext( + YGNodeRef node, + alias_ref javaNode, + alias_ref javaNodeProps) { + node->setContext( + new JNINodeContext{make_weak(javaNode), make_weak(javaNodeProps)}); } static void YGTransferLayoutDirection( YGNodeRef node, - alias_ref javaNode) { + alias_ref javaProps) { static auto layoutDirectionField = - javaNode->getClass()->getField("mLayoutDirection"); - javaNode->setFieldValue( + javaProps->getClass()->getField("mLayoutDirection"); + javaProps->setFieldValue( layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); } @@ -50,7 +73,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { if (!root->getHasNewLayout()) { return; } - auto obj = YGNodeJobject(root)->lockLocal(); + auto obj = YGNodePropsJObject(root)->lockLocal(); if (!obj) { YGLog( root, @@ -223,7 +246,9 @@ static YGSize YGJNIMeasureFunc( findClassStatic("com/facebook/yoga/YogaNode") ->getMethod("measure"); - YGTransferLayoutDirection(node, obj); + if (auto jProps = YGNodePropsJObject(node)->lockLocal()) { + YGTransferLayoutDirection(node, jProps); + } const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); @@ -287,18 +312,21 @@ static int YGJNILogFunc( return result; } -jlong jni_YGNodeNew(alias_ref thiz) { +jlong jni_YGNodeNew( + alias_ref javaProps, + alias_ref javaNode) { const YGNodeRef node = YGNodeNew(); - node->setContext(new weak_ref(make_weak(thiz))); - // YGNodeSetContext(node, new weak_ref(make_weak(thiz))); + setNodeContext(node, javaNode, javaProps); node->setPrintFunc(YGPrint); - // YGNodeSetPrintFunc(node, YGPrint); return reinterpret_cast(node); } -jlong jni_YGNodeNewWithConfig(alias_ref thiz, jlong configPointer) { +jlong jni_YGNodeNewWithConfig( + alias_ref javaProps, + alias_ref javaNode, + jlong configPointer) { const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer)); - node->setContext(new weak_ref(make_weak(thiz))); + setNodeContext(node, javaNode, javaProps); node->setPrintFunc(YGPrint); return reinterpret_cast(node); } @@ -314,18 +342,18 @@ void jni_YGNodeSetOwner( } jlong jni_YGNodeClone( - alias_ref thiz, + alias_ref, jlong nativePointer, - alias_ref clonedJavaObject) { + alias_ref clonedJavaObject, + alias_ref clonedJavaProps) { const YGNodeRef clonedYogaNode = YGNodeClone(_jlong2YGNodeRef(nativePointer)); - clonedYogaNode->setContext( - new weak_ref(make_weak(clonedJavaObject))); + setNodeContext(clonedYogaNode, clonedJavaObject, clonedJavaProps); return reinterpret_cast(clonedYogaNode); } void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - delete YGNodeJobject(node); + delete reinterpret_cast(node->getContext()); YGNodeFree(node); } @@ -387,6 +415,12 @@ void jni_YGNodeCalculateLayout( static_cast(width), static_cast(height), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); +} + +static void jni_YGTransferLayoutOutputsRecursive( + alias_ref, + jlong nativePointer) { + const YGNodeRef root = _jlong2YGNodeRef(nativePointer); YGTransferLayoutOutputsRecursive(root); } @@ -666,23 +700,14 @@ jint jni_YGNodeGetInstanceCount(alias_ref clazz) { jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( - "com/facebook/yoga/YogaNode", + "com/facebook/yoga/YogaNodePropertiesJNI", { + YGMakeNativeMethod(jni_YGNodeClone), YGMakeNativeMethod(jni_YGNodeNew), YGMakeNativeMethod(jni_YGNodeNewWithConfig), YGMakeNativeMethod(jni_YGNodeFree), YGMakeNativeMethod(jni_YGNodeReset), - YGMakeNativeMethod(jni_YGNodeClearChildren), - YGMakeNativeMethod(jni_YGNodeInsertChild), - YGMakeNativeMethod(jni_YGNodeInsertSharedChild), - YGMakeNativeMethod(jni_YGNodeRemoveChild), - YGMakeNativeMethod(jni_YGNodeCalculateLayout), - YGMakeNativeMethod(jni_YGNodeMarkDirty), - YGMakeNativeMethod(jni_YGNodeMarkDirtyAndPropogateToDescendants), YGMakeNativeMethod(jni_YGNodeIsDirty), - YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc), - YGMakeNativeMethod(jni_YGNodeSetHasBaselineFunc), - YGMakeNativeMethod(jni_YGNodeCopyStyle), YGMakeNativeMethod(jni_YGNodeStyleGetDirection), YGMakeNativeMethod(jni_YGNodeStyleSetDirection), YGMakeNativeMethod(jni_YGNodeStyleGetFlexDirection), @@ -745,9 +770,23 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetAspectRatio), YGMakeNativeMethod(jni_YGNodeStyleSetAspectRatio), + YGMakeNativeMethod(jni_YGTransferLayoutOutputsRecursive), + }); + registerNatives( + "com/facebook/yoga/YogaNode", + { + YGMakeNativeMethod(jni_YGNodeClearChildren), + YGMakeNativeMethod(jni_YGNodeInsertChild), + YGMakeNativeMethod(jni_YGNodeInsertSharedChild), + YGMakeNativeMethod(jni_YGNodeRemoveChild), + YGMakeNativeMethod(jni_YGNodeCalculateLayout), + YGMakeNativeMethod(jni_YGNodeMarkDirty), + YGMakeNativeMethod(jni_YGNodeMarkDirtyAndPropogateToDescendants), + YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc), + YGMakeNativeMethod(jni_YGNodeSetHasBaselineFunc), + YGMakeNativeMethod(jni_YGNodeCopyStyle), YGMakeNativeMethod(jni_YGNodeGetInstanceCount), YGMakeNativeMethod(jni_YGNodePrint), - YGMakeNativeMethod(jni_YGNodeClone), YGMakeNativeMethod(jni_YGNodeSetOwner), }); registerNatives( From 3499e2e0efaa06cf8bd56c9623bb47defc07c06f Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 30 Jul 2018 09:30:51 -0700 Subject: [PATCH 042/189] Add `YogaNodeProperties` implementation based on `ByteBuffer` Summary: @public Adds an implementation of `YogaNodeProperties` that accesses style and layout properties using a `ByteBuffer` rather than JNI calls. We hope for a speed improvement. This needs further cleanup after experimenting, e.g. to codegen the offsets. Reviewed By: pasqualeanatriello Differential Revision: D8911723 fbshipit-source-id: 3c24b57eb545155878896ebb5d64d4553eb6bedc --- java/BUCK | 1 + java/com/facebook/yoga/YogaNode.java | 41 +- .../facebook/yoga/YogaNodeMemoryLayout.java | 151 ++++++ .../com/facebook/yoga/YogaNodeProperties.java | 2 +- .../yoga/YogaNodePropertiesByteBuffer.java | 510 ++++++++++++++++++ .../facebook/yoga/YogaNodePropertiesJNI.java | 3 +- java/com/facebook/yoga/YogaValue.java | 4 +- java/jni/YGJNI.cpp | 57 +- .../facebook/yoga/TestParametrization.java | 54 ++ .../facebook/yoga/YGAbsolutePositionTest.java | 111 ++-- .../com/facebook/yoga/YGAlignContentTest.java | 237 ++++---- .../com/facebook/yoga/YGAlignItemsTest.java | 257 ++++----- .../com/facebook/yoga/YGAlignSelfTest.java | 41 +- .../com/facebook/yoga/YGAndroidNewsFeed.java | 48 +- .../tests/com/facebook/yoga/YGBorderTest.java | 35 +- .../com/facebook/yoga/YGDimensionTest.java | 27 +- .../com/facebook/yoga/YGDisplayTest.java | 51 +- .../facebook/yoga/YGFlexDirectionTest.java | 65 ++- java/tests/com/facebook/yoga/YGFlexTest.java | 71 ++- .../com/facebook/yoga/YGFlexWrapTest.java | 215 ++++---- .../facebook/yoga/YGJustifyContentTest.java | 129 +++-- .../tests/com/facebook/yoga/YGMarginTest.java | 191 ++++--- .../facebook/yoga/YGMinMaxDimensionTest.java | 153 +++--- .../com/facebook/yoga/YGPaddingTest.java | 39 +- .../com/facebook/yoga/YGPercentageTest.java | 141 ++--- .../com/facebook/yoga/YGRoundingTest.java | 141 ++--- .../com/facebook/yoga/YGSizeOverflowTest.java | 35 +- .../yoga/YogaNodeStylePropertiesTest.java | 114 ++-- .../tests/com/facebook/yoga/YogaNodeTest.java | 89 +-- 29 files changed, 2034 insertions(+), 979 deletions(-) create mode 100644 java/com/facebook/yoga/YogaNodeMemoryLayout.java create mode 100644 java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java create mode 100644 java/tests/com/facebook/yoga/TestParametrization.java diff --git a/java/BUCK b/java/BUCK index 0975d521..4ddabcef 100644 --- a/java/BUCK +++ b/java/BUCK @@ -8,6 +8,7 @@ load("//:yoga_defs.bzl", "ANDROID", "CXX_LIBRARY_WHITELIST", "FBJNI_JAVA_TARGET" yoga_cxx_library( name = "jni", srcs = glob(["jni/*.cpp"]), + headers = glob(["jni/*.h"]), header_namespace = "", compiler_flags = [ "-fno-omit-frame-pointer", diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 18c49cfd..17297019 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -18,12 +18,10 @@ import javax.annotation.Nullable; public class YogaNode implements Cloneable { static { - SoLoader.loadLibrary("yoga"); + SoLoader.loadLibrary("yoga"); } - /** - * Get native instance count. Useful for testing only. - */ + /** Get native instance count. Useful for testing only. */ static native int jni_YGNodeGetInstanceCount(); private YogaNodeProperties mDelegate; @@ -41,6 +39,14 @@ public class YogaNode implements Cloneable { mDelegate = new YogaNodePropertiesJNI(this, config); } + public YogaNode(boolean unsafeClownyUseByteBufferValueDoesNotMatter) { + mDelegate = new YogaNodePropertiesByteBuffer(this); + } + + public YogaNode(boolean unsafeClownyUseByteBufferValueDoesNotMatter, YogaConfig config) { + mDelegate = new YogaNodePropertiesByteBuffer(this, config); + } + public long getNativePointer() { return mDelegate.getNativePointer(); } @@ -69,6 +75,7 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index); + public void addChildAt(YogaNode child, int i) { if (child.mOwner != null) { throw new IllegalStateException("Child already has a parent, it must be removed first."); @@ -144,6 +151,7 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeRemoveChild(long nativePointer, long childPointer); + public YogaNode removeChildAt(int i) { if (mChildren == null) { throw new IllegalStateException( @@ -156,12 +164,10 @@ public class YogaNode implements Cloneable { } /** - * @returns the {@link YogaNode} that owns this {@link YogaNode}. - * The owner is used to identify the YogaTree that a {@link YogaNode} belongs - * to. - * This method will return the parent of the {@link YogaNode} when the - * {@link YogaNode} only belongs to one YogaTree or null when the - * {@link YogaNode} is shared between two or more YogaTrees. + * @returns the {@link YogaNode} that owns this {@link YogaNode}. The owner is used to identify + * the YogaTree that a {@link YogaNode} belongs to. This method will return the parent of the + * {@link YogaNode} when the {@link YogaNode} only belongs to one YogaTree or null when the + * {@link YogaNode} is shared between two or more YogaTrees. */ @Nullable public YogaNode getOwner() { @@ -179,10 +185,11 @@ public class YogaNode implements Cloneable { return mChildren == null ? -1 : mChildren.indexOf(child); } - private native void jni_YGNodeCalculateLayout(long nativePointer, float width, float height); + private native boolean jni_YGNodeCalculateLayout(long nativePointer, float width, float height); + public void calculateLayout(float width, float height) { - jni_YGNodeCalculateLayout(getNativePointer(), width, height); - mDelegate.onAfterCalculateLayout(); + boolean hasNewLayout = jni_YGNodeCalculateLayout(getNativePointer(), width, height); + mDelegate.onAfterCalculateLayout(hasNewLayout); } public boolean hasNewLayout() { @@ -190,6 +197,7 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeMarkDirty(long nativePointer); + public void dirty() { jni_YGNodeMarkDirty(getNativePointer()); } @@ -205,6 +213,7 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer); + public void copyStyle(YogaNode srcNode) { jni_YGNodeCopyStyle(getNativePointer(), srcNode.getNativePointer()); } @@ -498,6 +507,7 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); + public void setMeasureFunction(YogaMeasureFunction measureFunction) { mMeasureFunction = measureFunction; jni_YGNodeSetHasMeasureFunc(getNativePointer(), measureFunction != null); @@ -523,6 +533,7 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc); + public void setBaselineFunction(YogaBaselineFunction baselineFunction) { mBaselineFunction = baselineFunction; jni_YGNodeSetHasBaselineFunc(getNativePointer(), baselineFunction != null); @@ -548,8 +559,8 @@ public class YogaNode implements Cloneable { private native void jni_YGNodePrint(long nativePointer); /** - * Use the set logger (defaults to adb log) to print out the styles, children, and computed - * layout of the tree rooted at this node. + * Use the set logger (defaults to adb log) to print out the styles, children, and computed layout + * of the tree rooted at this node. */ public void print() { jni_YGNodePrint(getNativePointer()); diff --git a/java/com/facebook/yoga/YogaNodeMemoryLayout.java b/java/com/facebook/yoga/YogaNodeMemoryLayout.java new file mode 100644 index 00000000..212c27ec --- /dev/null +++ b/java/com/facebook/yoga/YogaNodeMemoryLayout.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ + +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import java.nio.ByteBuffer; + +@DoNotStrip +/* package */ final class YogaNodeMemoryLayout { + + private static final int FLOAT_SIZE = 4; + private static final int INT_SIZE = 4; + private static final int VALUE_SIZE = FLOAT_SIZE + INT_SIZE; + private static final byte FALSE = 0; + private static final byte TRUE = 1; + private static final int AUTO = YogaUnit.AUTO.intValue(); + private static final int POINT = YogaUnit.POINT.intValue(); + private static final int PERCENT = YogaUnit.PERCENT.intValue(); + private static final int UNDEFINED = YogaUnit.UNDEFINED.intValue(); + + // TODO(davidaurelio) code-gen these values + static final int styleDirection = 0; + static final int styleFlexDirection = 4; + static final int styleJustifyContent = 8; + static final int styleAlignContent = 12; + static final int styleAlignItems = 16; + static final int styleAlignSelf = 20; + static final int stylePositionType = 24; + static final int styleFlexWrap = 28; + static final int styleOverflow = 32; + static final int styleDisplay = 36; + static final int styleFlex = 40; + static final int styleFlexGrow = 48; + static final int styleFlexShrink = 56; + static final int styleFlexBasis = 64; + static final int styleMargin = 72; + static final int stylePosition = 144; + static final int stylePadding = 216; + static final int styleBorder = 288; + static final int styleDimensions = 360; + static final int styleMinDimensions = 376; + static final int styleMaxDimensions = 392; + static final int styleAspectRatio = 408; + + static final int styleWidth = styleDimensions; + static final int styleHeight = styleDimensions + VALUE_SIZE; + static final int styleMinWidth = styleMinDimensions; + static final int styleMinHeight = styleMinDimensions + VALUE_SIZE; + static final int styleMaxWidth = styleMaxDimensions; + static final int styleMaxHeight = styleMaxDimensions + VALUE_SIZE; + + static final int layoutPosition = 0; + static final int layoutDimensions = 16; + static final int layoutMargin = 24; + static final int layoutBorder = 48; + static final int layoutPadding = 72; + static final int layoutDirection = 96; + static final int layoutComputedFlexBasisGeneration = 100; + static final int layoutComputedFlexBasis = 104; + static final int layoutHadOverflow = 112; + static final int layoutGenerationCount = 116; + static final int layoutLastOwnerDirection = 120; + static final int layoutNextCachedMeasurementsIndex = 124; + static final int layoutCachedMeasurements = 128; + static final int layoutMeasuredDimensions = 512; + static final int layoutCachedLayout = 520; + static final int layoutDidUseLegacyFlag = 544; + static final int layoutDoesLegacyStretchFlagAffectsLayout = 545; + + static final int layoutX = layoutPosition; + static final int layoutY = layoutPosition + FLOAT_SIZE; + static final int layoutWidth = layoutDimensions; + static final int layoutHeight = layoutDimensions + FLOAT_SIZE; + + static int stylePositionOffset(YogaEdge edge) { + return stylePosition + edge.intValue() * VALUE_SIZE; + } + + static int styleMarginOffset(YogaEdge edge) { + return styleMargin + edge.intValue() * VALUE_SIZE; + } + + static int layoutMarginOffset(YogaEdge edge) { + return layoutMargin + edge.intValue() * FLOAT_SIZE; + } + + static int stylePaddingOffset(YogaEdge edge) { + return stylePadding + edge.intValue() * VALUE_SIZE; + } + + static int layoutPaddingOffset(YogaEdge edge) { + return layoutPadding + edge.intValue() * FLOAT_SIZE; + } + + static int styleBorderOffset(YogaEdge edge) { + return styleBorder + edge.intValue() * VALUE_SIZE; + } + + static int layoutBorderOffset(YogaEdge edge) { + return layoutBorder + edge.intValue() * FLOAT_SIZE; + } + + static void putOptional(ByteBuffer buffer, int offset, float value) { + buffer.putFloat(offset, value); + buffer.put( + offset + FLOAT_SIZE, YogaConstants.isUndefined(value) ? TRUE : FALSE); // bool isUndefined_ + } + + static float getOptional(ByteBuffer buffer, int offset) { + return getBoolean(buffer, offset + FLOAT_SIZE) + ? YogaConstants.UNDEFINED + : buffer.getFloat(offset); + } + + private static void putValue(ByteBuffer buffer, int offset, float value, int unit) { + if (YogaConstants.isUndefined(value)) { + value = YogaConstants.UNDEFINED; + unit = UNDEFINED; + } + buffer.putFloat(offset, value); + buffer.putInt(offset + FLOAT_SIZE, unit); + } + + static void putAutoValue(ByteBuffer buffer, int offset) { + putValue(buffer, offset, 0, AUTO); + } + + static void putPointValue(ByteBuffer buffer, int offset, float value) { + putValue(buffer, offset, value, POINT); + } + + static void putPercentValue(ByteBuffer buffer, int offset, float value) { + putValue(buffer, offset, value, PERCENT); + } + + static YogaValue getValue(ByteBuffer buffer, int offset) { + float value = buffer.getFloat(offset); + int unit = buffer.getInt(offset + FLOAT_SIZE); + return new YogaValue(value, YogaUnit.fromInt(unit)); + } + + static boolean getBoolean(ByteBuffer buffer, int offset) { + return buffer.get(offset) != 0; + } +} diff --git a/java/com/facebook/yoga/YogaNodeProperties.java b/java/com/facebook/yoga/YogaNodeProperties.java index 834aa833..c93145e4 100644 --- a/java/com/facebook/yoga/YogaNodeProperties.java +++ b/java/com/facebook/yoga/YogaNodeProperties.java @@ -13,7 +13,7 @@ public interface YogaNodeProperties { long getNativePointer(); - void onAfterCalculateLayout(); + void onAfterCalculateLayout(boolean hasNewLayout); void reset(); diff --git a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java new file mode 100644 index 00000000..b792062b --- /dev/null +++ b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +@DoNotStrip +public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneable { + + static { + SoLoader.loadLibrary("yoga"); + } + + private static final int RTL = YogaDirection.RTL.intValue(); + private final ByteBuffer mStyleBuffer; + private final ByteBuffer mLayoutBuffer; + private final long mNativePointer; + private boolean mHasBorderSet = false; + private boolean mHasNewLayout = true; + + private static native ByteBuffer jni_getStyleBuffer(long nativePointer); + + private static native ByteBuffer jni_getLayoutBuffer(long nativePointer); + + private static native long jni_YGNodeNewByteBuffer(YogaNode node); + + public YogaNodePropertiesByteBuffer(YogaNode node) { + this(jni_YGNodeNewByteBuffer(node)); + } + + private static native long jni_YGNodeNewByteBufferWithConfig(YogaNode node, long configPointer); + + public YogaNodePropertiesByteBuffer(YogaNode node, YogaConfig config) { + this(jni_YGNodeNewByteBufferWithConfig(node, config.mNativePointer)); + } + + public YogaNodePropertiesByteBuffer(long nativePointer) { + mNativePointer = nativePointer; + mStyleBuffer = jni_getStyleBuffer(nativePointer).order(ByteOrder.LITTLE_ENDIAN); + mLayoutBuffer = jni_getLayoutBuffer(nativePointer).order(ByteOrder.LITTLE_ENDIAN); + } + + private static native void jni_YGNodeFree(long nativePointer); + + @Override + protected void finalize() throws Throwable { + try { + jni_YGNodeFree(getNativePointer()); + } finally { + super.finalize(); + } + } + + private static native long jni_YGNodeCloneNoProps(long nativePointer, YogaNode newNode); + + @Override + public YogaNodeProperties clone(YogaNode node) { + long clonedNativePointer = jni_YGNodeCloneNoProps(getNativePointer(), node); + YogaNodePropertiesByteBuffer clone = new YogaNodePropertiesByteBuffer(clonedNativePointer); + clone.mHasBorderSet = mHasBorderSet; + clone.mHasNewLayout = mHasNewLayout; + return clone; + } + + @Override + public long getNativePointer() { + return mNativePointer; + } + + @Override + public void onAfterCalculateLayout(boolean hasNewLayout) { + mHasNewLayout = hasNewLayout; + } + + private static native void jni_YGNodeReset(long nativePointer); + + @Override + public void reset() { + mHasBorderSet = false; + jni_YGNodeReset(getNativePointer()); + } + + @Override + public boolean hasNewLayout() { + return mHasNewLayout; + } + + private static native boolean jni_YGNodeIsDirty(long nativePointer); + + @Override + public boolean isDirty() { + return jni_YGNodeIsDirty(mNativePointer); + } + + @Override + public void markLayoutSeen() { + mHasNewLayout = false; + } + + @Override + public YogaDirection getStyleDirection() { + return YogaDirection.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleDirection)); + } + + @Override + public YogaValue getPosition(YogaEdge edge) { + return YogaNodeMemoryLayout.getValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge)); + } + + @Override + public YogaValue getMargin(YogaEdge edge) { + return YogaNodeMemoryLayout.getValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); + } + + @Override + public YogaValue getPadding(YogaEdge edge) { + return YogaNodeMemoryLayout.getValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge)); + } + + @Override + public float getBorder(YogaEdge edge) { + return mHasBorderSet + ? mStyleBuffer.getFloat(YogaNodeMemoryLayout.styleBorderOffset(edge)) + : YogaConstants.UNDEFINED; + } + + @Override + public void setDirection(YogaDirection direction) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); + } + + @Override + public YogaFlexDirection getFlexDirection() { + return YogaFlexDirection.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleFlexDirection)); + } + + @Override + public void setFlexDirection(YogaFlexDirection flexDirection) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); + } + + @Override + public YogaJustify getJustifyContent() { + return YogaJustify.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleJustifyContent)); + } + + @Override + public void setJustifyContent(YogaJustify justifyContent) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); + } + + @Override + public YogaAlign getAlignItems() { + return YogaAlign.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleAlignItems)); + } + + @Override + public void setAlignItems(YogaAlign alignItems) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); + } + + @Override + public YogaAlign getAlignSelf() { + return YogaAlign.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleAlignSelf)); + } + + @Override + public void setAlignSelf(YogaAlign alignSelf) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); + } + + @Override + public YogaAlign getAlignContent() { + return YogaAlign.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleAlignContent)); + } + + @Override + public void setAlignContent(YogaAlign alignContent) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); + } + + @Override + public YogaPositionType getPositionType() { + return YogaPositionType.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.stylePositionType)); + } + + @Override + public void setPositionType(YogaPositionType positionType) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); + } + + @Override + public void setWrap(YogaWrap flexWrap) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); + } + + @Override + public YogaOverflow getOverflow() { + return YogaOverflow.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleOverflow)); + } + + @Override + public void setOverflow(YogaOverflow overflow) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); + } + + @Override + public YogaDisplay getDisplay() { + return YogaDisplay.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleDisplay)); + } + + @Override + public void setDisplay(YogaDisplay display) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); + } + + @Override + public void setFlex(float flex) { + YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlex, flex); + } + + @Override + public float getFlexGrow() { + return mStyleBuffer.getFloat(YogaNodeMemoryLayout.styleFlexGrow); + } + + @Override + public void setFlexGrow(float flexGrow) { + YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlexGrow, flexGrow); + } + + @Override + public float getFlexShrink() { + return mStyleBuffer.getFloat(YogaNodeMemoryLayout.styleFlexShrink); + } + + @Override + public void setFlexShrink(float flexShrink) { + YogaNodeMemoryLayout.putOptional( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexShrink, flexShrink); + } + + @Override + public YogaValue getFlexBasis() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); + } + + @Override + public void setFlexBasis(float flexBasis) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, flexBasis); + } + + @Override + public void setFlexBasisPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, percent); + } + + @Override + public void setFlexBasisAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); + } + + @Override + public void setMargin(YogaEdge edge, float margin) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), margin); + } + + @Override + public void setMarginPercent(YogaEdge edge, float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), percent); + } + + @Override + public void setMarginAuto(YogaEdge edge) { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); + } + + @Override + public void setPadding(YogaEdge edge, float padding) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); + } + + @Override + public void setPaddingPercent(YogaEdge edge, float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); + } + + @Override + public void setBorder(YogaEdge edge, float border) { + mHasBorderSet = true; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleBorderOffset(edge), border); + } + + @Override + public void setPosition(YogaEdge edge, float position) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), position); + } + + @Override + public void setPositionPercent(YogaEdge edge, float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), percent); + } + + @Override + public YogaValue getWidth() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); + } + + @Override + public void setWidth(float width) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, width); + } + + @Override + public void setWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, percent); + } + + @Override + public void setWidthAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); + } + + @Override + public YogaValue getHeight() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); + } + + @Override + public void setHeight(float height) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, height); + } + + @Override + public void setHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, percent); + } + + @Override + public void setHeightAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); + } + + @Override + public YogaValue getMinWidth() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth); + } + + @Override + public void setMinWidth(float minWidth) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, minWidth); + } + + @Override + public void setMinWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, percent); + } + + @Override + public YogaValue getMinHeight() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight); + } + + @Override + public void setMinHeight(float minHeight) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, minHeight); + } + + @Override + public void setMinHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, percent); + } + + @Override + public YogaValue getMaxWidth() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth); + } + + @Override + public void setMaxWidth(float maxWidth) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, maxWidth); + } + + @Override + public void setMaxWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, percent); + } + + @Override + public YogaValue getMaxHeight() { + return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight); + } + + @Override + public void setMaxHeight(float maxHeight) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, maxHeight); + } + + @Override + public void setMaxHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, percent); + } + + @Override + public float getAspectRatio() { + return YogaNodeMemoryLayout.getOptional(mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio); + } + + @Override + public void setAspectRatio(float aspectRatio) { + YogaNodeMemoryLayout.putOptional( + mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); + } + + @Override + public float getLayoutX() { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutX); + } + + @Override + public float getLayoutY() { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutY); + } + + @Override + public float getLayoutWidth() { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutWidth); + } + + @Override + public float getLayoutHeight() { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutHeight); + } + + @Override + public boolean getDoesLegacyStretchFlagAffectsLayout() { + return YogaNodeMemoryLayout.getBoolean( + mLayoutBuffer, YogaNodeMemoryLayout.layoutDoesLegacyStretchFlagAffectsLayout); + } + + @Override + public float getLayoutMargin(YogaEdge edge) { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutMarginOffset(layoutEdge(edge))); + } + + @Override + public float getLayoutPadding(YogaEdge edge) { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutPaddingOffset(layoutEdge(edge))); + } + + @Override + public float getLayoutBorder(YogaEdge edge) { + return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutBorderOffset(layoutEdge(edge))); + } + + @Override + public YogaDirection getLayoutDirection() { + return YogaDirection.fromInt(getLayoutDirectionInt()); + } + + @Override + public void freeNatives() { + jni_YGNodeFree(mNativePointer); + } + + private int getLayoutDirectionInt() { + return mLayoutBuffer.getInt(YogaNodeMemoryLayout.layoutDirection); + } + + private YogaEdge layoutEdge(YogaEdge edge) { + int layoutDirection = getLayoutDirectionInt(); + switch (edge) { + case LEFT: + return layoutDirection == RTL ? YogaEdge.END : YogaEdge.START; + case RIGHT: + return layoutDirection == RTL ? YogaEdge.START : YogaEdge.END; + case TOP: + case BOTTOM: + case START: + case END: + return edge; + default: + throw new IllegalArgumentException("Cannot get layout properties of multi-edge shorthands"); + } + } +} diff --git a/java/com/facebook/yoga/YogaNodePropertiesJNI.java b/java/com/facebook/yoga/YogaNodePropertiesJNI.java index d44cd1d2..3ce7b493 100644 --- a/java/com/facebook/yoga/YogaNodePropertiesJNI.java +++ b/java/com/facebook/yoga/YogaNodePropertiesJNI.java @@ -10,6 +10,7 @@ package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.soloader.SoLoader; +@DoNotStrip public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { static { @@ -105,7 +106,7 @@ public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { private static native void jni_YGTransferLayoutOutputsRecursive(long nativePointer); @Override - public void onAfterCalculateLayout() { + public void onAfterCalculateLayout(boolean hasNewLayoutIgnoredSetByNative) { jni_YGTransferLayoutOutputsRecursive(mNativePointer); } diff --git a/java/com/facebook/yoga/YogaValue.java b/java/com/facebook/yoga/YogaValue.java index c0bb6e22..27781a15 100644 --- a/java/com/facebook/yoga/YogaValue.java +++ b/java/com/facebook/yoga/YogaValue.java @@ -33,7 +33,9 @@ public class YogaValue { if (other instanceof YogaValue) { final YogaValue otherValue = (YogaValue) other; if (unit == otherValue.unit) { - return unit == YogaUnit.UNDEFINED || Float.compare(value, otherValue.value) == 0; + return unit == YogaUnit.UNDEFINED + || unit == YogaUnit.AUTO + || Float.compare(value, otherValue.value) == 0; } } return false; diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index dc38500e..d83f7034 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -6,6 +6,7 @@ * */ #include +#include #include #include #include @@ -26,6 +27,12 @@ struct JYogaNodePropertiesJNI : public JavaClass { "Lcom/facebook/yoga/YogaNodePropertiesJNI;"; }; +struct JYogaNodePropertiesByteBuffer + : public JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/yoga/YogaNodePropertiesByteBuffer"; +}; + struct YGConfigContext { global_ref* logger; global_ref* config; @@ -331,6 +338,19 @@ jlong jni_YGNodeNewWithConfig( return reinterpret_cast(node); } +jlong jni_YGNodeNewByteBuffer( + alias_ref, + alias_ref javaNode) { + return jni_YGNodeNew(nullptr, javaNode); +} + +jlong jni_YGNodeNewByteBufferWithConfig( + alias_ref, + alias_ref javaNode, + jlong configPointer) { + return jni_YGNodeNewWithConfig(nullptr, javaNode, configPointer); +} + void jni_YGNodeSetOwner( alias_ref thiz, jlong nativePointer, @@ -351,6 +371,13 @@ jlong jni_YGNodeClone( return reinterpret_cast(clonedYogaNode); } +jlong jni_YGNodeCloneNoProps( + alias_ref cls, + jlong nativePointer, + alias_ref clonedJavaObject) { + return jni_YGNodeClone(cls, nativePointer, clonedJavaObject, nullptr); +} + void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); delete reinterpret_cast(node->getContext()); @@ -404,7 +431,7 @@ void jni_YGNodeRemoveChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } -void jni_YGNodeCalculateLayout( +jboolean jni_YGNodeCalculateLayout( alias_ref, jlong nativePointer, jfloat width, @@ -415,6 +442,7 @@ void jni_YGNodeCalculateLayout( static_cast(width), static_cast(height), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); + return root->getHasNewLayout(); } static void jni_YGTransferLayoutOutputsRecursive( @@ -694,6 +722,21 @@ void jni_YGConfigSetLogger( jint jni_YGNodeGetInstanceCount(alias_ref clazz) { return YGNodeGetInstanceCount(); } +local_ref jni_getStyleBuffer( + alias_ref, + jlong nativePointer) { + YGStyle* style = &_jlong2YGNodeRef(nativePointer)->getStyle(); + return JByteBuffer::wrapBytes( + reinterpret_cast(style), sizeof(YGStyle)); +} + +local_ref jni_getLayoutBuffer( + alias_ref, + jlong nativePointer) { + YGLayout* layout = &_jlong2YGNodeRef(nativePointer)->getLayout(); + return JByteBuffer::wrapBytes( + reinterpret_cast(layout), sizeof(YGLayout)); +} #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) @@ -803,5 +846,17 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod( jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), }); + registerNatives( + "com/facebook/yoga/YogaNodePropertiesByteBuffer", + { + YGMakeNativeMethod(jni_YGNodeCloneNoProps), + YGMakeNativeMethod(jni_YGNodeFree), + YGMakeNativeMethod(jni_YGNodeNewByteBuffer), + YGMakeNativeMethod(jni_YGNodeNewByteBufferWithConfig), + YGMakeNativeMethod(jni_YGNodeReset), + YGMakeNativeMethod(jni_YGNodeIsDirty), + YGMakeNativeMethod(jni_getStyleBuffer), + YGMakeNativeMethod(jni_getLayoutBuffer), + }); }); } diff --git a/java/tests/com/facebook/yoga/TestParametrization.java b/java/tests/com/facebook/yoga/TestParametrization.java new file mode 100644 index 00000000..f53f32b7 --- /dev/null +++ b/java/tests/com/facebook/yoga/TestParametrization.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import java.util.Arrays; + +public class TestParametrization { + public static Iterable nodeFactories() { + return Arrays.asList( + new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(); + } + + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(config); + } + + @Override + public String toString() { + return "JNI"; + } + }, + new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(true); + } + + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(true, config); + } + + @Override + public String toString() { + return "ByteBuffer"; + } + }); + } + + public interface NodeFactory { + YogaNode create(); + + YogaNode create(YogaConfig config); + } +} diff --git a/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java b/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java index c0590a52..ac42a041 100644 --- a/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java +++ b/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java @@ -9,20 +9,30 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGAbsolutePositionTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_absolute_layout_width_height_start_top() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.START, 10f); root_child0.setPosition(YogaEdge.TOP, 10f); @@ -60,11 +70,11 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_width_height_end_bottom() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.END, 10f); root_child0.setPosition(YogaEdge.BOTTOM, 10f); @@ -102,11 +112,11 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_start_top_end_bottom() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.START, 10f); root_child0.setPosition(YogaEdge.TOP, 10f); @@ -144,11 +154,11 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_width_height_start_top_end_bottom() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.START, 10f); root_child0.setPosition(YogaEdge.TOP, 10f); @@ -188,19 +198,19 @@ public class YGAbsolutePositionTest { public void test_do_not_clamp_height_of_absolute_node_to_height_of_its_overflow_hidden_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setOverflow(YogaOverflow.HIDDEN); root.setWidth(50f); root.setHeight(50f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.START, 0f); root_child0.setPosition(YogaEdge.TOP, 0f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(100f); root_child0_child0.setHeight(100f); root_child0.addChildAt(root_child0_child0, 0); @@ -245,7 +255,7 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_within_border() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setMargin(YogaEdge.LEFT, 10f); root.setMargin(YogaEdge.TOP, 10f); root.setMargin(YogaEdge.RIGHT, 10f); @@ -261,7 +271,7 @@ public class YGAbsolutePositionTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.LEFT, 0f); root_child0.setPosition(YogaEdge.TOP, 0f); @@ -269,7 +279,7 @@ public class YGAbsolutePositionTest { root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setPositionType(YogaPositionType.ABSOLUTE); root_child1.setPosition(YogaEdge.RIGHT, 0f); root_child1.setPosition(YogaEdge.BOTTOM, 0f); @@ -277,7 +287,7 @@ public class YGAbsolutePositionTest { root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setPositionType(YogaPositionType.ABSOLUTE); root_child2.setPosition(YogaEdge.LEFT, 0f); root_child2.setPosition(YogaEdge.TOP, 0f); @@ -289,7 +299,7 @@ public class YGAbsolutePositionTest { root_child2.setHeight(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setPositionType(YogaPositionType.ABSOLUTE); root_child3.setPosition(YogaEdge.RIGHT, 0f); root_child3.setPosition(YogaEdge.BOTTOM, 0f); @@ -361,14 +371,14 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_and_justify_content_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(60f); root_child0.setHeight(40f); @@ -404,14 +414,14 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_and_justify_content_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.FLEX_END); root.setAlignItems(YogaAlign.FLEX_END); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(60f); root_child0.setHeight(40f); @@ -447,13 +457,13 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_justify_content_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(60f); root_child0.setHeight(40f); @@ -489,13 +499,13 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(60f); root_child0.setHeight(40f); @@ -531,12 +541,12 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_center_on_child_only() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.CENTER); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(60f); @@ -573,14 +583,14 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_and_justify_content_center_and_top_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.TOP, 10f); root_child0.setWidth(60f); @@ -617,14 +627,14 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_and_justify_content_center_and_bottom_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.BOTTOM, 10f); root_child0.setWidth(60f); @@ -661,14 +671,14 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_and_justify_content_center_and_left_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.LEFT, 5f); root_child0.setWidth(60f); @@ -705,14 +715,14 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_align_items_and_justify_content_center_and_right_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setFlexGrow(1f); root.setWidth(110f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPosition(YogaEdge.RIGHT, 5f); root_child0.setWidth(60f); @@ -749,7 +759,7 @@ public class YGAbsolutePositionTest { public void test_position_root_with_rtl_should_position_withoutdirection() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPosition(YogaEdge.LEFT, 72f); root.setWidth(52f); root.setHeight(52f); @@ -774,25 +784,25 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_percentage_bottom_based_on_parent_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPositionPercent(YogaEdge.TOP, 50f); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setPositionType(YogaPositionType.ABSOLUTE); root_child1.setPositionPercent(YogaEdge.BOTTOM, 50f); root_child1.setWidth(10f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setPositionType(YogaPositionType.ABSOLUTE); root_child2.setPositionPercent(YogaEdge.TOP, 10f); root_child2.setPositionPercent(YogaEdge.BOTTOM, 10f); @@ -849,12 +859,12 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_in_wrap_reverse_column_container() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(20f); root_child0.setHeight(20f); @@ -890,13 +900,13 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_in_wrap_reverse_row_container() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(20f); root_child0.setHeight(20f); @@ -932,12 +942,12 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_in_wrap_reverse_column_container_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.FLEX_END); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(20f); @@ -974,13 +984,13 @@ public class YGAbsolutePositionTest { public void test_absolute_layout_in_wrap_reverse_row_container_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.FLEX_END); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setWidth(20f); @@ -1013,4 +1023,7 @@ public class YGAbsolutePositionTest { assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGAlignContentTest.java b/java/tests/com/facebook/yoga/YGAlignContentTest.java index c20f9767..82ef4cb0 100644 --- a/java/tests/com/facebook/yoga/YGAlignContentTest.java +++ b/java/tests/com/facebook/yoga/YGAlignContentTest.java @@ -9,42 +9,52 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGAlignContentTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_align_content_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP); root.setWidth(130f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(10f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root_child4.setHeight(10f); root.addChildAt(root_child4, 4); @@ -119,30 +129,30 @@ public class YGAlignContentTest { public void test_align_content_flex_start_without_height_on_children() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(10f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -216,36 +226,36 @@ public class YGAlignContentTest { public void test_align_content_flex_start_with_flex() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(120f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(0f); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexBasisPercent(0f); root_child1.setWidth(50f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setFlexGrow(1f); root_child3.setFlexShrink(1f); root_child3.setFlexBasisPercent(0f); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -319,33 +329,33 @@ public class YGAlignContentTest { public void test_align_content_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignContent(YogaAlign.FLEX_END); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(10f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root_child4.setHeight(10f); root.addChildAt(root_child4, 4); @@ -420,29 +430,29 @@ public class YGAlignContentTest { public void test_align_content_stretch() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -516,34 +526,34 @@ public class YGAlignContentTest { public void test_align_content_spacebetween() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.SPACE_BETWEEN); root.setWrap(YogaWrap.WRAP); root.setWidth(130f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(10f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root_child4.setHeight(10f); root.addChildAt(root_child4, 4); @@ -618,34 +628,34 @@ public class YGAlignContentTest { public void test_align_content_spacearound() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.SPACE_AROUND); root.setWrap(YogaWrap.WRAP); root.setWidth(140f); root.setHeight(120f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(10f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root_child4.setHeight(10f); root.addChildAt(root_child4, 4); @@ -720,30 +730,30 @@ public class YGAlignContentTest { public void test_align_content_stretch_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -817,36 +827,36 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_children() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0_child0.setFlexBasisPercent(0f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -930,36 +940,36 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_flex() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexShrink(1f); root_child1.setFlexBasisPercent(0f); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setFlexGrow(1f); root_child3.setFlexShrink(1f); root_child3.setFlexBasisPercent(0f); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1033,35 +1043,35 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_flex_no_shrink() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexShrink(1f); root_child1.setFlexBasisPercent(0f); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setFlexGrow(1f); root_child3.setFlexBasisPercent(0f); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1135,18 +1145,18 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setMargin(YogaEdge.LEFT, 10f); root_child1.setMargin(YogaEdge.TOP, 10f); root_child1.setMargin(YogaEdge.RIGHT, 10f); @@ -1154,11 +1164,11 @@ public class YGAlignContentTest { root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setMargin(YogaEdge.LEFT, 10f); root_child3.setMargin(YogaEdge.TOP, 10f); root_child3.setMargin(YogaEdge.RIGHT, 10f); @@ -1166,7 +1176,7 @@ public class YGAlignContentTest { root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1240,18 +1250,18 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_padding() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setPadding(YogaEdge.LEFT, 10); root_child1.setPadding(YogaEdge.TOP, 10); root_child1.setPadding(YogaEdge.RIGHT, 10); @@ -1259,11 +1269,11 @@ public class YGAlignContentTest { root_child1.setWidth(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setPadding(YogaEdge.LEFT, 10); root_child3.setPadding(YogaEdge.TOP, 10); root_child3.setPadding(YogaEdge.RIGHT, 10); @@ -1271,7 +1281,7 @@ public class YGAlignContentTest { root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1345,18 +1355,18 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_single_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -1400,31 +1410,31 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_fixed_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(60f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1498,31 +1508,31 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_max_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setMaxHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1596,31 +1606,31 @@ public class YGAlignContentTest { public void test_align_content_stretch_row_with_min_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setMinHeight(80f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1694,38 +1704,38 @@ public class YGAlignContentTest { public void test_align_content_stretch_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(150f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0_child0.setFlexBasisPercent(0f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexShrink(1f); root_child1.setFlexBasisPercent(0f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(50f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setHeight(50f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -1809,10 +1819,10 @@ public class YGAlignContentTest { public void test_align_content_stretch_is_not_overriding_align_items() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignContent(YogaAlign.STRETCH); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setAlignContent(YogaAlign.STRETCH); root_child0.setAlignItems(YogaAlign.CENTER); @@ -1820,7 +1830,7 @@ public class YGAlignContentTest { root_child0.setHeight(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0.setWidth(10f); root_child0_child0.setHeight(10f); @@ -1862,4 +1872,7 @@ public class YGAlignContentTest { assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGAlignItemsTest.java b/java/tests/com/facebook/yoga/YGAlignItemsTest.java index 0cc5ba45..2a65b735 100644 --- a/java/tests/com/facebook/yoga/YGAlignItemsTest.java +++ b/java/tests/com/facebook/yoga/YGAlignItemsTest.java @@ -9,20 +9,30 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGAlignItemsTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_align_items_stretch() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); root.setDirection(YogaDirection.LTR); @@ -56,12 +66,12 @@ public class YGAlignItemsTest { public void test_align_items_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -96,12 +106,12 @@ public class YGAlignItemsTest { public void test_align_items_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.FLEX_START); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -136,12 +146,12 @@ public class YGAlignItemsTest { public void test_align_items_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.FLEX_END); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -176,18 +186,18 @@ public class YGAlignItemsTest { public void test_align_baseline() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); @@ -232,23 +242,23 @@ public class YGAlignItemsTest { public void test_align_baseline_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); @@ -303,40 +313,40 @@ public class YGAlignItemsTest { public void test_align_baseline_child_multiline() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexDirection(YogaFlexDirection.ROW); root_child1.setWrap(YogaWrap.WRAP); root_child1.setWidth(50f); root_child1.setHeight(25f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(25f); root_child1_child0.setHeight(20f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child1_child1 = new YogaNode(config); + final YogaNode root_child1_child1 = createNode(config); root_child1_child1.setWidth(25f); root_child1_child1.setHeight(10f); root_child1.addChildAt(root_child1_child1, 1); - final YogaNode root_child1_child2 = new YogaNode(config); + final YogaNode root_child1_child2 = createNode(config); root_child1_child2.setWidth(25f); root_child1_child2.setHeight(20f); root_child1.addChildAt(root_child1_child2, 2); - final YogaNode root_child1_child3 = new YogaNode(config); + final YogaNode root_child1_child3 = createNode(config); root_child1_child3.setWidth(25f); root_child1_child3.setHeight(10f); root_child1.addChildAt(root_child1_child3, 3); @@ -421,41 +431,41 @@ public class YGAlignItemsTest { public void test_align_baseline_child_multiline_override() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexDirection(YogaFlexDirection.ROW); root_child1.setWrap(YogaWrap.WRAP); root_child1.setWidth(50f); root_child1.setHeight(25f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(25f); root_child1_child0.setHeight(20f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child1_child1 = new YogaNode(config); + final YogaNode root_child1_child1 = createNode(config); root_child1_child1.setAlignSelf(YogaAlign.BASELINE); root_child1_child1.setWidth(25f); root_child1_child1.setHeight(10f); root_child1.addChildAt(root_child1_child1, 1); - final YogaNode root_child1_child2 = new YogaNode(config); + final YogaNode root_child1_child2 = createNode(config); root_child1_child2.setWidth(25f); root_child1_child2.setHeight(20f); root_child1.addChildAt(root_child1_child2, 2); - final YogaNode root_child1_child3 = new YogaNode(config); + final YogaNode root_child1_child3 = createNode(config); root_child1_child3.setAlignSelf(YogaAlign.BASELINE); root_child1_child3.setWidth(25f); root_child1_child3.setHeight(10f); @@ -541,40 +551,40 @@ public class YGAlignItemsTest { public void test_align_baseline_child_multiline_no_override_on_secondline() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexDirection(YogaFlexDirection.ROW); root_child1.setWrap(YogaWrap.WRAP); root_child1.setWidth(50f); root_child1.setHeight(25f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(25f); root_child1_child0.setHeight(20f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child1_child1 = new YogaNode(config); + final YogaNode root_child1_child1 = createNode(config); root_child1_child1.setWidth(25f); root_child1_child1.setHeight(10f); root_child1.addChildAt(root_child1_child1, 1); - final YogaNode root_child1_child2 = new YogaNode(config); + final YogaNode root_child1_child2 = createNode(config); root_child1_child2.setWidth(25f); root_child1_child2.setHeight(20f); root_child1.addChildAt(root_child1_child2, 2); - final YogaNode root_child1_child3 = new YogaNode(config); + final YogaNode root_child1_child3 = createNode(config); root_child1_child3.setAlignSelf(YogaAlign.BASELINE); root_child1_child3.setWidth(25f); root_child1_child3.setHeight(10f); @@ -660,24 +670,24 @@ public class YGAlignItemsTest { public void test_align_baseline_child_top() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPosition(YogaEdge.TOP, 10f); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); @@ -732,24 +742,24 @@ public class YGAlignItemsTest { public void test_align_baseline_child_top2() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setPosition(YogaEdge.TOP, 5f); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); @@ -804,28 +814,28 @@ public class YGAlignItemsTest { public void test_align_baseline_double_nested_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(50f); root_child0_child0.setHeight(20f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(15f); root_child1.addChildAt(root_child1_child0, 0); @@ -890,17 +900,17 @@ public class YGAlignItemsTest { public void test_align_baseline_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); @@ -945,13 +955,13 @@ public class YGAlignItemsTest { public void test_align_baseline_child_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.LEFT, 5f); root_child0.setMargin(YogaEdge.TOP, 5f); root_child0.setMargin(YogaEdge.RIGHT, 5f); @@ -960,12 +970,12 @@ public class YGAlignItemsTest { root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setMargin(YogaEdge.LEFT, 1f); root_child1_child0.setMargin(YogaEdge.TOP, 1f); root_child1_child0.setMargin(YogaEdge.RIGHT, 1f); @@ -1024,7 +1034,7 @@ public class YGAlignItemsTest { public void test_align_baseline_child_padding() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setPadding(YogaEdge.LEFT, 5); @@ -1034,12 +1044,12 @@ public class YGAlignItemsTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setPadding(YogaEdge.LEFT, 5); root_child1.setPadding(YogaEdge.TOP, 5); root_child1.setPadding(YogaEdge.RIGHT, 5); @@ -1048,7 +1058,7 @@ public class YGAlignItemsTest { root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); @@ -1103,39 +1113,39 @@ public class YGAlignItemsTest { public void test_align_baseline_multiline() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(20f); root.addChildAt(root_child2, 2); - final YogaNode root_child2_child0 = new YogaNode(config); + final YogaNode root_child2_child0 = createNode(config); root_child2_child0.setWidth(50f); root_child2_child0.setHeight(10f); root_child2.addChildAt(root_child2_child0, 0); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(50f); root.addChildAt(root_child3, 3); @@ -1220,38 +1230,38 @@ public class YGAlignItemsTest { public void test_align_baseline_multiline_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.BASELINE); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(20f); root_child1_child0.setHeight(20f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(40f); root_child2.setHeight(70f); root.addChildAt(root_child2, 2); - final YogaNode root_child2_child0 = new YogaNode(config); + final YogaNode root_child2_child0 = createNode(config); root_child2_child0.setWidth(10f); root_child2_child0.setHeight(10f); root_child2.addChildAt(root_child2_child0, 0); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(20f); root.addChildAt(root_child3, 3); @@ -1336,38 +1346,38 @@ public class YGAlignItemsTest { public void test_align_baseline_multiline_column2() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.BASELINE); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(20f); root_child1_child0.setHeight(20f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(40f); root_child2.setHeight(70f); root.addChildAt(root_child2, 2); - final YogaNode root_child2_child0 = new YogaNode(config); + final YogaNode root_child2_child0 = createNode(config); root_child2_child0.setWidth(10f); root_child2_child0.setHeight(10f); root_child2.addChildAt(root_child2_child0, 0); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(20f); root.addChildAt(root_child3, 3); @@ -1452,39 +1462,39 @@ public class YGAlignItemsTest { public void test_align_baseline_multiline_row_and_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(20f); root.addChildAt(root_child2, 2); - final YogaNode root_child2_child0 = new YogaNode(config); + final YogaNode root_child2_child0 = createNode(config); root_child2_child0.setWidth(50f); root_child2_child0.setHeight(10f); root_child2.addChildAt(root_child2_child0, 0); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(50f); root_child3.setHeight(20f); root.addChildAt(root_child3, 3); @@ -1569,17 +1579,17 @@ public class YGAlignItemsTest { public void test_align_items_center_child_with_margin_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.CENTER); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setMargin(YogaEdge.LEFT, 10f); root_child0_child0.setMargin(YogaEdge.RIGHT, 10f); root_child0_child0.setWidth(52f); @@ -1626,17 +1636,17 @@ public class YGAlignItemsTest { public void test_align_items_flex_end_child_with_margin_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.FLEX_END); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setMargin(YogaEdge.LEFT, 10f); root_child0_child0.setMargin(YogaEdge.RIGHT, 10f); root_child0_child0.setWidth(52f); @@ -1683,17 +1693,17 @@ public class YGAlignItemsTest { public void test_align_items_center_child_without_margin_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.CENTER); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(72f); root_child0_child0.setHeight(72f); root_child0.addChildAt(root_child0_child0, 0); @@ -1738,17 +1748,17 @@ public class YGAlignItemsTest { public void test_align_items_flex_end_child_without_margin_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.FLEX_END); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(72f); root_child0_child0.setHeight(72f); root_child0.addChildAt(root_child0_child0, 0); @@ -1793,23 +1803,23 @@ public class YGAlignItemsTest { public void test_align_center_should_size_based_on_content() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setMargin(YogaEdge.TOP, 20f); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setJustifyContent(YogaJustify.CENTER); root_child0.setFlexShrink(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setWidth(20f); root_child0_child0_child0.setHeight(20f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); @@ -1864,22 +1874,22 @@ public class YGAlignItemsTest { public void test_align_strech_should_size_based_on_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setMargin(YogaEdge.TOP, 20f); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setJustifyContent(YogaJustify.CENTER); root_child0.setFlexShrink(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setWidth(20f); root_child0_child0_child0.setHeight(20f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); @@ -1934,20 +1944,20 @@ public class YGAlignItemsTest { public void test_align_flex_start_with_shrinking_children() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(500f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.FLEX_START); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setFlexGrow(1f); root_child0_child0_child0.setFlexShrink(1f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); @@ -2002,19 +2012,19 @@ public class YGAlignItemsTest { public void test_align_flex_start_with_stretching_children() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(500f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setFlexGrow(1f); root_child0_child0_child0.setFlexShrink(1f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); @@ -2069,20 +2079,20 @@ public class YGAlignItemsTest { public void test_align_flex_start_with_shrinking_children_with_stretch() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(500f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.FLEX_START); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setFlexGrow(1f); root_child0_child0_child0.setFlexShrink(1f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); @@ -2133,4 +2143,7 @@ public class YGAlignItemsTest { assertEquals(0f, root_child0_child0_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGAlignSelfTest.java b/java/tests/com/facebook/yoga/YGAlignSelfTest.java index d7ea10a6..ebf000a9 100644 --- a/java/tests/com/facebook/yoga/YGAlignSelfTest.java +++ b/java/tests/com/facebook/yoga/YGAlignSelfTest.java @@ -9,20 +9,30 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGAlignSelfTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_align_self_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.CENTER); root_child0.setWidth(10f); root_child0.setHeight(10f); @@ -58,11 +68,11 @@ public class YGAlignSelfTest { public void test_align_self_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.FLEX_END); root_child0.setWidth(10f); root_child0.setHeight(10f); @@ -98,11 +108,11 @@ public class YGAlignSelfTest { public void test_align_self_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.FLEX_START); root_child0.setWidth(10f); root_child0.setHeight(10f); @@ -138,12 +148,12 @@ public class YGAlignSelfTest { public void test_align_self_flex_end_override_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.FLEX_START); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.FLEX_END); root_child0.setWidth(10f); root_child0.setHeight(10f); @@ -179,24 +189,24 @@ public class YGAlignSelfTest { public void test_align_self_baseline() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setAlignSelf(YogaAlign.BASELINE); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setAlignSelf(YogaAlign.BASELINE); root_child1.setWidth(50f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidth(50f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); @@ -247,4 +257,7 @@ public class YGAlignSelfTest { assertEquals(10f, root_child1_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGAndroidNewsFeed.java b/java/tests/com/facebook/yoga/YGAndroidNewsFeed.java index 54c5ac1d..fcf1214a 100644 --- a/java/tests/com/facebook/yoga/YGAndroidNewsFeed.java +++ b/java/tests/com/facebook/yoga/YGAndroidNewsFeed.java @@ -12,28 +12,38 @@ package com.facebook.yoga; import static org.junit.Assert.assertEquals; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +@RunWith(Parameterized.class) public class YGAndroidNewsFeed { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_android_news_feed() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignContent(YogaAlign.STRETCH); root.setWidth(1080f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0.addChildAt(root_child0_child0_child0, 0); - final YogaNode root_child0_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0_child0 = createNode(config); root_child0_child0_child0_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child0_child0.setAlignItems(YogaAlign.FLEX_START); @@ -41,19 +51,19 @@ public class YGAndroidNewsFeed { root_child0_child0_child0_child0.setMargin(YogaEdge.TOP, 24f); root_child0_child0_child0.addChildAt(root_child0_child0_child0_child0, 0); - final YogaNode root_child0_child0_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0_child0_child0 = createNode(config); root_child0_child0_child0_child0_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child0_child0.addChildAt(root_child0_child0_child0_child0_child0, 0); - final YogaNode root_child0_child0_child0_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0_child0_child0_child0 = createNode(config); root_child0_child0_child0_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child0_child0_child0_child0.setWidth(120f); root_child0_child0_child0_child0_child0_child0.setHeight(120f); root_child0_child0_child0_child0_child0.addChildAt( root_child0_child0_child0_child0_child0_child0, 0); - final YogaNode root_child0_child0_child0_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child0_child0_child0_child1 = createNode(config); root_child0_child0_child0_child0_child1.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child0_child0_child1.setFlexShrink(1f); root_child0_child0_child0_child0_child1.setMargin(YogaEdge.RIGHT, 36f); @@ -63,24 +73,24 @@ public class YGAndroidNewsFeed { root_child0_child0_child0_child0_child1.setPadding(YogaEdge.BOTTOM, 18); root_child0_child0_child0_child0.addChildAt(root_child0_child0_child0_child0_child1, 1); - final YogaNode root_child0_child0_child0_child0_child1_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0_child0_child1_child0 = createNode(config); root_child0_child0_child0_child0_child1_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0_child0_child0_child1_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child0_child0_child1_child0.setFlexShrink(1f); root_child0_child0_child0_child0_child1.addChildAt( root_child0_child0_child0_child0_child1_child0, 0); - final YogaNode root_child0_child0_child0_child0_child1_child1 = new YogaNode(config); + final YogaNode root_child0_child0_child0_child0_child1_child1 = createNode(config); root_child0_child0_child0_child0_child1_child1.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child0_child0_child1_child1.setFlexShrink(1f); root_child0_child0_child0_child0_child1.addChildAt( root_child0_child0_child0_child0_child1_child1, 1); - final YogaNode root_child0_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child0_child1 = createNode(config); root_child0_child0_child1.setAlignContent(YogaAlign.STRETCH); root_child0_child0.addChildAt(root_child0_child0_child1, 1); - final YogaNode root_child0_child0_child1_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child1_child0 = createNode(config); root_child0_child0_child1_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0_child1_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child1_child0.setAlignItems(YogaAlign.FLEX_START); @@ -88,19 +98,19 @@ public class YGAndroidNewsFeed { root_child0_child0_child1_child0.setMargin(YogaEdge.TOP, 24f); root_child0_child0_child1.addChildAt(root_child0_child0_child1_child0, 0); - final YogaNode root_child0_child0_child1_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child1_child0_child0 = createNode(config); root_child0_child0_child1_child0_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0_child1_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child1_child0.addChildAt(root_child0_child0_child1_child0_child0, 0); - final YogaNode root_child0_child0_child1_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child1_child0_child0_child0 = createNode(config); root_child0_child0_child1_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child1_child0_child0_child0.setWidth(72f); root_child0_child0_child1_child0_child0_child0.setHeight(72f); root_child0_child0_child1_child0_child0.addChildAt( root_child0_child0_child1_child0_child0_child0, 0); - final YogaNode root_child0_child0_child1_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child0_child1_child0_child1 = createNode(config); root_child0_child0_child1_child0_child1.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child1_child0_child1.setFlexShrink(1f); root_child0_child0_child1_child0_child1.setMargin(YogaEdge.RIGHT, 36f); @@ -110,14 +120,14 @@ public class YGAndroidNewsFeed { root_child0_child0_child1_child0_child1.setPadding(YogaEdge.BOTTOM, 18); root_child0_child0_child1_child0.addChildAt(root_child0_child0_child1_child0_child1, 1); - final YogaNode root_child0_child0_child1_child0_child1_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child1_child0_child1_child0 = createNode(config); root_child0_child0_child1_child0_child1_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0_child1_child0_child1_child0.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child1_child0_child1_child0.setFlexShrink(1f); root_child0_child0_child1_child0_child1.addChildAt( root_child0_child0_child1_child0_child1_child0, 0); - final YogaNode root_child0_child0_child1_child0_child1_child1 = new YogaNode(config); + final YogaNode root_child0_child0_child1_child0_child1_child1 = createNode(config); root_child0_child0_child1_child0_child1_child1.setAlignContent(YogaAlign.STRETCH); root_child0_child0_child1_child0_child1_child1.setFlexShrink(1f); root_child0_child0_child1_child0_child1.addChildAt( @@ -298,4 +308,8 @@ public class YGAndroidNewsFeed { assertEquals(0f, root_child0_child0_child1_child0_child1_child1.getLayoutWidth(), 0.0f); assertEquals(0f, root_child0_child0_child1_child0_child1_child1.getLayoutHeight(), 0.0f); } + + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGBorderTest.java b/java/tests/com/facebook/yoga/YGBorderTest.java index 18a7431e..b75ad9a1 100644 --- a/java/tests/com/facebook/yoga/YGBorderTest.java +++ b/java/tests/com/facebook/yoga/YGBorderTest.java @@ -9,16 +9,26 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGBorderTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_border_no_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setBorder(YogaEdge.LEFT, 10f); root.setBorder(YogaEdge.TOP, 10f); root.setBorder(YogaEdge.RIGHT, 10f); @@ -44,13 +54,13 @@ public class YGBorderTest { public void test_border_container_match_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setBorder(YogaEdge.LEFT, 10f); root.setBorder(YogaEdge.TOP, 10f); root.setBorder(YogaEdge.RIGHT, 10f); root.setBorder(YogaEdge.BOTTOM, 10f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -85,7 +95,7 @@ public class YGBorderTest { public void test_border_flex_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setBorder(YogaEdge.LEFT, 10f); root.setBorder(YogaEdge.TOP, 10f); root.setBorder(YogaEdge.RIGHT, 10f); @@ -93,7 +103,7 @@ public class YGBorderTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); @@ -128,7 +138,7 @@ public class YGBorderTest { public void test_border_stretch_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setBorder(YogaEdge.LEFT, 10f); root.setBorder(YogaEdge.TOP, 10f); root.setBorder(YogaEdge.RIGHT, 10f); @@ -136,7 +146,7 @@ public class YGBorderTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); root.setDirection(YogaDirection.LTR); @@ -170,7 +180,7 @@ public class YGBorderTest { public void test_border_center_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setBorder(YogaEdge.START, 10f); @@ -179,7 +189,7 @@ public class YGBorderTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -210,4 +220,7 @@ public class YGBorderTest { assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGDimensionTest.java b/java/tests/com/facebook/yoga/YGDimensionTest.java index d9cfbea2..21b20356 100644 --- a/java/tests/com/facebook/yoga/YGDimensionTest.java +++ b/java/tests/com/facebook/yoga/YGDimensionTest.java @@ -9,18 +9,28 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGDimensionTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_wrap_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(100f); root_child0.setHeight(100f); root.addChildAt(root_child0, 0); @@ -55,12 +65,12 @@ public class YGDimensionTest { public void test_wrap_grandchild() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(100f); root_child0_child0.setHeight(100f); root_child0.addChildAt(root_child0_child0, 0); @@ -101,4 +111,7 @@ public class YGDimensionTest { assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGDisplayTest.java b/java/tests/com/facebook/yoga/YGDisplayTest.java index b8ffab07..a7d093c7 100644 --- a/java/tests/com/facebook/yoga/YGDisplayTest.java +++ b/java/tests/com/facebook/yoga/YGDisplayTest.java @@ -9,25 +9,35 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGDisplayTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_display_none() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setDisplay(YogaDisplay.NONE); root.addChildAt(root_child1, 1); @@ -72,16 +82,16 @@ public class YGDisplayTest { public void test_display_none_fixed_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(20f); root_child1.setHeight(20f); root_child1.setDisplay(YogaDisplay.NONE); @@ -127,12 +137,12 @@ public class YGDisplayTest { public void test_display_none_with_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.LEFT, 10f); root_child0.setMargin(YogaEdge.TOP, 10f); root_child0.setMargin(YogaEdge.RIGHT, 10f); @@ -142,7 +152,7 @@ public class YGDisplayTest { root_child0.setDisplay(YogaDisplay.NONE); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -186,25 +196,25 @@ public class YGDisplayTest { public void test_display_none_with_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexShrink(1f); root_child0.setFlexBasisPercent(0f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexShrink(1f); root_child1.setFlexBasisPercent(0f); root_child1.setDisplay(YogaDisplay.NONE); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setFlexGrow(1f); root_child1_child0.setFlexShrink(1f); root_child1_child0.setFlexBasisPercent(0f); @@ -213,7 +223,7 @@ public class YGDisplayTest { root_child1_child0.setMinHeight(0f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setFlexShrink(1f); root_child2.setFlexBasisPercent(0f); @@ -279,16 +289,16 @@ public class YGDisplayTest { public void test_display_none_with_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setPosition(YogaEdge.TOP, 10f); root_child1.setDisplay(YogaDisplay.NONE); @@ -330,4 +340,7 @@ public class YGDisplayTest { assertEquals(0f, root_child1.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGFlexDirectionTest.java b/java/tests/com/facebook/yoga/YGFlexDirectionTest.java index d5fb3f4a..07f96d17 100644 --- a/java/tests/com/facebook/yoga/YGFlexDirectionTest.java +++ b/java/tests/com/facebook/yoga/YGFlexDirectionTest.java @@ -9,27 +9,37 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGFlexDirectionTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_flex_direction_column_no_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -83,19 +93,19 @@ public class YGFlexDirectionTest { public void test_flex_direction_row_no_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -149,19 +159,19 @@ public class YGFlexDirectionTest { public void test_flex_direction_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -215,20 +225,20 @@ public class YGFlexDirectionTest { public void test_flex_direction_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -282,20 +292,20 @@ public class YGFlexDirectionTest { public void test_flex_direction_column_reverse() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.COLUMN_REVERSE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -349,20 +359,20 @@ public class YGFlexDirectionTest { public void test_flex_direction_row_reverse() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW_REVERSE); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -412,4 +422,7 @@ public class YGFlexDirectionTest { assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGFlexTest.java b/java/tests/com/facebook/yoga/YGFlexTest.java index 000c33c1..7140d7a1 100644 --- a/java/tests/com/facebook/yoga/YGFlexTest.java +++ b/java/tests/com/facebook/yoga/YGFlexTest.java @@ -9,25 +9,35 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGFlexTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_flex_basis_flex_grow_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -71,17 +81,17 @@ public class YGFlexTest { public void test_flex_basis_flex_grow_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -125,16 +135,16 @@ public class YGFlexTest { public void test_flex_basis_flex_shrink_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexShrink(1f); root_child0.setFlexBasis(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexBasis(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -178,17 +188,17 @@ public class YGFlexTest { public void test_flex_basis_flex_shrink_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexShrink(1f); root_child0.setFlexBasis(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexBasis(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -232,21 +242,21 @@ public class YGFlexTest { public void test_flex_shrink_to_zero() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setHeight(75f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexShrink(1f); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(50f); root.addChildAt(root_child2, 2); @@ -301,22 +311,22 @@ public class YGFlexTest { public void test_flex_basis_overrides_main_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -371,14 +381,14 @@ public class YGFlexTest { public void test_flex_grow_shrink_at_most() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexShrink(1f); root_child0.addChildAt(root_child0_child0, 0); @@ -423,20 +433,20 @@ public class YGFlexTest { public void test_flex_grow_less_than_factor_one() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(0.2f); root_child0.setFlexBasis(40f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(0.2f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(0.4f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -486,4 +496,7 @@ public class YGFlexTest { assertEquals(184f, root_child2.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGFlexWrapTest.java b/java/tests/com/facebook/yoga/YGFlexWrapTest.java index d7d0dc2b..0c36aa9c 100644 --- a/java/tests/com/facebook/yoga/YGFlexWrapTest.java +++ b/java/tests/com/facebook/yoga/YGFlexWrapTest.java @@ -9,35 +9,45 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGFlexWrapTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_wrap_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWrap(YogaWrap.WRAP); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(30f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(30f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(30f); root.addChildAt(root_child3, 3); @@ -102,27 +112,27 @@ public class YGFlexWrapTest { public void test_wrap_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(30f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(30f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(30f); root.addChildAt(root_child3, 3); @@ -187,28 +197,28 @@ public class YGFlexWrapTest { public void test_wrap_row_align_items_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.FLEX_END); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(30f); root.addChildAt(root_child3, 3); @@ -273,28 +283,28 @@ public class YGFlexWrapTest { public void test_wrap_row_align_items_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.CENTER); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(30f); root.addChildAt(root_child3, 3); @@ -359,18 +369,18 @@ public class YGFlexWrapTest { public void test_flex_wrap_children_with_min_main_overriding_flex_basis() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexBasis(50f); root_child0.setMinWidth(55f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexBasis(50f); root_child1.setMinWidth(55f); root_child1.setHeight(50f); @@ -416,24 +426,24 @@ public class YGFlexWrapTest { public void test_flex_wrap_wrap_to_child_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setAlignItems(YogaAlign.FLEX_START); root_child0.setWrap(YogaWrap.WRAP); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(100f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setWidth(100f); root_child0_child0_child0.setHeight(100f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(100f); root_child1.setHeight(100f); root.addChildAt(root_child1, 1); @@ -498,17 +508,17 @@ public class YGFlexWrapTest { public void test_flex_wrap_align_stretch_fits_one_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP); root.setWidth(150f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -552,32 +562,32 @@ public class YGFlexWrapTest { public void test_wrap_reverse_row_align_content_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(40f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(30f); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); @@ -652,33 +662,33 @@ public class YGFlexWrapTest { public void test_wrap_reverse_row_align_content_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.CENTER); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(40f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(30f); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); @@ -753,32 +763,32 @@ public class YGFlexWrapTest { public void test_wrap_reverse_row_single_line_different_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(300f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(40f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(30f); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); @@ -853,33 +863,33 @@ public class YGFlexWrapTest { public void test_wrap_reverse_row_align_content_stretch() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.STRETCH); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(40f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(30f); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); @@ -954,33 +964,33 @@ public class YGFlexWrapTest { public void test_wrap_reverse_row_align_content_space_around() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignContent(YogaAlign.SPACE_AROUND); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(40f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(30f); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); @@ -1055,33 +1065,33 @@ public class YGFlexWrapTest { public void test_wrap_reverse_column_fixed_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWrap(YogaWrap.WRAP_REVERSE); root.setWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(30f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(30f); root_child1.setHeight(20f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(30f); root_child2.setHeight(30f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setWidth(30f); root_child3.setHeight(40f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setWidth(30f); root_child4.setHeight(50f); root.addChildAt(root_child4, 4); @@ -1156,22 +1166,22 @@ public class YGFlexWrapTest { public void test_wrapped_row_within_align_items_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setWrap(YogaWrap.WRAP); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(150f); root_child0_child0.setHeight(80f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setWidth(80f); root_child0_child1.setHeight(80f); root_child0.addChildAt(root_child0_child1, 1); @@ -1226,22 +1236,22 @@ public class YGFlexWrapTest { public void test_wrapped_row_within_align_items_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.FLEX_START); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setWrap(YogaWrap.WRAP); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(150f); root_child0_child0.setHeight(80f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setWidth(80f); root_child0_child1.setHeight(80f); root_child0.addChildAt(root_child0_child1, 1); @@ -1296,22 +1306,22 @@ public class YGFlexWrapTest { public void test_wrapped_row_within_align_items_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.FLEX_END); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setWrap(YogaWrap.WRAP); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(150f); root_child0_child0.setHeight(80f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setWidth(80f); root_child0_child1.setHeight(80f); root_child0.addChildAt(root_child0_child1, 1); @@ -1366,7 +1376,7 @@ public class YGFlexWrapTest { public void test_wrapped_column_max_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignContent(YogaAlign.CENTER); root.setAlignItems(YogaAlign.CENTER); @@ -1374,13 +1384,13 @@ public class YGFlexWrapTest { root.setWidth(700f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(100f); root_child0.setHeight(500f); root_child0.setMaxHeight(200f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setMargin(YogaEdge.LEFT, 20f); root_child1.setMargin(YogaEdge.TOP, 20f); root_child1.setMargin(YogaEdge.RIGHT, 20f); @@ -1389,7 +1399,7 @@ public class YGFlexWrapTest { root_child1.setHeight(200f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(100f); root_child2.setHeight(100f); root.addChildAt(root_child2, 2); @@ -1444,7 +1454,7 @@ public class YGFlexWrapTest { public void test_wrapped_column_max_height_flex() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignContent(YogaAlign.CENTER); root.setAlignItems(YogaAlign.CENTER); @@ -1452,7 +1462,7 @@ public class YGFlexWrapTest { root.setWidth(700f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexShrink(1f); root_child0.setFlexBasisPercent(0f); @@ -1461,7 +1471,7 @@ public class YGFlexWrapTest { root_child0.setMaxHeight(200f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexShrink(1f); root_child1.setFlexBasisPercent(0f); @@ -1473,7 +1483,7 @@ public class YGFlexWrapTest { root_child1.setHeight(200f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(100f); root_child2.setHeight(100f); root.addChildAt(root_child2, 2); @@ -1528,29 +1538,29 @@ public class YGFlexWrapTest { public void test_wrap_nodes_with_content_sizing_overflowing_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(500f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setWrap(YogaWrap.WRAP); root_child0.setWidth(85f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setWidth(40f); root_child0_child0_child0.setHeight(40f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setMargin(YogaEdge.RIGHT, 10f); root_child0.addChildAt(root_child0_child1, 1); - final YogaNode root_child0_child1_child0 = new YogaNode(config); + final YogaNode root_child0_child1_child0 = createNode(config); root_child0_child1_child0.setWidth(40f); root_child0_child1_child0.setHeight(40f); root_child0_child1.addChildAt(root_child0_child1_child0, 0); @@ -1625,29 +1635,29 @@ public class YGFlexWrapTest { public void test_wrap_nodes_with_content_sizing_margin_cross() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(500f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setWrap(YogaWrap.WRAP); root_child0.setWidth(70f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setWidth(40f); root_child0_child0_child0.setHeight(40f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setMargin(YogaEdge.TOP, 10f); root_child0.addChildAt(root_child0_child1, 1); - final YogaNode root_child0_child1_child0 = new YogaNode(config); + final YogaNode root_child0_child1_child0 = createNode(config); root_child0_child1_child0.setWidth(40f); root_child0_child1_child0.setHeight(40f); root_child0_child1.addChildAt(root_child0_child1_child0, 0); @@ -1718,4 +1728,7 @@ public class YGFlexWrapTest { assertEquals(40f, root_child0_child1_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGJustifyContentTest.java b/java/tests/com/facebook/yoga/YGJustifyContentTest.java index cde75c84..69b2077e 100644 --- a/java/tests/com/facebook/yoga/YGJustifyContentTest.java +++ b/java/tests/com/facebook/yoga/YGJustifyContentTest.java @@ -9,29 +9,39 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGJustifyContentTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_justify_content_row_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -85,21 +95,21 @@ public class YGJustifyContentTest { public void test_justify_content_row_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.FLEX_END); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -153,21 +163,21 @@ public class YGJustifyContentTest { public void test_justify_content_row_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -221,21 +231,21 @@ public class YGJustifyContentTest { public void test_justify_content_row_space_between() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.SPACE_BETWEEN); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -289,21 +299,21 @@ public class YGJustifyContentTest { public void test_justify_content_row_space_around() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.SPACE_AROUND); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -357,19 +367,19 @@ public class YGJustifyContentTest { public void test_justify_content_column_flex_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -423,20 +433,20 @@ public class YGJustifyContentTest { public void test_justify_content_column_flex_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.FLEX_END); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -490,20 +500,20 @@ public class YGJustifyContentTest { public void test_justify_content_column_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -557,20 +567,20 @@ public class YGJustifyContentTest { public void test_justify_content_column_space_between() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.SPACE_BETWEEN); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -624,20 +634,20 @@ public class YGJustifyContentTest { public void test_justify_content_column_space_around() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.SPACE_AROUND); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -691,13 +701,13 @@ public class YGJustifyContentTest { public void test_justify_content_row_min_width_and_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.CENTER); root.setMargin(YogaEdge.LEFT, 100f); root.setMinWidth(50f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(20f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); @@ -732,14 +742,14 @@ public class YGJustifyContentTest { public void test_justify_content_row_max_width_and_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.CENTER); root.setMargin(YogaEdge.LEFT, 100f); root.setWidth(100f); root.setMaxWidth(80f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(20f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); @@ -774,12 +784,12 @@ public class YGJustifyContentTest { public void test_justify_content_column_min_height_and_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setMargin(YogaEdge.TOP, 100f); root.setMinHeight(50f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(20f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); @@ -814,13 +824,13 @@ public class YGJustifyContentTest { public void test_justify_content_colunn_max_height_and_margin() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setMargin(YogaEdge.TOP, 100f); root.setHeight(100f); root.setMaxHeight(80f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(20f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); @@ -855,20 +865,20 @@ public class YGJustifyContentTest { public void test_justify_content_column_space_evenly() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.SPACE_EVENLY); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -922,21 +932,21 @@ public class YGJustifyContentTest { public void test_justify_content_row_space_evenly() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.SPACE_EVENLY); root.setWidth(102f); root.setHeight(102f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -986,4 +996,7 @@ public class YGJustifyContentTest { assertEquals(10f, root_child2.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGMarginTest.java b/java/tests/com/facebook/yoga/YGMarginTest.java index c4921e16..e6f774a1 100644 --- a/java/tests/com/facebook/yoga/YGMarginTest.java +++ b/java/tests/com/facebook/yoga/YGMarginTest.java @@ -9,21 +9,31 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGMarginTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_margin_start() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.START, 10f); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); @@ -58,11 +68,11 @@ public class YGMarginTest { public void test_margin_top() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.TOP, 10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -97,13 +107,13 @@ public class YGMarginTest { public void test_margin_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setJustifyContent(YogaJustify.FLEX_END); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.END, 10f); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); @@ -138,12 +148,12 @@ public class YGMarginTest { public void test_margin_bottom() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.FLEX_END); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.BOTTOM, 10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -178,12 +188,12 @@ public class YGMarginTest { public void test_margin_and_flex_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMargin(YogaEdge.START, 10f); root_child0.setMargin(YogaEdge.END, 10f); @@ -219,11 +229,11 @@ public class YGMarginTest { public void test_margin_and_flex_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMargin(YogaEdge.TOP, 10f); root_child0.setMargin(YogaEdge.BOTTOM, 10f); @@ -259,12 +269,12 @@ public class YGMarginTest { public void test_margin_and_stretch_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMargin(YogaEdge.TOP, 10f); root_child0.setMargin(YogaEdge.BOTTOM, 10f); @@ -300,11 +310,11 @@ public class YGMarginTest { public void test_margin_and_stretch_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMargin(YogaEdge.START, 10f); root_child0.setMargin(YogaEdge.END, 10f); @@ -340,17 +350,17 @@ public class YGMarginTest { public void test_margin_with_sibling_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMargin(YogaEdge.END, 10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -394,16 +404,16 @@ public class YGMarginTest { public void test_margin_with_sibling_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMargin(YogaEdge.BOTTOM, 10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -447,18 +457,18 @@ public class YGMarginTest { public void test_margin_auto_bottom() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.BOTTOM); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -503,18 +513,18 @@ public class YGMarginTest { public void test_margin_auto_top() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.TOP); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -559,19 +569,19 @@ public class YGMarginTest { public void test_margin_auto_bottom_and_top() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.TOP); root_child0.setMarginAuto(YogaEdge.BOTTOM); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -616,19 +626,19 @@ public class YGMarginTest { public void test_margin_auto_bottom_and_top_justify_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.TOP); root_child0.setMarginAuto(YogaEdge.BOTTOM); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -673,24 +683,24 @@ public class YGMarginTest { public void test_margin_auto_mutiple_children_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.TOP); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setMarginAuto(YogaEdge.TOP); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(50f); root.addChildAt(root_child2, 2); @@ -745,25 +755,25 @@ public class YGMarginTest { public void test_margin_auto_mutiple_children_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setMarginAuto(YogaEdge.RIGHT); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(50f); root.addChildAt(root_child2, 2); @@ -818,20 +828,20 @@ public class YGMarginTest { public void test_margin_auto_left_and_right_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -876,18 +886,18 @@ public class YGMarginTest { public void test_margin_auto_left_and_right() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -932,20 +942,20 @@ public class YGMarginTest { public void test_margin_auto_start_and_end_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.START); root_child0.setMarginAuto(YogaEdge.END); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -990,18 +1000,18 @@ public class YGMarginTest { public void test_margin_auto_start_and_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.START); root_child0.setMarginAuto(YogaEdge.END); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1046,19 +1056,19 @@ public class YGMarginTest { public void test_margin_auto_left_and_right_column_and_center() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1103,18 +1113,18 @@ public class YGMarginTest { public void test_margin_auto_left() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1159,18 +1169,18 @@ public class YGMarginTest { public void test_margin_auto_right() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1215,19 +1225,19 @@ public class YGMarginTest { public void test_margin_auto_left_and_right_strech() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1272,18 +1282,18 @@ public class YGMarginTest { public void test_margin_auto_top_and_bottom_strech() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.TOP); root_child0.setMarginAuto(YogaEdge.BOTTOM); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1328,11 +1338,11 @@ public class YGMarginTest { public void test_margin_should_not_be_part_of_max_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(250f); root.setHeight(250f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.TOP, 20f); root_child0.setWidth(100f); root_child0.setHeight(100f); @@ -1369,11 +1379,11 @@ public class YGMarginTest { public void test_margin_should_not_be_part_of_max_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(250f); root.setHeight(250f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.LEFT, 20f); root_child0.setWidth(100f); root_child0.setMaxWidth(100f); @@ -1410,12 +1420,12 @@ public class YGMarginTest { public void test_margin_auto_left_right_child_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(72f); @@ -1452,12 +1462,12 @@ public class YGMarginTest { public void test_margin_auto_left_child_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setWidth(72f); root_child0.setHeight(72f); @@ -1493,12 +1503,12 @@ public class YGMarginTest { public void test_margin_fix_left_auto_right_child_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMargin(YogaEdge.LEFT, 10f); root_child0.setMarginAuto(YogaEdge.RIGHT); root_child0.setWidth(72f); @@ -1535,12 +1545,12 @@ public class YGMarginTest { public void test_margin_auto_left_fix_right_child_bigger_than_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(52f); root.setHeight(52f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMarginAuto(YogaEdge.LEFT); root_child0.setMargin(YogaEdge.RIGHT, 10f); root_child0.setWidth(72f); @@ -1577,19 +1587,19 @@ public class YGMarginTest { public void test_margin_auto_top_stretching_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexShrink(1f); root_child0.setFlexBasisPercent(0f); root_child0.setMarginAuto(YogaEdge.TOP); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1634,19 +1644,19 @@ public class YGMarginTest { public void test_margin_auto_left_stretching_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexShrink(1f); root_child0.setFlexBasisPercent(0f); root_child0.setMarginAuto(YogaEdge.LEFT); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); @@ -1687,4 +1697,7 @@ public class YGMarginTest { assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java b/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java index eb01dd82..765fd2f5 100644 --- a/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java +++ b/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java @@ -9,20 +9,30 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGMinMaxDimensionTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_max_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMaxWidth(50f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -57,12 +67,12 @@ public class YGMinMaxDimensionTest { public void test_max_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setMaxHeight(50f); root.addChildAt(root_child0, 0); @@ -97,16 +107,16 @@ public class YGMinMaxDimensionTest { public void test_min_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMinHeight(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -150,17 +160,17 @@ public class YGMinMaxDimensionTest { public void test_min_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMinWidth(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -204,13 +214,13 @@ public class YGMinMaxDimensionTest { public void test_justify_content_min_max() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setWidth(100f); root.setMinHeight(100f); root.setMaxHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(60f); root_child0.setHeight(60f); root.addChildAt(root_child0, 0); @@ -245,13 +255,13 @@ public class YGMinMaxDimensionTest { public void test_align_items_min_max() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.CENTER); root.setMinWidth(100f); root.setMaxWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(60f); root_child0.setHeight(60f); root.addChildAt(root_child0, 0); @@ -286,22 +296,22 @@ public class YGMinMaxDimensionTest { public void test_justify_content_overflow_min_max() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setMinHeight(100f); root.setMaxHeight(110f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(50f); root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(50f); root_child2.setHeight(50f); root.addChildAt(root_child2, 2); @@ -356,17 +366,17 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_to_min() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setMinHeight(100f); root.setMaxHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexShrink(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -410,17 +420,17 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_in_at_most_container() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.FLEX_START); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexBasis(0f); root_child0.addChildAt(root_child0_child0, 0); @@ -465,10 +475,10 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(0f); root_child0.setHeight(100f); @@ -504,15 +514,15 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_constrained_min_max_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setMinHeight(100f); root.setMaxHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -556,16 +566,16 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_max_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setMaxWidth(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setHeight(20f); root_child0.addChildAt(root_child0_child0, 0); @@ -610,16 +620,16 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_constrained_max_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setMaxWidth(300f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setHeight(20f); root_child0.addChildAt(root_child0_child0, 0); @@ -664,18 +674,18 @@ public class YGMinMaxDimensionTest { public void test_flex_root_ignored() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexGrow(1f); root.setWidth(100f); root.setMinHeight(100f); root.setMaxHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(200f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(100f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -719,23 +729,23 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_root_minimized() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setMinHeight(100f); root.setMaxHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMinHeight(100f); root_child0.setMaxHeight(500f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexBasis(200f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setHeight(100f); root_child0.addChildAt(root_child0_child1, 1); root.setDirection(YogaDirection.LTR); @@ -789,22 +799,22 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_height_maximized() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMinHeight(100f); root_child0.setMaxHeight(500f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexBasis(200f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setHeight(100f); root_child0.addChildAt(root_child0_child1, 1); root.setDirection(YogaDirection.LTR); @@ -858,16 +868,16 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_constrained_min_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setMinWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setWidth(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -911,14 +921,14 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_constrained_min_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setMinHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -962,21 +972,21 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_constrained_max_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setMaxWidth(100f); root_child0.setHeight(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexShrink(1f); root_child0_child0.setFlexBasis(100f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setWidth(50f); root_child0.addChildAt(root_child0_child1, 1); root.setDirection(YogaDirection.LTR); @@ -1030,16 +1040,16 @@ public class YGMinMaxDimensionTest { public void test_flex_grow_within_constrained_max_column() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setMaxHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexShrink(1f); root_child0.setFlexBasis(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); root.setDirection(YogaDirection.LTR); @@ -1083,18 +1093,18 @@ public class YGMinMaxDimensionTest { public void test_child_min_max_width_flexing() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(120f); root.setHeight(50f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(0f); root_child0.setMinWidth(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexBasisPercent(50f); root_child1.setMaxWidth(20f); @@ -1140,7 +1150,7 @@ public class YGMinMaxDimensionTest { public void test_min_width_overrides_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(50f); root.setMinWidth(100f); root.setDirection(YogaDirection.LTR); @@ -1164,7 +1174,7 @@ public class YGMinMaxDimensionTest { public void test_max_width_overrides_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setMaxWidth(100f); root.setDirection(YogaDirection.LTR); @@ -1188,7 +1198,7 @@ public class YGMinMaxDimensionTest { public void test_min_height_overrides_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setHeight(50f); root.setMinHeight(100f); root.setDirection(YogaDirection.LTR); @@ -1212,7 +1222,7 @@ public class YGMinMaxDimensionTest { public void test_max_height_overrides_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setHeight(200f); root.setMaxHeight(100f); root.setDirection(YogaDirection.LTR); @@ -1236,12 +1246,12 @@ public class YGMinMaxDimensionTest { public void test_min_max_percent_no_width_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setAlignItems(YogaAlign.FLEX_START); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setMinWidthPercent(10f); root_child0.setMaxWidthPercent(10f); root_child0.setMinHeightPercent(10f); @@ -1274,4 +1284,7 @@ public class YGMinMaxDimensionTest { assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGPaddingTest.java b/java/tests/com/facebook/yoga/YGPaddingTest.java index b8d477c9..9407c35b 100644 --- a/java/tests/com/facebook/yoga/YGPaddingTest.java +++ b/java/tests/com/facebook/yoga/YGPaddingTest.java @@ -9,16 +9,26 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGPaddingTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_padding_no_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPadding(YogaEdge.LEFT, 10); root.setPadding(YogaEdge.TOP, 10); root.setPadding(YogaEdge.RIGHT, 10); @@ -44,13 +54,13 @@ public class YGPaddingTest { public void test_padding_container_match_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPadding(YogaEdge.LEFT, 10); root.setPadding(YogaEdge.TOP, 10); root.setPadding(YogaEdge.RIGHT, 10); root.setPadding(YogaEdge.BOTTOM, 10); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -85,7 +95,7 @@ public class YGPaddingTest { public void test_padding_flex_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPadding(YogaEdge.LEFT, 10); root.setPadding(YogaEdge.TOP, 10); root.setPadding(YogaEdge.RIGHT, 10); @@ -93,7 +103,7 @@ public class YGPaddingTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); @@ -128,7 +138,7 @@ public class YGPaddingTest { public void test_padding_stretch_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPadding(YogaEdge.LEFT, 10); root.setPadding(YogaEdge.TOP, 10); root.setPadding(YogaEdge.RIGHT, 10); @@ -136,7 +146,7 @@ public class YGPaddingTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); root.setDirection(YogaDirection.LTR); @@ -170,7 +180,7 @@ public class YGPaddingTest { public void test_padding_center_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setPadding(YogaEdge.START, 10); @@ -179,7 +189,7 @@ public class YGPaddingTest { root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(10f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); @@ -214,13 +224,13 @@ public class YGPaddingTest { public void test_child_with_padding_align_end() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.FLEX_END); root.setAlignItems(YogaAlign.FLEX_END); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPadding(YogaEdge.LEFT, 20); root_child0.setPadding(YogaEdge.TOP, 20); root_child0.setPadding(YogaEdge.RIGHT, 20); @@ -255,4 +265,7 @@ public class YGPaddingTest { assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGPercentageTest.java b/java/tests/com/facebook/yoga/YGPercentageTest.java index 8b06a21e..eabffa60 100644 --- a/java/tests/com/facebook/yoga/YGPercentageTest.java +++ b/java/tests/com/facebook/yoga/YGPercentageTest.java @@ -9,21 +9,31 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGPercentageTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_percentage_width_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidthPercent(30f); root_child0.setHeightPercent(30f); root.addChildAt(root_child0, 0); @@ -58,12 +68,12 @@ public class YGPercentageTest { public void test_percentage_position_left_top() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(400f); root.setHeight(400f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionPercent(YogaEdge.LEFT, 10f); root_child0.setPositionPercent(YogaEdge.TOP, 20f); root_child0.setWidthPercent(45f); @@ -100,12 +110,12 @@ public class YGPercentageTest { public void test_percentage_position_bottom_right() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(500f); root.setHeight(500f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionPercent(YogaEdge.RIGHT, 20f); root_child0.setPositionPercent(YogaEdge.BOTTOM, 10f); root_child0.setWidthPercent(55f); @@ -142,17 +152,17 @@ public class YGPercentageTest { public void test_percentage_flex_basis() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexBasisPercent(25f); root.addChildAt(root_child1, 1); @@ -197,16 +207,16 @@ public class YGPercentageTest { public void test_percentage_flex_basis_cross() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setFlexBasisPercent(25f); root.addChildAt(root_child1, 1); @@ -251,16 +261,16 @@ public class YGPercentageTest { public void test_percentage_flex_basis_cross_min_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMinHeightPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(2f); root_child1.setMinHeightPercent(10f); root.addChildAt(root_child1, 1); @@ -305,18 +315,18 @@ public class YGPercentageTest { public void test_percentage_flex_basis_main_max_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(10f); root_child0.setMaxHeightPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(10f); root_child1.setMaxHeightPercent(20f); @@ -362,17 +372,17 @@ public class YGPercentageTest { public void test_percentage_flex_basis_cross_max_height() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(10f); root_child0.setMaxHeightPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(10f); root_child1.setMaxHeightPercent(20f); @@ -418,18 +428,18 @@ public class YGPercentageTest { public void test_percentage_flex_basis_main_max_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(15f); root_child0.setMaxWidthPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(10f); root_child1.setMaxWidthPercent(20f); @@ -475,17 +485,17 @@ public class YGPercentageTest { public void test_percentage_flex_basis_cross_max_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(10f); root_child0.setMaxWidthPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(15f); root_child1.setMaxWidthPercent(20f); @@ -531,18 +541,18 @@ public class YGPercentageTest { public void test_percentage_flex_basis_main_min_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(15f); root_child0.setMinWidthPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(10f); root_child1.setMinWidthPercent(20f); @@ -588,17 +598,17 @@ public class YGPercentageTest { public void test_percentage_flex_basis_cross_min_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(10f); root_child0.setMinWidthPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(15f); root_child1.setMinWidthPercent(20f); @@ -644,11 +654,11 @@ public class YGPercentageTest { public void test_percentage_multiple_nested_with_padding_margin_and_percentage_values() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasisPercent(10f); root_child0.setMargin(YogaEdge.LEFT, 5f); @@ -662,7 +672,7 @@ public class YGPercentageTest { root_child0.setMinWidthPercent(60f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setMargin(YogaEdge.LEFT, 5f); root_child0_child0.setMargin(YogaEdge.TOP, 5f); root_child0_child0.setMargin(YogaEdge.RIGHT, 5f); @@ -674,7 +684,7 @@ public class YGPercentageTest { root_child0_child0.setWidthPercent(50f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setMarginPercent(YogaEdge.LEFT, 5f); root_child0_child0_child0.setMarginPercent(YogaEdge.TOP, 5f); root_child0_child0_child0.setMarginPercent(YogaEdge.RIGHT, 5f); @@ -686,7 +696,7 @@ public class YGPercentageTest { root_child0_child0_child0.setWidthPercent(45f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(4f); root_child1.setFlexBasisPercent(15f); root_child1.setMinWidthPercent(20f); @@ -752,11 +762,11 @@ public class YGPercentageTest { public void test_percentage_margin_should_calculate_based_only_on_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setMarginPercent(YogaEdge.LEFT, 10f); root_child0.setMarginPercent(YogaEdge.TOP, 10f); @@ -764,7 +774,7 @@ public class YGPercentageTest { root_child0.setMarginPercent(YogaEdge.BOTTOM, 10f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(10f); root_child0_child0.setHeight(10f); root_child0.addChildAt(root_child0_child0, 0); @@ -809,11 +819,11 @@ public class YGPercentageTest { public void test_percentage_padding_should_calculate_based_only_on_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setPaddingPercent(YogaEdge.LEFT, 10); root_child0.setPaddingPercent(YogaEdge.TOP, 10); @@ -821,7 +831,7 @@ public class YGPercentageTest { root_child0.setPaddingPercent(YogaEdge.BOTTOM, 10); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(10f); root_child0_child0.setHeight(10f); root_child0.addChildAt(root_child0_child0, 0); @@ -866,11 +876,11 @@ public class YGPercentageTest { public void test_percentage_absolute_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(200f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPositionPercent(YogaEdge.LEFT, 30f); root_child0.setPositionPercent(YogaEdge.TOP, 10f); @@ -908,9 +918,9 @@ public class YGPercentageTest { public void test_percentage_width_height_undefined_parent_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidthPercent(50f); root_child0.setHeightPercent(50f); root.addChildAt(root_child0, 0); @@ -945,24 +955,24 @@ public class YGPercentageTest { public void test_percent_within_flex_grow() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(350f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setWidthPercent(100f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setWidth(100f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -1026,27 +1036,27 @@ public class YGPercentageTest { public void test_percentage_container_in_wrapping_container() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setJustifyContent(YogaJustify.CENTER); root.setAlignItems(YogaAlign.CENTER); root.setWidth(200f); root.setHeight(200f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0_child0.setJustifyContent(YogaJustify.CENTER); root_child0_child0.setWidthPercent(100f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setWidth(50f); root_child0_child0_child0.setHeight(50f); root_child0_child0.addChildAt(root_child0_child0_child0, 0); - final YogaNode root_child0_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child0_child1 = createNode(config); root_child0_child0_child1.setWidth(50f); root_child0_child0_child1.setHeight(50f); root_child0_child0.addChildAt(root_child0_child0_child1, 1); @@ -1111,11 +1121,11 @@ public class YGPercentageTest { public void test_percent_absolute_position() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(60f); root.setHeight(50f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexDirection(YogaFlexDirection.ROW); root_child0.setPositionType(YogaPositionType.ABSOLUTE); root_child0.setPositionPercent(YogaEdge.LEFT, 50f); @@ -1123,11 +1133,11 @@ public class YGPercentageTest { root_child0.setHeight(50f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidthPercent(100f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setWidthPercent(100f); root_child0.addChildAt(root_child0_child1, 1); root.setDirection(YogaDirection.LTR); @@ -1177,4 +1187,7 @@ public class YGPercentageTest { assertEquals(50f, root_child0_child1.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGRoundingTest.java b/java/tests/com/facebook/yoga/YGRoundingTest.java index 31489988..a9384f20 100644 --- a/java/tests/com/facebook/yoga/YGRoundingTest.java +++ b/java/tests/com/facebook/yoga/YGRoundingTest.java @@ -9,29 +9,39 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGRoundingTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_rounding_flex_basis_flex_grow_row_width_of_100() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -85,28 +95,28 @@ public class YGRoundingTest { public void test_rounding_flex_basis_flex_grow_row_prime_number_width() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(113f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root.addChildAt(root_child2, 2); - final YogaNode root_child3 = new YogaNode(config); + final YogaNode root_child3 = createNode(config); root_child3.setFlexGrow(1f); root.addChildAt(root_child3, 3); - final YogaNode root_child4 = new YogaNode(config); + final YogaNode root_child4 = createNode(config); root_child4.setFlexGrow(1f); root.addChildAt(root_child4, 4); root.setDirection(YogaDirection.LTR); @@ -180,21 +190,21 @@ public class YGRoundingTest { public void test_rounding_flex_basis_flex_shrink_row() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(101f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexShrink(1f); root_child0.setFlexBasis(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexBasis(25f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexBasis(25f); root.addChildAt(root_child2, 2); root.setDirection(YogaDirection.LTR); @@ -248,22 +258,22 @@ public class YGRoundingTest { public void test_rounding_flex_basis_overrides_main_size() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(113f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -318,22 +328,22 @@ public class YGRoundingTest { public void test_rounding_total_fractial() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(87.4f); root.setHeight(113.4f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(0.7f); root_child0.setFlexBasis(50.3f); root_child0.setHeight(20.3f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1.6f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1.1f); root_child2.setHeight(10.7f); root.addChildAt(root_child2, 2); @@ -388,36 +398,36 @@ public class YGRoundingTest { public void test_rounding_total_fractial_nested() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(87.4f); root.setHeight(113.4f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(0.7f); root_child0.setFlexBasis(50.3f); root_child0.setHeight(20.3f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1f); root_child0_child0.setFlexBasis(0.3f); root_child0_child0.setPosition(YogaEdge.BOTTOM, 13.3f); root_child0_child0.setHeight(9.9f); root_child0.addChildAt(root_child0_child0, 0); - final YogaNode root_child0_child1 = new YogaNode(config); + final YogaNode root_child0_child1 = createNode(config); root_child0_child1.setFlexGrow(4f); root_child0_child1.setFlexBasis(0.3f); root_child0_child1.setPosition(YogaEdge.TOP, 13.3f); root_child0_child1.setHeight(1.1f); root_child0.addChildAt(root_child0_child1, 1); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1.6f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1.1f); root_child2.setHeight(10.7f); root.addChildAt(root_child2, 2); @@ -492,22 +502,22 @@ public class YGRoundingTest { public void test_rounding_fractial_input_1() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(113.4f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -562,22 +572,22 @@ public class YGRoundingTest { public void test_rounding_fractial_input_2() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(113.6f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -632,23 +642,23 @@ public class YGRoundingTest { public void test_rounding_fractial_input_3() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPosition(YogaEdge.TOP, 0.3f); root.setWidth(100f); root.setHeight(113.4f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -703,23 +713,23 @@ public class YGRoundingTest { public void test_rounding_fractial_input_4() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setPosition(YogaEdge.TOP, 0.7f); root.setWidth(100f); root.setHeight(113.4f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setFlexBasis(50f); root_child0.setHeight(20f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -774,26 +784,26 @@ public class YGRoundingTest { public void test_rounding_inner_node_controversy_horizontal() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(320f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setHeight(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeight(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setFlexGrow(1f); root_child1_child0.setHeight(10f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeight(10f); root.addChildAt(root_child2, 2); @@ -858,25 +868,25 @@ public class YGRoundingTest { public void test_rounding_inner_node_controversy_vertical() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setHeight(320f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setWidth(10f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setWidth(10f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setFlexGrow(1f); root_child1_child0.setWidth(10f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setWidth(10f); root.addChildAt(root_child2, 2); @@ -941,42 +951,42 @@ public class YGRoundingTest { public void test_rounding_inner_node_controversy_combined() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setFlexDirection(YogaFlexDirection.ROW); root.setWidth(640f); root.setHeight(320f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setFlexGrow(1f); root_child0.setHeightPercent(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child1 = new YogaNode(config); + final YogaNode root_child1 = createNode(config); root_child1.setFlexGrow(1f); root_child1.setHeightPercent(100f); root.addChildAt(root_child1, 1); - final YogaNode root_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child0 = createNode(config); root_child1_child0.setFlexGrow(1f); root_child1_child0.setWidthPercent(100f); root_child1.addChildAt(root_child1_child0, 0); - final YogaNode root_child1_child1 = new YogaNode(config); + final YogaNode root_child1_child1 = createNode(config); root_child1_child1.setFlexGrow(1f); root_child1_child1.setWidthPercent(100f); root_child1.addChildAt(root_child1_child1, 1); - final YogaNode root_child1_child1_child0 = new YogaNode(config); + final YogaNode root_child1_child1_child0 = createNode(config); root_child1_child1_child0.setFlexGrow(1f); root_child1_child1_child0.setWidthPercent(100f); root_child1_child1.addChildAt(root_child1_child1_child0, 0); - final YogaNode root_child1_child2 = new YogaNode(config); + final YogaNode root_child1_child2 = createNode(config); root_child1_child2.setFlexGrow(1f); root_child1_child2.setWidthPercent(100f); root_child1.addChildAt(root_child1_child2, 2); - final YogaNode root_child2 = new YogaNode(config); + final YogaNode root_child2 = createNode(config); root_child2.setFlexGrow(1f); root_child2.setHeightPercent(100f); root.addChildAt(root_child2, 2); @@ -1067,4 +1077,7 @@ public class YGRoundingTest { assertEquals(320f, root_child2.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YGSizeOverflowTest.java b/java/tests/com/facebook/yoga/YGSizeOverflowTest.java index e4aa71cd..e24e0677 100644 --- a/java/tests/com/facebook/yoga/YGSizeOverflowTest.java +++ b/java/tests/com/facebook/yoga/YGSizeOverflowTest.java @@ -9,23 +9,33 @@ package com.facebook.yoga; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) public class YGSizeOverflowTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + @Test public void test_nested_overflowing_child() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(200f); root_child0_child0.setHeight(200f); root_child0.addChildAt(root_child0_child0, 0); @@ -70,16 +80,16 @@ public class YGSizeOverflowTest { public void test_nested_overflowing_child_in_constraint_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(100f); root_child0.setHeight(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(200f); root_child0_child0.setHeight(200f); root_child0.addChildAt(root_child0_child0, 0); @@ -124,15 +134,15 @@ public class YGSizeOverflowTest { public void test_parent_wrap_child_size_overflowing_parent() { YogaConfig config = new YogaConfig(); - final YogaNode root = new YogaNode(config); + final YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - final YogaNode root_child0 = new YogaNode(config); + final YogaNode root_child0 = createNode(config); root_child0.setWidth(100f); root.addChildAt(root_child0, 0); - final YogaNode root_child0_child0 = new YogaNode(config); + final YogaNode root_child0_child0 = createNode(config); root_child0_child0.setWidth(100f); root_child0_child0.setHeight(200f); root_child0.addChildAt(root_child0_child0, 0); @@ -173,4 +183,7 @@ public class YGSizeOverflowTest { assertEquals(200f, root_child0_child0.getLayoutHeight(), 0.0f); } + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } diff --git a/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java b/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java index 8efcdd13..6ba58ed4 100644 --- a/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java @@ -10,14 +10,24 @@ package com.facebook.yoga; import static org.junit.Assert.assertEquals; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +@RunWith(Parameterized.class) public class YogaNodeStylePropertiesTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + private static final float UNDEFINED = YogaValue.UNDEFINED.value; @Test public void testDirectionDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(node.getStyleDirection(), YogaDirection.INHERIT); assertEquals(node.getLayoutDirection(), YogaDirection.INHERIT); @@ -25,7 +35,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testDirectionAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setDirection(YogaDirection.LTR); node.calculateLayout(UNDEFINED, UNDEFINED); @@ -44,7 +54,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testFlexDirectionDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaFlexDirection.COLUMN, node.getFlexDirection()); } @@ -71,14 +81,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testJustifyContentDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaJustify.FLEX_START, node.getJustifyContent()); } @Test public void testJustifyContentAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setJustifyContent(YogaJustify.SPACE_EVENLY); assertEquals(YogaJustify.SPACE_EVENLY, node.getJustifyContent()); @@ -99,14 +109,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testAlignItemsDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaAlign.STRETCH, node.getAlignItems()); } @Test public void testAlignItemsAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setAlignItems(YogaAlign.SPACE_AROUND); assertEquals(YogaAlign.SPACE_AROUND, node.getAlignItems()); @@ -123,14 +133,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testAlignSelfDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaAlign.AUTO, node.getAlignSelf()); } @Test public void testAlignSelfAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setAlignSelf(YogaAlign.FLEX_END); assertEquals(YogaAlign.FLEX_END, node.getAlignSelf()); @@ -147,14 +157,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testAlignContentDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaAlign.FLEX_START, node.getAlignContent()); } @Test public void testAlignContentAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setAlignContent(YogaAlign.BASELINE); assertEquals(YogaAlign.BASELINE, node.getAlignContent()); @@ -179,14 +189,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testPositionTypeDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaPositionType.RELATIVE, node.getPositionType()); } @Test public void testPositionTypeAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setPositionType(YogaPositionType.ABSOLUTE); assertEquals(YogaPositionType.ABSOLUTE, node.getPositionType()); @@ -221,14 +231,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testOverflowDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaOverflow.VISIBLE, node.getOverflow()); } @Test public void testOverflowAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setOverflow(YogaOverflow.SCROLL); assertEquals(YogaOverflow.SCROLL, node.getOverflow()); @@ -238,14 +248,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testDisplayDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaDisplay.FLEX, node.getDisplay()); } @Test public void testDisplayAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setDisplay(YogaDisplay.NONE); assertEquals(YogaDisplay.NONE, node.getDisplay()); @@ -278,14 +288,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testFlexGrowDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(0, node.getFlexGrow(), 0); } @Test public void testFlexGrowAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setFlexGrow(2.5f); assertEquals(2.5f, node.getFlexGrow(), 0); @@ -302,14 +312,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testFlexShrinkDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(0, node.getFlexShrink(), 0); } @Test public void testFlexShrinkAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setFlexShrink(2.5f); assertEquals(2.5f, node.getFlexShrink(), 0); @@ -326,14 +336,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testFlexBasisDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.AUTO, node.getFlexBasis()); } @Test public void testFlexBasisAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setFlexBasis(50); assertEquals(new YogaValue(50, YogaUnit.POINT), node.getFlexBasis()); @@ -370,7 +380,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testMarginDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { assertEquals(YogaValue.UNDEFINED, node.getMargin(edge)); } @@ -378,7 +388,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testMarginAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { node.setMargin(edge, 25); assertEquals(new YogaValue(25, YogaUnit.POINT), node.getMargin(edge)); @@ -423,7 +433,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testPaddingDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { assertEquals(YogaValue.UNDEFINED, node.getPadding(edge)); } @@ -431,7 +441,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testPaddingAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { node.setPadding(edge, 25); assertEquals(new YogaValue(25, YogaUnit.POINT), node.getPadding(edge)); @@ -460,7 +470,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testBorderDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { assertEquals(UNDEFINED, node.getBorder(edge), 0); } @@ -468,7 +478,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testBorderAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { node.setBorder(edge, 2.5f); assertEquals(2.5f, node.getBorder(edge), 0); @@ -485,7 +495,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testPositionDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { assertEquals(YogaValue.UNDEFINED, node.getPosition(edge)); } @@ -493,7 +503,7 @@ public class YogaNodeStylePropertiesTest { @Test public void testPositionAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { node.setPosition(edge, 25); assertEquals(new YogaValue(25, YogaUnit.POINT), node.getPosition(edge)); @@ -537,14 +547,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testWidthDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.AUTO, node.getWidth()); } @Test public void testWidthAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setWidth(123); assertEquals(new YogaValue(123, YogaUnit.POINT), node.getWidth()); @@ -572,14 +582,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testHeightDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.AUTO, node.getHeight()); } @Test public void testHeightAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setHeight(123); assertEquals(new YogaValue(123, YogaUnit.POINT), node.getHeight()); @@ -607,14 +617,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testMinWidthDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.UNDEFINED, node.getMinWidth()); } @Test public void testMinWidthAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMinWidth(123); assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMinWidth()); @@ -640,14 +650,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testMinHeightDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.UNDEFINED, node.getMinHeight()); } @Test public void testMinHeightAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMinHeight(123); assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMinHeight()); @@ -673,14 +683,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testMaxWidthDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.UNDEFINED, node.getMaxWidth()); } @Test public void testMaxWidthAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMaxWidth(123); assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMaxWidth()); @@ -706,14 +716,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testMaxHeightDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(YogaValue.UNDEFINED, node.getMaxHeight()); } @Test public void testMaxHeightAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMaxHeight(123); assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMaxHeight()); @@ -749,14 +759,14 @@ public class YogaNodeStylePropertiesTest { @Test public void testAspectRatioDefault() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(UNDEFINED, node.getAspectRatio(), 0); } @Test public void testAspectRatioAssignment() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setAspectRatio(2.75f); assertEquals(2.75f, node.getAspectRatio(), 0); @@ -778,13 +788,21 @@ public class YogaNodeStylePropertiesTest { assertEquals(450, node.getChildAt(0).getLayoutWidth(), 0); } - private static StyledNode style() { - return new StyledNode(); + private YogaNode createNode() { + return mNodeFactory.create(); + } + + private StyledNode style() { + return new StyledNode(mNodeFactory); } private static class StyledNode { - private YogaNode mNode = new YogaNode(); + private YogaNode mNode; + + public StyledNode(TestParametrization.NodeFactory nodeFactory) { + mNode = nodeFactory.create(); + } YogaNode node() { return mNode; diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index 9cc26eb9..e72930e4 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 static org.junit.Assert.assertEquals; @@ -17,30 +17,39 @@ import static org.junit.Assert.fail; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +@RunWith(Parameterized.class) public class YogaNodeTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; @Test public void testInit() { final int refCount = YogaNode.jni_YGNodeGetInstanceCount(); - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); assertEquals(refCount + 1, YogaNode.jni_YGNodeGetInstanceCount()); } @Test public void testBaseline() { - final YogaNode root = new YogaNode(); + final YogaNode root = createNode(); root.setFlexDirection(YogaFlexDirection.ROW); root.setAlignItems(YogaAlign.BASELINE); root.setWidth(100); root.setHeight(100); - final YogaNode child1 = new YogaNode(); + final YogaNode child1 = createNode(); child1.setWidth(40); child1.setHeight(40); root.addChildAt(child1, 0); - final YogaNode child2 = new YogaNode(); + final YogaNode child2 = createNode(); child2.setWidth(40); child2.setHeight(40); child2.setBaselineFunction(new YogaBaselineFunction() { @@ -58,7 +67,7 @@ public class YogaNodeTest { @Test public void testMeasure() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMeasureFunction(new YogaMeasureFunction() { public long measure( YogaNode node, @@ -76,7 +85,7 @@ public class YogaNodeTest { @Test public void testMeasureFloat() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMeasureFunction(new YogaMeasureFunction() { public long measure( YogaNode node, @@ -94,7 +103,7 @@ public class YogaNodeTest { @Test public void testMeasureFloatMin() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setMeasureFunction(new YogaMeasureFunction() { public long measure( YogaNode node, @@ -112,7 +121,7 @@ public class YogaNodeTest { @Test public void testMeasureFloatBigNumber() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); final float bigNumber = (float) 10E5; node.setMeasureFunction( new YogaMeasureFunction() { @@ -132,10 +141,10 @@ public class YogaNodeTest { @Test public void testCopyStyle() { - final YogaNode node0 = new YogaNode(); + final YogaNode node0 = createNode(); assertTrue(YogaConstants.isUndefined(node0.getMaxHeight())); - final YogaNode node1 = new YogaNode(); + final YogaNode node1 = createNode(); node1.setMaxHeight(100); node0.copyStyle(node1); @@ -144,7 +153,7 @@ public class YogaNodeTest { @Test public void testLayoutMargin() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setWidth(100); node.setHeight(100); node.setMargin(YogaEdge.START, 1); @@ -161,7 +170,7 @@ public class YogaNodeTest { @Test public void testLayoutPadding() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setWidth(100); node.setHeight(100); node.setPadding(YogaEdge.START, 1); @@ -178,7 +187,7 @@ public class YogaNodeTest { @Test public void testLayoutBorder() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setWidth(100); node.setHeight(100); node.setBorder(YogaEdge.START, 1); @@ -197,13 +206,13 @@ public class YogaNodeTest { public void testUseWebDefaults() { final YogaConfig config = new YogaConfig(); config.setUseWebDefaults(true); - final YogaNode node = new YogaNode(config); + final YogaNode node = createNode(config); assertEquals(YogaFlexDirection.ROW, node.getFlexDirection()); } @Test public void testPercentPaddingOnRoot() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); node.setPaddingPercent(YogaEdge.ALL, 10); node.calculateLayout(50, 50); @@ -215,7 +224,7 @@ public class YogaNodeTest { @Test public void testDefaultEdgeValues() { - final YogaNode node = new YogaNode(); + final YogaNode node = createNode(); for (YogaEdge edge : YogaEdge.values()) { assertEquals(YogaUnit.UNDEFINED, node.getMargin(edge).unit); @@ -228,9 +237,9 @@ public class YogaNodeTest { @Test public void testCloneNode() throws Exception { YogaConfig config = new YogaConfig(); - YogaNode root = new YogaNode(config); - YogaNode child = new YogaNode(config); - YogaNode grandChild = new YogaNode(config); + YogaNode root = createNode(config); + YogaNode child = createNode(config); + YogaNode grandChild = createNode(config); root.addChildAt(child, 0); child.addChildAt(grandChild, 0); child.setFlexDirection(YogaFlexDirection.ROW); @@ -255,9 +264,9 @@ public class YogaNodeTest { @Test public void testCloneWithNewChildren() throws Exception { YogaConfig config = new YogaConfig(); - YogaNode root = new YogaNode(config); - YogaNode child = new YogaNode(config); - YogaNode grandChild = new YogaNode(config); + YogaNode root = createNode(config); + YogaNode child = createNode(config); + YogaNode grandChild = createNode(config); root.addChildAt(child, 0); child.addChildAt(grandChild, 0); child.setFlexDirection(YogaFlexDirection.ROW); @@ -274,9 +283,9 @@ public class YogaNodeTest { @Test public void testAddSharedChildCloneWithNewChildren() throws Exception { YogaConfig config = new YogaConfig(); - YogaNode root = new YogaNode(config); - YogaNode child = new YogaNode(config); - YogaNode grandChild = new YogaNode(config); + YogaNode root = createNode(config); + YogaNode child = createNode(config); + YogaNode grandChild = createNode(config); root.addChildAt(child, 0); child.addChildAt(grandChild, 0); child.setFlexDirection(YogaFlexDirection.ROW); @@ -306,10 +315,10 @@ public class YogaNodeTest { return oldNode.clone(); } }); - YogaNode root = new YogaNode(config); + YogaNode root = createNode(config); root.setWidth(100f); root.setHeight(100f); - YogaNode child0 = new YogaNode(config); + YogaNode child0 = createNode(config); root.addChildAt(child0, 0); child0.setWidth(50f); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -359,21 +368,29 @@ public class YogaNodeTest { YogaConfig config = new YogaConfig(); config.setShouldDiffLayoutWithoutLegacyStretchBehaviour(true); config.setUseLegacyStretchBehaviour(true); - YogaNode root = new YogaNode(config); + YogaNode root = createNode(config); root.setWidth(500); root.setHeight(500); - YogaNode root_child0 = new YogaNode(config); + YogaNode root_child0 = createNode(config); root_child0.setAlignItems(YogaAlign.FLEX_START); root.addChildAt(root_child0, 0); - YogaNode root_child0_child0 = new YogaNode(config); + YogaNode root_child0_child0 = createNode(config); root_child0_child0.setFlexGrow(1); root_child0_child0.setFlexShrink(1); root_child0.addChildAt(root_child0_child0, 0); - YogaNode root_child0_child0_child0 = new YogaNode(config); + YogaNode root_child0_child0_child0 = createNode(config); root_child0_child0_child0.setFlexGrow(1); root_child0_child0_child0.setFlexShrink(1); root_child0_child0.addChildAt(root_child0_child0_child0, 0); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); assertFalse(root.getDoesLegacyStretchFlagAffectsLayout()); } + + private YogaNode createNode() { + return mNodeFactory.create(); + } + + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } } From 78d6988461664dd01064c75c84b769125104b15e Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 30 Jul 2018 09:30:54 -0700 Subject: [PATCH 043/189] Add `YogaNodeProperties` implementation with `ByteBuffer` based setters Summary: @public Adds an implementation of `YogaNodeProperties` that sets style properties using a `ByteBuffer` rather than JNI calls. We hope for a speed improvement. Reviewed By: pasqualeanatriello Differential Revision: D9042225 fbshipit-source-id: c7f2b24eaeddd1190755bec85a5034079bd2f492 --- java/com/facebook/yoga/YogaNode.java | 29 +- .../yoga/YogaNodePropertiesHybrid.java | 261 ++++++++++++++++++ .../facebook/yoga/YogaNodePropertiesJNI.java | 10 +- java/jni/YGJNI.cpp | 11 + .../facebook/yoga/TestParametrization.java | 74 +++-- 5 files changed, 347 insertions(+), 38 deletions(-) create mode 100644 java/com/facebook/yoga/YogaNodePropertiesHybrid.java diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 17297019..1a765bc4 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -21,6 +21,9 @@ public class YogaNode implements Cloneable { SoLoader.loadLibrary("yoga"); } + public static final int BYTE_BUFFER = 1; + public static final int HYBRID = 2; + /** Get native instance count. Useful for testing only. */ static native int jni_YGNodeGetInstanceCount(); @@ -39,12 +42,30 @@ public class YogaNode implements Cloneable { mDelegate = new YogaNodePropertiesJNI(this, config); } - public YogaNode(boolean unsafeClownyUseByteBufferValueDoesNotMatter) { - mDelegate = new YogaNodePropertiesByteBuffer(this); + public YogaNode(int storageType) { + switch (storageType) { + case BYTE_BUFFER: + mDelegate = new YogaNodePropertiesByteBuffer(this); + break; + case HYBRID: + mDelegate = new YogaNodePropertiesHybrid(this); + break; + default: + mDelegate = new YogaNodePropertiesJNI(this); + } } - public YogaNode(boolean unsafeClownyUseByteBufferValueDoesNotMatter, YogaConfig config) { - mDelegate = new YogaNodePropertiesByteBuffer(this, config); + public YogaNode(int storageType, YogaConfig config) { + switch (storageType) { + case BYTE_BUFFER: + mDelegate = new YogaNodePropertiesByteBuffer(this, config); + break; + case HYBRID: + mDelegate = new YogaNodePropertiesHybrid(this, config); + break; + default: + mDelegate = new YogaNodePropertiesJNI(this, config); + } } public long getNativePointer() { diff --git a/java/com/facebook/yoga/YogaNodePropertiesHybrid.java b/java/com/facebook/yoga/YogaNodePropertiesHybrid.java new file mode 100644 index 00000000..dc727ccc --- /dev/null +++ b/java/com/facebook/yoga/YogaNodePropertiesHybrid.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +@DoNotStrip +public class YogaNodePropertiesHybrid extends YogaNodePropertiesJNI { + + static { + SoLoader.loadLibrary("yoga"); + } + + private ByteBuffer mStyleBuffer; + + private static native ByteBuffer jni_getStyleBuffer(long nativePointer); + + public YogaNodePropertiesHybrid(YogaNode node) { + super(node); + mStyleBuffer = jni_getStyleBuffer(getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); + } + + public YogaNodePropertiesHybrid(YogaNode node, YogaConfig config) { + super(node, config); + mStyleBuffer = jni_getStyleBuffer(getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); + } + + @Override + public void setDirection(YogaDirection direction) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); + } + + @Override + public void setFlexDirection(YogaFlexDirection flexDirection) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); + } + + @Override + public void setJustifyContent(YogaJustify justifyContent) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); + } + + @Override + public void setAlignItems(YogaAlign alignItems) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); + } + + @Override + public void setAlignSelf(YogaAlign alignSelf) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); + } + + @Override + public void setAlignContent(YogaAlign alignContent) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); + } + + @Override + public void setPositionType(YogaPositionType positionType) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); + } + + @Override + public void setWrap(YogaWrap flexWrap) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); + } + + @Override + public void setOverflow(YogaOverflow overflow) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); + } + + @Override + public void setDisplay(YogaDisplay display) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); + } + + @Override + public void setFlex(float flex) { + YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlex, flex); + } + + @Override + public void setFlexGrow(float flexGrow) { + YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlexGrow, flexGrow); + } + + @Override + public void setFlexShrink(float flexShrink) { + YogaNodeMemoryLayout.putOptional( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexShrink, flexShrink); + } + + @Override + public void setFlexBasis(float flexBasis) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, flexBasis); + } + + @Override + public void setFlexBasisPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, percent); + } + + @Override + public void setFlexBasisAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); + } + + @Override + public void setMargin(YogaEdge edge, float margin) { + mEdgeSetFlag |= MARGIN; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), margin); + } + + @Override + public void setMarginPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= MARGIN; + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), percent); + } + + @Override + public void setMarginAuto(YogaEdge edge) { + mEdgeSetFlag |= MARGIN; + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); + } + + @Override + public void setPadding(YogaEdge edge, float padding) { + mEdgeSetFlag |= PADDING; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); + } + + @Override + public void setPaddingPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= PADDING; + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); + } + + @Override + public void setBorder(YogaEdge edge, float border) { + mEdgeSetFlag |= BORDER; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleBorderOffset(edge), border); + } + + @Override + public void setPosition(YogaEdge edge, float position) { + mHasSetPosition = true; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), position); + } + + @Override + public void setPositionPercent(YogaEdge edge, float percent) { + mHasSetPosition = true; + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), percent); + } + + @Override + public void setWidth(float width) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, width); + } + + @Override + public void setWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, percent); + } + + @Override + public void setWidthAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); + } + + @Override + public void setHeight(float height) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, height); + } + + @Override + public void setHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, percent); + } + + @Override + public void setHeightAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); + } + + @Override + public void setMinWidth(float minWidth) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, minWidth); + } + + @Override + public void setMinWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, percent); + } + + @Override + public void setMinHeight(float minHeight) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, minHeight); + } + + @Override + public void setMinHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, percent); + } + + @Override + public void setMaxWidth(float maxWidth) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, maxWidth); + } + + @Override + public void setMaxWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, percent); + } + + @Override + public void setMaxHeight(float maxHeight) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, maxHeight); + } + + @Override + public void setMaxHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, percent); + } + + @Override + public void setAspectRatio(float aspectRatio) { + YogaNodeMemoryLayout.putOptional( + mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); + } + + @Override + public YogaNodeProperties clone(YogaNode node) { + YogaNodePropertiesHybrid clone = (YogaNodePropertiesHybrid) super.clone(node); + clone.mStyleBuffer = + jni_getStyleBuffer(clone.getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); + return clone; + } +} diff --git a/java/com/facebook/yoga/YogaNodePropertiesJNI.java b/java/com/facebook/yoga/YogaNodePropertiesJNI.java index 3ce7b493..d7644ba5 100644 --- a/java/com/facebook/yoga/YogaNodePropertiesJNI.java +++ b/java/com/facebook/yoga/YogaNodePropertiesJNI.java @@ -20,13 +20,13 @@ public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { private long mNativePointer; /* Those flags needs be in sync with YGJNI.cpp */ - private static final int MARGIN = 1; - private static final int PADDING = 2; - private static final int BORDER = 4; + protected static final int MARGIN = 1; + protected static final int PADDING = 2; + protected static final int BORDER = 4; - @DoNotStrip private int mEdgeSetFlag = 0; + @DoNotStrip protected int mEdgeSetFlag = 0; - private boolean mHasSetPosition = false; + protected boolean mHasSetPosition = false; @DoNotStrip private float mWidth = YogaConstants.UNDEFINED; @DoNotStrip private float mHeight = YogaConstants.UNDEFINED; diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index d83f7034..8aa6565e 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -33,6 +33,12 @@ struct JYogaNodePropertiesByteBuffer "Lcom/facebook/yoga/YogaNodePropertiesByteBuffer"; }; +struct JYogaNodePropertiesHybrid + : public JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/yoga/YogaNodePropertiesHybrid"; +}; + struct YGConfigContext { global_ref* logger; global_ref* config; @@ -858,5 +864,10 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod(jni_getStyleBuffer), YGMakeNativeMethod(jni_getLayoutBuffer), }); + registerNatives( + "com/facebook/yoga/YogaNodePropertiesHybrid", + { + YGMakeNativeMethod(jni_getStyleBuffer), + }); }); } diff --git a/java/tests/com/facebook/yoga/TestParametrization.java b/java/tests/com/facebook/yoga/TestParametrization.java index f53f32b7..ecb81ca1 100644 --- a/java/tests/com/facebook/yoga/TestParametrization.java +++ b/java/tests/com/facebook/yoga/TestParametrization.java @@ -12,43 +12,59 @@ import java.util.Arrays; public class TestParametrization { public static Iterable nodeFactories() { return Arrays.asList( - new NodeFactory() { - @Override - public YogaNode create() { - return new YogaNode(); - } + new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(); + } - @Override - public YogaNode create(YogaConfig config) { - return new YogaNode(config); - } + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(config); + } - @Override - public String toString() { - return "JNI"; - } - }, - new NodeFactory() { - @Override - public YogaNode create() { - return new YogaNode(true); - } + @Override + public String toString() { + return "JNI"; + } + }, + new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(YogaNode.BYTE_BUFFER); + } - @Override - public YogaNode create(YogaConfig config) { - return new YogaNode(true, config); - } + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(YogaNode.BYTE_BUFFER, config); + } - @Override - public String toString() { - return "ByteBuffer"; - } - }); + @Override + public String toString() { + return "ByteBuffer"; + } + }, + new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(YogaNode.HYBRID); + } + + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(YogaNode.HYBRID, config); + } + + @Override + public String toString() { + return "Hybrid"; + } + }); } + public interface NodeFactory { YogaNode create(); - YogaNode create(YogaConfig config); } } From 292bfed1028c28fabbfae429b91859cf3c793d9e Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 2 Aug 2018 03:09:34 -0700 Subject: [PATCH 044/189] Update CoC for various projects Summary: The old link 404s. This is the new canonical location. Reviewed By: IanChilds Differential Revision: D9131447 fbshipit-source-id: 77b82a4184fff89faf1da76e922a5f1ce3de3314 --- CODE_OF_CONDUCT.md | 2 +- CONTRIBUTING.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 55203be7..0fb24580 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ # 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.facebook.com/pages/876921332402685/open-source-code-of-conduct) so that you can understand what actions will and will not be tolerated. +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. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 679644f2..fa519766 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ possible. ## 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.facebook.com/pages/876921332402685/open-source-code-of-conduct) so that you can understand what actions will and will not be tolerated. +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. ## Pull Requests We actively welcome your pull requests. From 0e9998020674a3b62c924eeff9f0de04454d46ee Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 2 Aug 2018 03:50:15 -0700 Subject: [PATCH 045/189] Adapt micro benchmark Summary: - adds more property assignments - reduces the number of layout roots that exist simultanously Reviewed By: pasqualeanatriello Differential Revision: D8989389 fbshipit-source-id: 6a0ac800a4caad61a2f4bf98caa314855b70875f --- java/com/facebook/yoga/YogaNode.java | 22 +++++++++------------- java/jni/YGJNI.cpp | 3 +++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 1a765bc4..73305370 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -18,7 +18,7 @@ import javax.annotation.Nullable; public class YogaNode implements Cloneable { static { - SoLoader.loadLibrary("yoga"); + SoLoader.loadLibrary("yoga"); } public static final int BYTE_BUFFER = 1; @@ -96,7 +96,6 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index); - public void addChildAt(YogaNode child, int i) { if (child.mOwner != null) { throw new IllegalStateException("Child already has a parent, it must be removed first."); @@ -172,7 +171,6 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeRemoveChild(long nativePointer, long childPointer); - public YogaNode removeChildAt(int i) { if (mChildren == null) { throw new IllegalStateException( @@ -185,10 +183,12 @@ public class YogaNode implements Cloneable { } /** - * @returns the {@link YogaNode} that owns this {@link YogaNode}. The owner is used to identify - * the YogaTree that a {@link YogaNode} belongs to. This method will return the parent of the - * {@link YogaNode} when the {@link YogaNode} only belongs to one YogaTree or null when the - * {@link YogaNode} is shared between two or more YogaTrees. + * @returns the {@link YogaNode} that owns this {@link YogaNode}. + * The owner is used to identify the YogaTree that a {@link YogaNode} belongs + * to. + * This method will return the parent of the {@link YogaNode} when the + * {@link YogaNode} only belongs to one YogaTree or null when the + * {@link YogaNode} is shared between two or more YogaTrees. */ @Nullable public YogaNode getOwner() { @@ -218,7 +218,6 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeMarkDirty(long nativePointer); - public void dirty() { jni_YGNodeMarkDirty(getNativePointer()); } @@ -234,7 +233,6 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer); - public void copyStyle(YogaNode srcNode) { jni_YGNodeCopyStyle(getNativePointer(), srcNode.getNativePointer()); } @@ -528,7 +526,6 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); - public void setMeasureFunction(YogaMeasureFunction measureFunction) { mMeasureFunction = measureFunction; jni_YGNodeSetHasMeasureFunc(getNativePointer(), measureFunction != null); @@ -554,7 +551,6 @@ public class YogaNode implements Cloneable { } private native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc); - public void setBaselineFunction(YogaBaselineFunction baselineFunction) { mBaselineFunction = baselineFunction; jni_YGNodeSetHasBaselineFunc(getNativePointer(), baselineFunction != null); @@ -580,8 +576,8 @@ public class YogaNode implements Cloneable { private native void jni_YGNodePrint(long nativePointer); /** - * Use the set logger (defaults to adb log) to print out the styles, children, and computed layout - * of the tree rooted at this node. + * Use the set logger (defaults to adb log) to print out the styles, children, and computed + * layout of the tree rooted at this node. */ public void print() { jni_YGNodePrint(getNativePointer()); diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 8aa6565e..ecf13a26 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -385,6 +385,9 @@ jlong jni_YGNodeCloneNoProps( } void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { + if (nativePointer == 0) { + return; + } const YGNodeRef node = _jlong2YGNodeRef(nativePointer); delete reinterpret_cast(node->getContext()); YGNodeFree(node); From 71f1d99494776b79e5d5b75d23053891a047a79f Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 2 Aug 2018 03:50:16 -0700 Subject: [PATCH 046/189] Fix behaviour of `freeNatives()` Summary: @public Prevents repeated deallocation of weak references. Reviewed By: pasqualeanatriello Differential Revision: D9131551 fbshipit-source-id: bc79596e056ae0657a55146ad786422fd0f5badc --- .../facebook/yoga/YogaNodePropertiesByteBuffer.java | 12 ++++++++---- java/com/facebook/yoga/YogaNodePropertiesJNI.java | 5 +++-- java/jni/YGJNI.cpp | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java index b792062b..daca67db 100644 --- a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java +++ b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java @@ -25,6 +25,7 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab private final long mNativePointer; private boolean mHasBorderSet = false; private boolean mHasNewLayout = true; + private boolean isFreed = false; private static native ByteBuffer jni_getStyleBuffer(long nativePointer); @@ -48,12 +49,10 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab mLayoutBuffer = jni_getLayoutBuffer(nativePointer).order(ByteOrder.LITTLE_ENDIAN); } - private static native void jni_YGNodeFree(long nativePointer); - @Override protected void finalize() throws Throwable { try { - jni_YGNodeFree(getNativePointer()); + freeNatives(); } finally { super.finalize(); } @@ -482,9 +481,14 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab return YogaDirection.fromInt(getLayoutDirectionInt()); } + private static native void jni_YGNodeFree(long nativePointer); + @Override public void freeNatives() { - jni_YGNodeFree(mNativePointer); + if (!isFreed) { + isFreed = true; + jni_YGNodeFree(mNativePointer); + } } private int getLayoutDirectionInt() { diff --git a/java/com/facebook/yoga/YogaNodePropertiesJNI.java b/java/com/facebook/yoga/YogaNodePropertiesJNI.java index d7644ba5..2322193c 100644 --- a/java/com/facebook/yoga/YogaNodePropertiesJNI.java +++ b/java/com/facebook/yoga/YogaNodePropertiesJNI.java @@ -66,12 +66,13 @@ public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { } } - private native void jni_YGNodeFree(long nativePointer); + private static native void jni_YGNodeFree(long nativePointer); @Override public void freeNatives() { - jni_YGNodeFree(mNativePointer); + long nativePointer = mNativePointer; mNativePointer = 0; + jni_YGNodeFree(nativePointer); } @Override diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index ecf13a26..7f4dc041 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -384,7 +384,7 @@ jlong jni_YGNodeCloneNoProps( return jni_YGNodeClone(cls, nativePointer, clonedJavaObject, nullptr); } -void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { +void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { if (nativePointer == 0) { return; } From c5d4485db322df37f1f8d0d0f67761369aa48faa Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 2 Aug 2018 10:32:09 -0700 Subject: [PATCH 047/189] Fix Travis build (#800) Summary: Fix the `Werror` failures and update JUnit to 4.12 as we're making use of `Parameterized` features which aren't available in whichever version we have here. Pull Request resolved: https://github.com/facebook/yoga/pull/800 Reviewed By: jknoxville Differential Revision: D9132106 Pulled By: passy fbshipit-source-id: 5e6a130ba65e4a1ebd1d9ec506fdb126ecd0e44a --- .travis.yml | 8 ++++++++ lib/junit/BUCK | 2 +- lib/junit/junit-4.12.jar | Bin 0 -> 314932 bytes lib/junit/junit4.jar | Bin 253160 -> 0 bytes 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 lib/junit/junit-4.12.jar delete mode 100644 lib/junit/junit4.jar diff --git a/.travis.yml b/.travis.yml index 9f7c4a14..0c42284f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,12 @@ language: java +os: linux +addons: + apt: + sources: + - llvm-toolchain-trusty-6.0 + - ubuntu-toolchain-r-test + packages: + - clang-6.0 env: - TARGET: website diff --git a/lib/junit/BUCK b/lib/junit/BUCK index 0d187f70..7cc0079c 100644 --- a/lib/junit/BUCK +++ b/lib/junit/BUCK @@ -7,7 +7,7 @@ load("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") yoga_prebuilt_jar( name = "junit-jar", - binary_jar = "junit4.jar", + binary_jar = "junit-4.12.jar", ) yoga_java_library( diff --git a/lib/junit/junit-4.12.jar b/lib/junit/junit-4.12.jar new file mode 100644 index 0000000000000000000000000000000000000000..3a7fc266c3e32283a2b21fe12166ebdcc33a1da1 GIT binary patch literal 314932 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

&R7;REBZd0NaNVcN6Eoy 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

?@Ib4$R$ZbA6MIsF(ZEk4Ii=sfRBa)&Yo zdo*%+J~Z_4Ve2DlO3H=gri+l&z1J@juzqxm_xwRViQht_&1OavHJXt$3rIeBbnQ$= z6{7tuh8?B5NvT#b3&5vtz!ok*tj9nWQy>b2deChCqnt1&-?N3oU%RV;C=`rq2Ep0` z$9|7Z2fL1tZQlQu3vZLdQ?AdgU_}db4R#CPuX)T1T=XAo-N7Mkcd68Vys&*6L@pI= z*@hY++4Sa(UH8u_x#*i0Cow&F!B^KqU*D%Ax8KFrr)5h*&yr-ypzZW8wc&f$@rh)4 z!9Cdi7W@8o)klls+xdFV>Koblp>m8_G9?$uctSXx+snV@u@q;`tNH8|ydk31MnDW}cEG?&A>isZNL$3fLBa#iwuXx_Vb5QSoS zc1*L^MR%Gynit@tW2j=}4jgmYyDCao)m8jr4>(2v^k~|32Cr)lIXA>F%C;ahnSt9x z1GaRvG`-Xkk+z8kqSX!{MH%#>P=`Rk>2!-3qSK{mioBN_rFQ1|9+9Q( ztI6RR*Le7!y%9!zI8u}a2GcLz&vLLUhCEBh)8L}1t@g?e>Lwh`8TkOkt+zDmDG7A* z*!h7IDGs5jSEo9E!zC2GH5p8bM)Y>1M2ewL?T{E_PAf7|g|#3+Brny}2BWoW8nDnLxaQgd$|Krm|VgXR>c}%6|I(d4bwx(t9Qj4_-|)l8&$?59gZ#XM!LL zhnyFj&qCOTLMNq_(lCm*u0&d>b{gKLH`kcZc2nf6%6s|veBOKp!3+kTvA6sJ9(qoFmReBVj9$vK&>HQspEPRH07 zdd{(FsPScw7($NHWhHJ?2?{FDNO-#B))CNkUaa+srxL^|v_e&cuJ5kFSN%qhNjl_YH(V{ISF4U#Yfz+gz5TSG+I9hWsM(Bk5fN#dx(2?FM(Eb*tGz2Jb{J zY8Ai7a6iHpFThsiz+3L~3ZLFncL=vHhE$GTYFx`LF=7_pq4R|==h`&^J$9a%O>-T0 zEJRwIV6*?SINx8XX$7%D^XuO7XM(@`{q0LZA{tg8xpbt6l>@)TlQ@Q6i=2>y-#vHdPcQcoi<56xTBo~U;b0!Wj@=!MKa zlLa>@J_NedkI-7@$HRz57>PWh5_-h^q_|Xm*Vye(>E!a;uyM$G;NUgFLfU95^gD$j zIB(fSpgAh82AUT>o<~~Vfo6&*!dS!o0n#V~tTw_g%AOs9|5DQbRaH)@WnP*98K)CE z5D@qO->Uk1kegP&&_-Rs^POpAoV@ghEF=_K2H)?5q18)NQ`8o*WeP7wq?NR0xrVJo()6J30FGQ@z;1i0FcT|@LbAaW;7tOF6 z<@1v0&+u?m2l-MNUUz^)Ox!*eCau$85B-uFj_;F|_ZI7a<5aPOf;9Xr`T-;#JQq#? z{nFr{$GE7yW}?(UJ8Wb?0$W(4@tbK_4u>lAswk8*iz8=AmD|wFRhOwoWJH2WYd@UI zJlQ$ab7YH4Lf~V!o?IK$<)-q4{2}X99LY(QH*ZnmxhOHQo@`V3v84^WZkb|}O1=hmX|@5pp` zmSmO)wYh>Q$rzC*;hoVd0@!9U!^G~|t<@Ac)Ec1@+Y*yrQpyum%aV<{b6s=}xopuQ zaGO_xp=`<-EHYiYMo%C=*k$#S?#ksK#+xm(572mCPNDIMUu$UW$bWL2$s|~7?hyv% zn}46?@*Sz**3)gQ+gz?CZWDnrFS?i&ZlsIDF?kQ(*yqe=Im5@qG+5Op+HV{gP=%R7 zK;3h5XlJhsdFP+r>-&J`yF47EZ*(27gcn!YZo|1xeROt!Qsy8c0uvp;$4!j~dMzqh z1rL=`=9{snfqFgwjwm0JgX*f+?n8r`*)KzeH`3^HM$R3bA;ldIf_+v+w}s*#Wx!-Z zi^;B+Rn6l~S8Yiaig=$*cT!^_VG&c47lqzhj9j%`i`7WhUXHFTCbsJrI~4k%@tGje zEA}zzO@dszk4>N#e=DtnQBOz|CJM#g{%zzoKUk7)b0`WVmGlGpC%S|5fbG{SS+|U+ zuBdm)EzU!TkHKp~7e9eHk}oW%zWw37Q~B24!WbVCf0 z4yDXRiY;W&ppNd}kEC13t=9)TFKMYr$#8UaCCEr?w613bQs2&I?0({VUhYdZxKc!x zy`T}!OjB{K&7JVy0R9&NNj!wqD+ZUwrROl4L0w`gWZm8bH&!&>y<;Mzc`VJP(=RQ_ zHYz!z>OBzdv-C;z3fCdV(PYmJg3{w|8U7@DT3sSC)i|QL5>=uOcQ zO*X7*V&4*k(Zdq6d+!6I)Xw>ALSK6FKCK$R1%GazQ$=a$YxP1s-@; zr4I;ee1N_`e!GsKDvlId6JHL*8#i+5LJ5&z1G(d$Ec{L1LeLogLN5TZJKA8HPYYU4sQ7@mm9`*) zR%d53TNs88hSO%O;0c@!eR@*@Ie_eb-}Vu40jqBklW3%2=k-|PiS@i-2dO)W)jJIZ zLhL;-``J^A?=l^>dBk}YK<35d-Jnm>KU>p7U6l#*UkP8^?C0v1^Zl_vQQfjTqZYld zkx}0eSPyfE96Q+0z9RxL*sz_oI^ckG#d>C9BDJDHyPY=3dssU8=T%)XNQ}bCPnhB> z_Ua{!gjdWW2leCtv#gGI_?D=9V~$d7mNGQL6k8UZHIq>M{u56+TxQfG*l878e@J^X zeJe}YT@h?dstcCA@8@iBdEUTmtB)iUgoK@0uFeWW^mId!3=9zB4w=vu339QM( z?8uRyo`Hx9&t12v#~rC*qh!x8r`%K*QDaEm#ug09mQ>K~(qfQ` z^sIPC`B6T`d{lBKmcGs*TPflvK$GxNRbJznD|2D`h#({B)QDegzA-ydxH@FS2h+v# zdQs6fWsqtDnovsZYI;S4*CDpI%BpH`%VfoLM1K)BhTLm}(B&^nRL;>;txQX-usC&v zsxHMfjCE5V8tv|p&AN|NR(MfTZE%!x9LYcaB?sxMwN~=`5!PTJG!wi*n+>>d*^FMHs{u6ipyZ!&WMF~;h{)=() z6&hAX2+ap=96b_faR4Ctfku-PgUiDJMvoz~N&JotlKYjv`6k)q^YI!o$5}pcTNyKT z&j>&#t8n#b2Hbt{1;@r$iw`UX9!^|@tXjW@^}JEK*nXZ)y%lmqD0IX%k?u&>s6y@uZU_`!T$2F z_dp*OL7gEDK{$fYy?CaZa~arIY|zJy3XUFV-l14Spq1 zdclTI07=)ezQE)fYmmKZqXX+o;jJ53J2U%l-lC zD$m;JG#>l0g?T>_S_K5%{G3XbZK~|9D>ymTd6j%Gu8N zLTPNv8Lmy$?NT`dvB0XomP@q3Z0yl1D;zhCLvOZHmDM)Q2WNn00|FbpzPtbh3QqTQ zdG_13w*~vvHB~sf8B)JBoPGTeWR+EBcIf}%dc~2vWT#}`G>`iWH zn?|gG=peNc_Hw)t*}R?8-fRO6Y<}<=H=0oYA)Z6^bivhPRa;hvZsx|()OLxYMwx+_ zn|1dc=x-i06&I-tTcmCL2Nm z`heaztiHHHeR%>uKp+@3%Ep~jdmXO1lk4DibFFu8(KsSh@Ob2_9$m?W3iKgwK*=Qc zD73I6-s+HC^^o9nk#yrF$R8w;KLo9b8^6GkB2H!1*1_44tybA%bBeBTwG1hSRJ(5E zTo!eTSdmf6srFo1c2NJMeHZ-}?jYlcTSzheBejcSGsXbPxOX0xLA#`IwA-WN0XP&3 zD<1md9D-5x89XB8FJBJ~D!JY;or=d{!n{+z|Ei+DCanBJS1@|OO1cbyTl^17{(rr% z01LB!#VwfrvyxQ*_5l=*52?qb2iZp>wL+$cf~Fk8Q5XHD1UCGQPh*lfh1SNcVl5`0 ze~2YjWDeg_zHKr(1sR=`cCV04{!W&p9GEV-UpI6M(4|8;`sfh%p+blesi?R2r7s{EVc! z=Dak0T8c$JPoBe6c2%Kpw9jOrsXJ)yNTt|o9O6C=NQ<%wYPbolI6dmUwGthUHJhdu zOReQ9O=zQs9^10h7|5BGCfHnvxtmPKk#?=H!c(G?KA{*$0VWD^aS8P;-Duhb(IwOj z&0&x!O{(=mhf`YyqkZckdNP$cUFnXCgmrul)j8H^v+j&j zM%duQOkkAK=_Z@*bS-&XA zPhP9ctd2?G#Kn7?f;N;gNw)+xF=i2FKyFBw#N$m7`5ksaPv0GEjH}DVHv)%LG2U4c zj<5$(hFNXt|3lh426x_WYr?TQwrxAZI<=>! z>h~$1QvX|PUF$*;nA^!KIdB&-mNi4BOJEwInOKMlyPV(#ZI$6@eHY=W^9h^-JI#oV z>nm8K(6JEn1*j+uJ19*|XM;-U0?MpUw859)Bk=8Wgp&sWD){~bikwFuau;|-J4Lq> za~^ndh-pI0V+@=KuaN{2yV zMhoHZvO(Ng#AV>|}WFn<)vVL=&j+tmHd&C4S!09nn>uL)lk@I{P$GEL#(oTlcj zc8nWHXA%|PwMOBR?F7C9ehSN06m^#CP?1@ANf2=?k9%!!_9!L-|5Kf>!hK!QN4;cK zDUSKi^wBt3eP>67)X*NLQ|-&7mB_DDG-c5K{NVje|lpAHcq z2i0ktQvQ6o2QN#Oh~TRrm*n5D=`)8gkzR_#6097SZ*KZ}MvvWW?grkD505@)qvvApCS4U62>_JYhf&Ifp*IEt#-U zUn6=?i7x~29(1gjsRYXaykucAIzN*%A3d`{A&uR^1j-KWElN1^gqm@phQxZ}Yik~K zspAQQq!CWDiB$sRFmkm-Z(@3{@;c)}n~f#~*Bn){coK4zF)fr#Xm3YmwF#r3GO}5y zhGDGp=w%sx_sV>0$dC1dZ$N~NE}T`xP{m+&1*U6YqAo5eH8G3Og!F_>#Mf@=LJxxa ztdqo|Gr0kTTg?EyGDr#-0a9R3ZMCG#z!l-VzHw%GR#`D*FYNd)HKd&$I<~ zGwvz0Jpk)B^{Nj48gR`PU38^zYW4|S}MzuN4Y94a8s+#agO-lTh}T?+Q^yN~7jIQ=Iys{j2c{o@EF%5h74=cHyvh8pM1 zJS(Y&5F$3%&h!eWBS}LLAGTz$ma--jSS_F9w7d7bv;6S(;T6xgqmsf`J)iVG(P%3^;f5xkn($yC-8TRSlp>8ryJCxM8_6vb+Yr5 znH}}z*EySqBvX*OTe_H!cxGRkwe=X8hL_>YZE+u*7j57|7M7gOt?lF*OX%O(I1l18 zq*RnPYL);!e@dx+XIqMnAxPbGijAep714YL-9x}Q1wtrn4L~dsClw;5bMpw%$n@#i z*^O0ALEzBKqP_%&3ctRg79dm-;JxMK!xn_D`us!eKe%4NiLSqkj!ko)sZ%iG!xy>< zg_DtZ(j`lv=(kY4<feerfn_i>T%|jmmX5sxW&X#`_>&^!5tzLg= z@1Xx*hK&Cd31_NU{$;x5Wd)(OOiKp})$~wUSSkf{;U`}UlZTuuFEAY^zgBipw@&&a zUF+~N2<^`c+dB$}K1Dv$CxG!gjMwznHhAV~YkFV+JaPT_{^qyw-5b|YhWq5o!IBE^ z2heZq18Ijnfu9})dEiWTE&0Edg*bVXXQF?i+_g}tWS6LRb0;eDD#iBYg>fYzdlYTk zgISK%#20C7HndJ*Y>u_&l~k)>k1f4SlAzy{i4;DXVw zhZ(uqWdOmiVd%5Fk3$CaT17qYJIsZeUE>n0SlxB84bQPwOF9{KP|mQlV%3XVHaQl0wC6 zt}ZAX%e}6w0Ntb+dM_HLux+L|iC!V`5XmSJO!SRlPcmj#@6ul`%0L2rl#(#!+fZ5N zHfzG@!R5ch@!n?UXY^6a&vwdYo>@rSV4ezrS z%d6%W;k#~bZ(Ow(Fa=SKcobfkwL}UU<^-lB{$?qpPaXTu=nvgngnt0ktExm1!qnrD z&uI1SxM0p$HmlSOnsx zz#tt#Q6CbEE4ZQDgk8B54?iBl-0`mVHx9l=#w;+Y=#dah8UWt-M27J=^MaEQ>sgY@ zow4H2S{Gb}si9+I`IQ4)ZSp|}rdB~4)JI?se$o}K(eGqK&^%IS;lmgR2c*VZWE-W7 zW>TD;#}4q4{p+E+ljGxGjJ*EB@^(B*u!p{%nU!xO;^%)*vHc&gynnninF?Cw^S_X} z!?C-Fc+{S~|ALIxw@ z_@nobApWQQW$O_x=^roeFUa3maQe(PY`ww}08fM#!Yz0^zTLuG2`@WYw$`HYiBUm} zbSDd@;zQCHG&T3icYM6bLVSV0?pkL@FQBL$+5~)StYO7|8|E-yB*r7G0RJ4tFolz( zyvuDEy)vhF5D8<+f{B=jvmN1w%*2gXLYkF64CN%$M?o2J-$R#U^p-=WocnAcn|}Sa zDV5n)Fs4r;V;m`*jPo>3oOC;ian5HbtXj&fmn%6aNYgC}{1ARw8>T|b<%iCP^Gi|Qc9=ZOQQtg^{V5Fit@mF&{oM+Fx?xMvNo^Fp-U1Nfyw zKfF&$+ZQYsTN8nzjaC~*)!0pI&&BrXyS;~`toF>PWU8!mA-?m95$>!)g~hOF14D@H zVdw99*4Ri&#AbWO)tlH%HNk134{<3lXs8C|<2|)lJ_K>( zN_jrsSn-tpf#lq ztpOZe>|p2lZE4p{l4NkRYiZY3&Iq@4g3uQct7^`*ya6YN?hbSyi|!j}>|1gmgE)sUf-;TXQ>AEC7!W5aFxMxz7@oBjz*TP`G08`nlFU)^ zROd8pVN0G$50Z{$FoFk)cx0f}BSI1#I?QP+$fP8n5$aZ2YOr3I-9Ix%rG`AFm<}C4 zVr)L#&uV}cCt+7o%XXL!H#vpF;pkbLm!5};3LRuE_4Pl8H^~IEPso8 zKzr0E#j{kzD!t2Lj|x~0ksTQVqB28&#?^nGkP>AsVK2sujoIoK{(g}tS{L3}EFG$u z`$$!!)Wy76Aez@opDZ5!4!*xZD({mKW((Qqm@{q2F+Hv&0Hp!tzlcEA;oun06Bk?x zt=LHF>;uoEI5N?eSyc9`Y3cYyMPkHGQXx+nP_h#TC8U)7Xy9b{Lni#7_RzdQz67e5 z53+u=-)PL*bH#Rz0smC(0Cg}gnVzuR+Spa>4_DxjY#(k-j(5pvvo zJ6Oc?)d5Fw8tLxKPeZ8a$Un3iw&h657Qud9hZIaQ851AWLIT}MJnPnm=P9+53EEoO z=8wgp1DK0?nL$!5vVF>GdUag>bS5sSQ>D*&L3BG~)al7#`CDO%9zuO8H(YBc39hr4 zT|w35&p|=fyBhCZ2f&w)o=$7;Vt@40M|u`8m=M@3YQNSj-nvRc)`*EPyZo=ro^iEv z8is91F9e$~VjJ#@Q-ZGcKy}}J!|=YjG}`mm`YM$&DWet=5IZv03MjmLOZ0TSSd^5{ zt@w>-DrV21UZuM#m|l@vCf`ceA?rzG;BSPB!ZTfj`5o7L`dVb>g>2;m!+YjhSP zEDF7kBDmS9f5w@JIotb(q3+=_i{DN# z+4!y&k*(6I_mSz!cKv>YYnVhy)0RY8>FLrYR;d=)X-qvR8km8OsFHYNl+aV4WG{Rq zX-Bu3Cyl$LoFN{r<>?yit`n8?nVp+098(Rj7ZfOn#Ku;C(2THF z5h{earABBo=SB|@^8$>Xh|2D%u5k0dB^oHa*be9rt`-dKk?dnNSr(Jw=rMRMA3Jd> z+wsZ1)9t;F%H0GP?2)w*Ikmo+0*AW^)VYLJFm$d&{Gkft$p&T85O|?rz?_})9K;<0 zO@{@EyOdz~o%Jp4owBKlPp4s`ZP1{CG5=xL;F%<8@q*eyuwn{V^uy@0qlPD3B}0S6 znX6fbysiMcriOP{eivf`DIV2t*BQ^&v|Dm;30=61{>Y!1hKLu&R8(c=JB#rE0Cg(n zj*Mh@u{=7MZE}(tHG}H$q);v<+nAHd&5v3t@J~%!-JiRHXONFU4-~Y5tvpEcR-2ac z#z4>0 zP|C%-%n`JW&aW@)o_ybkr-oaijhlgzf#L%2wq^{PTm``rh$+Vuv|7v{(4^~(g*jk@ zlzNIA>;!OO87%kbfIe!CG0GHXZYaPG8peZ_*$$&`+;*HJU`45ASU-)4V(x}SatSnX zCcn>BR2>ooLJx;H25pDBt<`U`a)6}fnnN>6;s*Z;*Y}d&5m!qq#N72wJ*W`(Ddtdq zG|jjD+D%i~$9NZZR$EvWA{6d~4{nxYed?E%`0?#FE;TS4D`bmQygw%!+~qn~%N?bU zyI=6!duVs23g9|nQK>Ih@fGk6aUX^WU2=Pw&)R9~#%9e+-nh;7(7 zeMTGL1_BiZP!x_J&_a~7+$1d|MH5rcfYF8&F9?}DMaUhVpzD5t?U42MefV#ed^0jO zG71;O@YhwWS{G3S?DIGLit9lBJ-Hv2{jGhFz_2A>UUQNx>`@Ib+VwB{>f?e{(W|jDD$)2-eE%tT_ z+0F)pu_2p9K>O>GO zI(}|8X0T@%D}bYG1-ryE;cOM$mG<(F_Hx%GmV3;s3w?2ls@zOwjkvr|dSy#fq#r{! zWg=R=ck3L8*?5#CZEkpdZjXV;SLG?`{NCJ)EsbUHt3uf< zn%@n;|B&eLcLVVE1m+*rWnk=>bnh?ZpedVjXTE{4UQtc>(7{2L!G6(DQcAEgEM)=i zB!WKZRA~h5i9on*0Sp-_5UI45loQ^smrwhmi=m@6&hNFV0yYG1!dcdh!L!F8^1qd< zbm!dGzZ9?HZ`O~L)y?EPk^koaCU9srj*Pz$hQ~b~Ktzm0ujYZxo5U4a&ZAact;*G>eqWztgFr0)00=1cctVm%Z%sIyQf|KE749~t5TXc#<6_AD>u^%PCL8yr6>i5fwpa4U8%2Xb!0Fs%VR>u;u& zrmlY(nEka}SZ}9UeBUr7#CJcS{2%lJ-{VU|JFD+xTRsa5ssBm{_+O2i9kG<5gNe1l z-yNN@u7%_OQsyd~f8&?vUea+!0+_T1i}!k38q_<4fME+s+JfXEFvx&%-D`C} zh-|IhhXnHj=*AKQd86Z(&g28s%0!($s9N!6oz?LmJ^JAVel!-!00bF8TQnW zb?~dX-kU5X6n5L;@K>|>q!!(OsLRgUV6)NBOa0#NCohKODl$=!yf2Bk`Q87f1O{;A%m3Nm4*xx=sZEX_D4?XF@S1KF=J!tWg&R!OfDx^4GQ- z%c3ZzNlXoY$RR+nhf20lqY0yIAt~J9Mhz9E%44cVAxyZD*<*FwAZ3pq!0Cg3^J8Qd)0cU2z&= zlA6Mbs4=Fr*1&8^i7P532k-HQ>|KLaBu18ANXd-AD9UD$Yq*Wf;}y{??=@52lxz4l z|I&0642YqBqxwFsL4nuGX}vPPpH-zW z4LtIdBghAe2{&HC)LD3Q@vslaDE+!PyA9c}FShEKKgwUd$X(M_Yc}PadZ9OqE~uRw zNRGYP>`Y$&1%mwR(o$81Cjf^50C*t!2AclgF0FsOIuq)UE{Y4^Ap?v|bdtF6bvuGd z2!sK|=(6*O5Qw6Fs`!fVat%(B+P&TTQW=u)6{u&lO|+I;c}u`ciF`h;pdlD8 z0yvq`_F`xcX)j*7vuxJu2w&rammh&8-S&*n9b8^=s9q!8$^H;~RDmvlbffLnm@X6{ z;;veu#RmK4vmRPT-b5ka-Qn%CrD+#Zzw=EU^A^+f2mUFDFpf4wH{AYHFz9pa`)3P0 ziHmA~r`a|cn3uXwHYfugFWYrE&^u#@-8*H7&K?_>7uBCXNLsk8*KhbqyKsJALcre4 z*JQxn%07Or>rIvYv#JHfL#J}&TBamygKH`xh_SR(rX-6(dYwsre`ru!j|l@$sCGjq z+oU?3nAMVx6BD@|wQiiKl$#e%#mp#vAOro#&!`dA6<&ZioKi2|))?gryrKI3)ytaC zJg90}?Ytt02B>x|W0%`R2`Q&8bLd(b#I>+y12i<+D+L?I>f&Qnwe0dyWCSa-+DfD# zSVb`PYZH?~F4X4MHgLk#LqQ3RG@30|O-WeBS#CB3(_^OP9YsfQ`ONb&orqV`Yf#74 zYbokTYkk9YRD4olmwkmg?%V>e^bnS3Y(^ zn#Rk|D9m4mI&4#nW3oo5gUkiq^cxvdCLak=jmTrx9Ry&D4G!!{1Y0%NsIz-c#o}8x zkfKbEnas1uwKEwRsylXw2!(~lLEkkCR;G;KIg5%ABm~jvI`&sI8DwVdaY(P?ZqCw3 z2T@6Dth#-YR%vdZvzq+QByQQ?Eu$`v%;KdnkYePUs9R^yAjzb%6dzSw)~cS)E=*H> zrkSy7c$|bW!%nr5Bqm&wC${E+&i1&=C?o$$n!_T@^Y5K(HhLl&TLG~v@=p&X5z<)F zkkK%cs1)Fv_Z*d^-OQMWKEw+Q{b|IGVWJo1anP~y;B6l20KzW>c^1NAXVY-9{;dwJ zFAtg!tG6q}9$-m4Y46ulCQB4`cnpKutQ{|%vy(K}2b_!NDJ5Rr1DG!4@0i(KT+OAg zHxqDz9doLyPqjox;F1liKavR4TS>G#y`eUD03wTtARY!*a9ac#%34_AJVQ>jzmpF$ z!?eSk9Z|t{f~jN1MG{~~)^Y(EpuxToqcOlHq0OHnhBG|X#9WF^+uF^r>`R`d!C)%< zytD~KzO@N&Di%zF6Z!Rl1u}$XMS^|^+t+8KO=r##O}=N{pdc0mUYG)5cz5|zg+5Qe z#O_<1MqSi&YD62HxyC11s7Z{3VlOL+|93G0II&uNdvIt0co+i5MfrKWC zluSxEVR_7St%9VoV-5CcwTt&$9Qy4F5V3&ZmJs^2%>rDV&OY4OvEFG!Zdk^ZICVWC ztxY?zWPWrkvL9GmI#`lZ3YBQOi+i7HMy<`Xz&>OC zpu4_JX|JUu)`e+ZLZ~1mJ3x9Vj91AL;h(bXdnUO~K$%#gCy6da~Y9UPA&?1ha8;U-EE(%CzPRkQ~8Fo8#j zf*;%bJr4O|Xnc*mLhWiF0w;E3W=qKIYZPKp8YwO7hGOEW>ZY9VIebwX!4IPd>X8() zqB40^8}zJRVwPKny-HJd>@9=A;p(`u9A=eCJ=&_Y#Qc4=n6UW>IZ%E50^`I+meRn{ zT#K{d*|H3hepU7B`vwUkvB8G<9d55-cxTvmO{8y~u~a}{HO5^iiHZSd?vZTpQn89dSN^ol8sZ5=!E zFTm@uelQd1$R2+ubg1;6m^cU9?Ys!^PE~Gh1`a=6nY#wG5mma; zr}pAj4F$4H%Lka&V$CF8ss_per{B8Cb}oAVm>KlI9^Q^>v$(SSt8#LuNL#@hI5=S|Tj4)=av|$=orHo zeuQIr|DBQ1_9udlP{-13WQ`+7>QFB~I7Sv9EJrPZm-x9La{90g!KVL2 zh^d#e%loCxOX4Q}AH8q?95h4rD?0|uyJ!>+jhkTZ461sxA9L|csXVlirc&DpUXm9A zrWb$#Q-q1Y>_)sr2Rq|h;5y4^t`ZE+zy~rUy_kAjftZk&u9zzZ4(-E-uEVJA|MkJ$ zU>gfwL+7=03*0cLBI8-YBhN9(&3}tGIX>+yI(ZM^nas)sx&X(KjoF`P@dNCnMo7!r zQxgX1vlD3dlYsPNS(P9o&r`~PAn#3n*>nGb!Oa1KlNCrR6%5iZ3!*j=gIldnAfHYH zRaYWyK$^|@DSGeL8o_1n&4Dbvui(?;hwl=o7qQIBp{ghfjE!xpA-u!54s;Q?4I^WtO7R6FR;ro-%gy1QVHH+pxnH2yBeTW?Lz98%?asm3G)mEVCLahNO`KY?V3UrENu?>Rw08>(ceE z3^B2JIGb++C5|R@KXq*uUcP zmcIW5+c^GC-mijR!&h!b@%P7R55iKz=&-K%IIRpJTrr^@U~uf)ZcS{m)mWjoq&l_1oZeE5}i-lJ=+}W zTul54y2FX8I>5Wyx&-tJbYGS(llx$Iof-vB@m99|06^usbigVoXNjeEN&n33mW)q6 z+;qO4$n3w>?Rp`PKhwfAW_eHY(Eb#$(`(XK6#woi~%AfSA+0b?*>I|u$u<)x_A zS@&2g^g{MB>Jjg(XJ?suS)!#dny_{Fom`g#Vs`tS-D(dvnD-YGU(hMr_y0&D#! zP=g{In2bu?sXY{RRNtGUvO()jJS9}W9k$NQBg8t_oo!Bj^aq)N!Oa%yWJrth=muGUzE9$O+hoJEy;`|K4W!^io>12Df>y?um!JDmkyF0rF ziU{nM{``*Zi8-wN*lws(&pUo4zE7IIP zC^}k{3OG8>?t<%cLDm;V1{g)eZAzhr>VX7x1HAy+JKBFEd4CZ-Rw7P8ZoW~x(r;?+ zemEu( zq9e8M)sCBW3C)RusaWBlS+^;JsG&8`8Dz;eW)F8KlbEODw&2$Yk06?3(j5hB*{yQC z_)s(v5Nhd-({D!;?+PbSPUyl=fbD%mbxBF{mMniP1XZ{!pfR(Rvzug7>1O$6-?9U`_=Bxxhg@I zkTzAiI#znyZ|SVWl&_jXZC$ZWH+huI#nNUDY5^k*2sM;Ifd!e(7Nuf*S07Cv) zLTrg**c{wipX;J?Y5@4L2PwH76gUE6r8nB^0K}BSLa#ZOf{Fh8)TF4FcXC^Ui>|kc zKcrGW(i|P;cK4}dob50Hz-^Fr6hhU+dL zZ^m2cVWYJDFIHsM;4DsreIEJ^3hZ*q?=e}>_0G1|2q%4F8G2Gfv4f@=d=bw=83*Eb zGZdRkh$!|3z>8)MBFumgaZaJ z^vK2oYW60C7(d&q_b019QFEp%h(&4qxjE){Hs%YP*o_{A`@p^CZS-=J0E;OyP5)?t|tHazN!ZJ!0FA{6d z(IN6`|gr_JbznYF7R_?yn)_WB-ZH=o4 z4M=n6R&KIiDjX*XpZYbMnxj9$e63LbF~TBKEvb!)-Z5aS)H$GlLNWA%r7BX;@x_M{ zE_Eiw0#_264uWy1228TI<^n?1%MsRrdAxyT)v$p35N+UCJc3jyEC4{q(Mqcdg!;6r}jodycP!*QQgW(PG4zBwVM;lhNb}q6X=X_N_&F1x*~TkT79Mnr zo$6*bEGa9gVq_Yug#kMIH00QsRp$8ho>o>7Ym~(wZY@dzbP&`xnJ>B<_Os*MuDrbo zQp0p8qcifSV0f(Z)LxwBRn^avk(u9CVp_r?-F>ABcw%aqetGDln+6i5!Q3-kqsqz3 zO3?*wq&4R4RI#&?=EHLNRoHE9U~6J~59w`rk?^Op(_QBkf;5F?gOi*l0Mpmd_ZkYt z8ar!Jp~ZmT5D;S1wku@%4B-x`_Ubh44%Tx~K>7`hwl@5YCFE9*b7|ud&?1yacw-+I#=Q70( z{AJAbkC;kbZLd%?p?C4#YJ_}-u5BBOCHedle*MKixic|4Z7i{}2Q8#K&F3Rm^n}0X z{BkoVOdSyD#GbjWbbi&7fSitG0UjLA=XbgSTKigARhMX< z%!q#vctFX+y&1g_wUc#=KW6#6?UsBf^btK+6k63R@!W8-I97~t@+lWq3ofNVW7TcE zcT%cVQL8<%vpH6`xx2XnO$z3w8+y2;nE7C)KA|b9@EbDURzzCgdI|iTTyndOYB!r& zwfHzI13*T@Q`^b3e`4q`DFCx%J@8=2Iy)g`v^WT3sl$XTVmWUT8$lA&(>WS7vJjJb z*``JaE4(I}04f+98z`pP98L zZ{PGLDIC|TD#XOc^2?CP~`q=?JiTzu!(&|ufTsxd)Nihdkw5Huit6_`z z%AKlnE}-BDzjFp6|AFP+iO%!&q@Iflk^s9kq{C)U=($%4ZO6N}*OR7FB38y6#;B4fuM`j#<%1v*L$D+RG7Q0faN||cJB5Muu4;JS!mXR~s z%EOGY=N`x{T`oQdkZppa{eBW57*90asv9{DUgr0Ke$hQ$S>J_2EX-H4u=`QEnU zajoj&-a~)LBud#ySvPfR`o4HdtdDj-HfhC}g+!kWku_8}Xhz^MFWjFizk&1%R8>qY z8uz%$3qhgn)N_2xx|mQBqL(7sj9@B=s40Han;hhJ^7d;m@B`$NT9FBCApTpaJYrPS zj9x@CW`v-pc8g-!Q{c{*dcm^9^9BW64z5@;r@NJijbpNMM1Ex>rr0`?CSK;|j4-#D zQ{QqDbuE^6>e1IS^>>udQ~MIjvTGF>rUj@!dyX$4l&>!hqNJ)a!1oCvZvxA~AN!M7VyDGdn}XifgBQfQ zd1Ru&T9q&|zfG-E%uFy6S72&G;y3wGl?Dk@ZC1wh8XjjDRs*rfaj1qLB$v%_cwS2K z>b!oe{Lq8kW$HDOV7D;U_Lshao59;y%=pD491_tQs7ezpL@MhDMlx4|8zPw(WI#1Y zWT^VnceP#>+ZD0=_ypQ-t|XtRHm$1~?@xe=;V@ls7$7J`wjZIKD&>d=QlJ47DDhr5 zDqD^QHu!DmDPV*Pb`1&m22=Soo)#OOcuu1SU5b^;^FHIYCzVvObg$G3tqV z+xqTPs_}rWnxSuYnRE9L*Bcpp zr{BXK*qwQZfhSaNo38dsx^! z{sfTQCBX$zfTEzG*F2^9H_zgjVrx`o^=ge?SZ(|GX^;J)=B{UBX|Qu{pmS{G9{tkk zVT*%E+G+DL_Xx=)J-*p!w|j^T{&9wSncWx5_^ALXD+}4i#Wi|yO{>BQyqtMl*5j~} zDG~I}Aj#@vz#}-kb)^S7$a4v(V+j~N12|=<*`heG?0%$BX_BJpNWwZFw7u}Pw*u8Q zY}TF^!J}It?j%-4km$_Fd_NKKv%O+7o`>?$xpMK^rJ2RzBKNF0%(L?hB2j&ONe-#i z19l-66LrbJ&A|Rk3=d^CE(q~RJSY+K7yMSPVJI=MrS;B<-o4<+} zKQPbN%5*ppGX6$=ukc)!sGXF!M@9brZ{+N2QeWhO?_obT?6-3H|7LEcU}LCnYGkVa zH(BHFq5nVTX9LQXDo7&eo#_G8#NqOOq792pl*B$2&$G&Ys)D8q@Gl;3w37>vmmVZi2r%rb4y%pCu#US|nI);Ce9!VY^th}weAFZUm-(6*U1EUX)K}`OZ zXWc4&=J9)Tffs^@Qz{^W(5DQ8F3L~oAzB$P8!k%;$EWOL=8F1_`$O*Chpf(((iTeMXyUA#1lFxttI0=nxsrmCz#ERom7jF z+;W%hi5DMx6$RHugXhj_#z<9YMyuZ8C1w}Hp3Ul5(&8euLJI|`rc9RX!Q* zXSKOWjXYR(Qz-LPfRp~N3M1$xawx{JG}pCji7HW&x$?ob++>frSu*S~#GhLZ7Dize zqU+Fmp*R{9L25ynOZ8n6V9=(e0puZU)NOh~ddDcr5s)cpC=M*dtyA|wSE4U`Q{z-E zUdXHKr-^Bomz~HB?Ylyuo1tM)t@%>S8CAX1DPFpx*Y=>3i_Ff<+eK1SG9!wdX1fck z%39ED2lQ>lbowAzF5q7uGnS4QP`5)Zb5~QC`mL5Km&%0$&S*Oc*FT~(!%?X^(}H(S zMfvQePO}mO*|48nQT)Ufc2QMjDwhnL2cKl^r~-*9M6c< ziuVuu3n-{=-#5XhVhnP2sCgD_5R#FhFN*bN9mCexDU+D@YbyAD2eQ=Bn5;WSs?3Uo zW~srM;-CvI>k0PWkI21Zo$Wkl2Bc$AxKY`m;dt3<$@u) z4ebKH^a+B*;IV~f1E9L@Cf`e9A=!VJzrJ7STf&nOLY-={3pV^g(>S9gq?S|+&31;J*0^h z-E?+=82E3M4l!#J*u6Dcl@nBbOMTJ(su5NNYa&oVQ~$tw-GZHpn$$!ngA&o)Br&cc zzlX`Kgp)4|IuK*S4drwSzmYaDO4Cb6mRsB2+F{@T4mJ%5+}L1bgVbEFd8gk@UrC}@ z$X*Izt>Mat$6u<=@&s#WrhemAp+{n_i4KJsYKWOe7Id#UjAeL`#4iSTTXkO0vaE*l z1E>rkW5`&fgYXWc=Yv31*IPz0CK#FnESR>PMhYyaVD1Zz)h&;X1IyOS?JMh5lW?_E z%HN;xQtm}u-kX?vj6twTfV4){bd_#ci*UP@he5k=+M463sFUMT`Pn@}xp{ztLV;(v zfpz^yQd7iS6(_Q7vXj(h4V6-}dBO$XIi|VZ(uI~&B!hKM6RURf8LT_f#Kq|ge7hb> zdz7LUoEV$bDn?vpE@-sL81==de82u`uahBJnqb{Z&S*{iV(11|IJpFYubcAzW0Oje$r^ zE4P-wHC*u)g}$<2mWuY4vt3*PM-9^1b9#2Z`aW5aRg3Cq-wrI#A2d%!D7{?m(w zA*En*(%7cUcI+#a7BsOKt=|BvVaar1ris;gZ$Vy z{^k-TYRTYoO+nKtcfaFDKl_(Wn~7jQb|MV2^?mh*v)!b$meapuJ6i-9pKC-58I5;%)tjU?4)e`%i z-L7aDuIn3kK!L(3CE?$5L!`J2T-i%{L6zQ1m*~*yh^?du-Zp%XF>Xz8WzdtpRNKp0zJBRz9Hcs?>JqWPYUHQh z^mCZq`>yIhj<1T8%e2Q3=Buu}13k8~cZr%e0&r8$o<{$u2`~&RKs{A7q{D+(&udYB z37XASa2_qr@h0J*UMim?<_&x^4RWsCwv4!vcCmEApmOjkEU}VxY87TBzM@i1zDiZ3)>~RiBa4C$JslEY1(XA!f6|oW~FVb z(zb2euH=)pZQHg{Y1_7|Qj_mN_c`4&^G$#M?kj%Yv3JCdwf0`izb@*wzK@t1Gt{5_ zB#m|$f9))If2@f3ux;X2FZB%$_?*V~KD63NK zogZ2B(1elf#20F+A-(<#J~N4nie)+qPFT=-b^pn4ggLtG-j=-2S26I3N6CeZt3@mmTD>YX)kJru(*XndCw}UZh`mJ@$ z_~C@pcC+>VxYVUX$elG?BX!6}dGmEq&84FJeq@{f6JkdP7yPy?sE80h7AY2>6(yclL8;LbwHj19RHuw_ZVuzZM2f4i_cn^n>gS{sy z7c4HNc4EfJK}n?%-d3|bk6$<4Og{#b>lkjc9({95z7g9l$3|&Ar`JKr{@ktcPNzk|Sg1k)41@sQn_^2kes5tUuvkfjq)cP`JMVl07d`E8 zQSx>&$L+IX>5=VV>+}cm&3(fp9n&IN4FTi-RS*Vc^@(ny)opA$L2xU>wlmE-^8w;N zD2z9EBscZgVsQ}=Bbw&N4P6R*{e@En=)>(#mDr-SAbm$QL?^e&Xh;``zha7;mbtGe zL~f4@+eYRQ{h1$)lm@#z>i{?Q3Fo_gpSIB*x9L zufNN%bWqwdA9Nr#&>jz##hfHoyrw#1k)t6Zf5R)nsxe95bZ2F7kB@@O;ZV3sxXpuY zW0r`g3^yo8?*SUaNXJ5TG!I|UagOx9qyNw2?=PY)O4j)@@atYU{36@b{~wOO|II`- z$v+KJ#Y}8X91WaJ{?>f`UtChF6xSs|8IgFEyk?so6|0u0q4?Z^F>Vzo#k+FRkgI%R zSR3P5<78A{wfLaJy-1_nf4W*O=(j)BlF#|)5 zxu@3m6Z3wQXu7+%1P<`~J3q`iv6$-$>g&cZ^9f~e;tIrtKXNe?!*GWoL6AeDl43Ui z_(xP6e#Z8Sx9AbKP?*)QA|Q>=vUkUAzLY@>z}#*6Ex`hvUpSe^Kki>V=KjX8;_TK- zer>$h*T%E|zij+}7+?Ln=8%VKC+-;WF|JNzrEgBA&thG zX@?4(Zz4G=qOTu;N#?f#NJPLO@8ncxnvb2U>o&jcHc;k%YcvxV9fA%nv~mcQqAQ8~ z)uS26l!~_;h>V_yb3)aTaj|1Hmc^?B;iEKm(uiKJ5e5}{>x~hr=R{-}k0!bCLO3yX zlNkmYj!2msd6ae>Df3voFf|kC64cmK;gmUw85!Xb)^jtVq5+AGsrk%v%H0poG?le` z70a}C-!24-I;vD+5Fy9IbK zEK+QmfL>P&)>qJS0bDy!7fg!%_(lk3U$~EK(+WRD=M(vV=H*{c0NPlw2FI_h3I0+o z75P7JkI`4Unf=|F>?`4{U5rhH{$qvYA1h8jZ2vLVUZnix7omXkA*)2Y&JO#Z8{9L%P{AHO zDOZgA($9q5e{WUf15n;PwFi^|YJYd^v<_`Pn@$iH&e*RNH`%odZhdDsB!Gz_dOj<( z0mr+#T=Rjrtg>-xu}#Y!Idy2+ZPnSQAXE*^d1$4MZoAA#o@Mjda?$SN{XSlk^S$Cb zx)t1+2+e?Vrybz;?a`kuJ^1P&!A9E5}~t3o!NZA@xz?B_Pks0W>Pt8RGGE$|J@7GNBKtdX!3J2{=K zL?fbI#-RX?WgUrRG96YQw1NFSe)Q5QpZj1|OiUH!5{1|(+$@y?lTb%qHjWZ8wrC&i z?3h7hu6Ur&yxKzsq<0 zOHfPL{+FQsJLZ=azix@chy?h#n$fz|`fJr@eqKaq6qrg93VwwHOo*_y5Q7q+ONFyb zF{)XxnEa<|twI3Q$B$3>MEtzCOh{r>SDd*ZO|HlEczH1<2WV?wCX$k;#(-25oZix1 zV}KfvCX{ftr+oBkIyl3@BDz-n&4bPfaN5i??t)o8Km&B&4jtO{d!D8tDXzLUtZ zh|Op`FYu2t*L_z5zMn2&C9}(L6@6Ve z0$+Ky=MkzPu+$F@Uz#DTP$1i7%$~tF_~w+j3rwH@-}We_%x9;Q`zI>X(oZ@hzXf=P zCSe%J?w67O6h_T1U%l{>Bhv1D4#YW@SwtR3e5xJ zO-%gMl}JUL;w`?bnW-7y>t-8g563IKKI#Nx@l7Y72ot@tbk_vF2Gi74R#69c+#g5;fBlIt9kx3*ODkXs*Y z35%TamFD?!Z}Uz2ZvjkJnnrsn=FUnI#kXfNK$`@d(0%cr*_%7?3e>jCx#j)`j}ry2 zg84I~yzZJmqOJXkvs;BTKb1FiK73VI7T5z$erZ*C9-qSV2xRTf^J=~ytpT}DS^=uO z^fCF~dj1v-&D4KIL;rt^hKRqSVVH7d`XA8{7Opz`w`d^3pZ!NP=*fRYgI=k(msj{1 zqGLHQ6JEF~NUjE16!4a3qz9K?YryL$YJD~YGT%=|^=Wz70L)cn#{GYx2mWePVK5dj z7XNBfQTu9B`SJgB-~G!)_m58xQ48y@3BkWdMVE$^v$7ichpcIQnzXH-G$9e9zMo%0 zS`e^w97-=Bwt4mj4iU8K(!@~$AZuED-y2lkq*>LZNv&d)E9YHkX<3#`f|R#HwXh`C zw76zjfo|2I{ZaYVUwFQCyw&E!%<=Pia z&ut%rs^^dg1gX=Cp?5e|!+GO!b-jOtg8=9Fb2OL?myYbr*A{=L4KmF$G$X|0B@|RF z^Q9Q}kV8GdZg*YQI|NclmS_Ckt<58dv*)R zeMEiEDAH!oUjd_&V{+bz4tE5)cvxd8rj7Hom+~ry>IYCs+9UY}&t)$&$do(@rmTzA zCdfSZQ`zgH02LMtBv+GhgMfosDS1Abl7o!??BL?!ABIX%Pmn4D);RS`t@Y02Cyu6% z#@_hGi{w#1zZDVYQxVR6h9&UgrgDiYa%_TDE;Lz72jC)Jl-WJS+GM1av&|-MEdwVX zF_taVm6Y(Hc;G7j;vpd)O_DMI=noxraVaoOnR?rN7(q+BsQRl@yu8q6#>Ez~2s@?c zAdBHmWcc!3JWHNIBcr+160*Q9losj&zf>oGXl3a{1|%t|w4{MwzNjnNBLcc@$~f#^ z^d0M&5Cok0G%=^l_c$wQpa+hrEkj~5~cCA%(ei>Ta6 z0$Z|}>5#)kDI9f(CVCId&s*%xllyd5Daa{-mG;|}Bf?cf%+EFbgE3sU5XK*k?Lw{9 zox(KDq;HJakAJrNk1J^z7tW)Vj_>NGzyx;`#SMjRnNw|av5I)#cYTW)QqoQYJ!cL`KQAj?XJuWXW_W(f z1Od&$OV!>Yy7;Bu@B91dxT-=pKd_rkgm0GPz?p{JUxcp_A zi7?yFv7LbqvWonpv}CAqy)^Y#=;7$6_Pm5NhfP|oLU1d zg-z+dui(OqltRe2EkxE*f49ztqVNq_ zPM_D`P_47UQ=yNZj$V0mr0Ol%hpwKtBWc_IBSe!^;&&lehQfiv&M{2(!2QAOrX`1W zSAgD53J9BALCBaM<%v*DfZjehq;J7ai~Fp93fddOH1!LwZgIVPcdW|HK*xHlB9e&o zkN6D!9dt({S$j$jKP_B$l|F)7a&Q8no`B_>_5l8UdXVn2lK24j8#VCb8}@IH#Q{D0 zwEpe5xjvR8Xi~u@^$>IPSsGg#TH$u}fCx^OYS6yiWbp-Bo%Tcmpx;}5tDF}1_1SaK z^Kans=I0TlkOy2t_Hoz|7RY~`EgC^K8_ft*YK}H=*qqGRj+ifa-bi^h>yxfos5;SP zbg6fe-L>&fphz)YJ+du)oiN$SeJs96{x*fpwg%BNt9O!q{J70Qw?G5);l2rH$m1@V z2Fu|}I5{g8Tr$o-4Rzv|SGK!`^ZMus1{PacBl9G3M2I#M+C+z_e(Bp9eXXJnvuVU3 z(yiUeS)U!`*HJ2x*i|vn#okOz%xN7Iv8y76FwYgci60~rZXqf%dk|Q@4psE+dK2TQ z^OO(p(?4y1F6^Ct1oT3hEBhs}bTe5=KSr3dr!bsNIFK)kYg*;a^2N&w_*DIbGej!d zr#Nw37d7}bQ z5c%RgPAVBcAI806MQjj5uT!;%_sdRfN;|el_u04-;iZh&xW%sX$=Sa4d%3PB-?vwB ztao{CeA7j2Uly*l$*Gj9~=cSKqi zyUu9)7rM@6%A8d*m^Ld7!W!9-R-IDt3C^AHvCHG;b;o+f*rA2j9AQfOI7J(z*BHRf z#~1)=#_7W9$)$}KgWx%&6|cy>@N+?ZVp;ftJlxguZRQRQ*sBxFd0Vp?U?hAJ8NP|1 zL8LcGoQbA4XxTF_O9r;bQFQogkz#ov6(&1CmYSsncO$pPNCG0)0W=|s=0M1Af{bk2 zqU9PtCOF1BHkid2C!R@6am9jr2{W(8i8$O1!5X+r=@Vc>?QY8OeNtFLmd(K>+;DzR?a15Z zIAScdB<2ArVfvkI$u=K-gf)Dn$T(g=&c~LUam<{U%nRH(=8h#p^nGa}PG$ zS1G@(QONF+Wps|NKbHxAZ5hpO8Jqr$P4;qrD^6k@7#F+~5EeD&GJ3>{?gsJY#^$_h zjr;D)r0XuQWluE?4 z8~}UZz#!iPy+FSUEiojMYaQL~6qtCK5<9OArz@8V_D;4Ph#c~gI11&Jj4YTdik2(8 zB2ORwVJF)9LTQKT(7=PGzs1q1Q}EDqQj#vs|B)rlQg~XR(W_%0j*jfW-isH+xkeF``ETF7O!}g8nHhcwTgQT|ti%WL@ z$dgllXj5)~#~qaQwA!H5BOom$es_yoQq=4TqsVyJv^gT3K6%XYM7q~JYX2mD_mxm| z+Ye+SezCqD(nS0G7u4*pGL>-NmisS>LH;jjM(}@HrvCf;|j2=HTM%O)iQVQP8B2rTc0sLtWQk#JwYNy`bK&W~lw!s16xRe1Xi3S-` z$T$Y5RF4<`GDGqgga!uFC2IHupT)ucU&TWI1#S4}JK_t#wlFqu{wI-_rK z)*=A_CPre>WK|ymn<>+@0524kO#BwW8XC2%?M*KPhBAP#^Y*u?-R{xP__y=*Vq7PJBV zmdyZ*>00b?WtaBOtu787@pr-?PJc8y=+u!z!mZ=DreHNN?IB2>YUq>x5S!NM823>g zN1i(#7@kx=a5Qk?TJsDlo@Dopomwj@UPf*wB2IP}SI;|7rmXC&f_H1KfjlQq3EjA& z`l3=rfJOnXAXZW7nChxNuARrT`RY?s(O_jE@CwO(iViWq&kXz2un)n$F4Az5c}VN-Tk&dYIGf3-Ayhoe4ds`MdeZv{@ z!5lKFuDfLDd|rnearmehjopmYQKlYI$IR-jObuVs&_<}`-PTW1@wjdnkJvDJe43C2lCyJhF0^8n)JE*J=@8RhGr<@9by+Wy3CY`4n;}+Dn zG4PXQ&urt+evh;mM#X8svWU#ZW$!8dQ)>d3D|}M2UF$-h=a!gvyW2!uNrZCIKu82l z&YC}{U9(8}ETTTmv?7_gxMqf7Hd9FMSJ*jVZ0O^dupkKA(Th)>$of_pC)r>~I=%S4 zLg@ax$q6a9u@yZ^t~lspP<44wfuM40C34Al0CV_-YOclV+~#`ZjjJI~L1MB>a&d?G zRO8nEt|`_p398z7X$RRME!yhlxu&Y^QMTqM@skyp#OgqRT7u`V>m=;XVH!d~ka~?e z9<-lqnCz$u>^ktacpO=_u30bquQUflJHoT_v) z$J?D0x)4X?6I6Q|g=lA=-S0bud`#p%fre=b+!z_H%i0nclE5>}0gZHWbsfi_L--!n zKo^Q$HSbbY$2ABI^6uKjMwayub|4mN{Cfn-q-*o!m$A?0O4`_;jymcDc<1kurEYfm z(?XqhkZ*{Y*cJ;je46BV$7P@Yq6_uc!5s>oBlJJxKK>g_O!AMF{}1kCOC9-|G<9uI zeC|atu&>3&OA$fCHKPmjwdNt1EdJ%I2Wpse9eo^SuL{xW$lJ`c`; zwYplLy_^UF4i(FWT5d(EAZ1`Z4>d}qWKD6eeC<%|7IO2A8`ja|Qrz!Z77#skQ7L!d zuEyzDOD^6ihItgWpE$T~t*=uT>Op9lvdfK6GHRnI)?d`eP{c2I$R6yC z(4niy>tu`PsM>+7J6oR=D&zGpjX~cXMMcW$Npuaxnto&Jj2My3FawtSh|wgQlRpID zlJRh5^DZJG*t#=Ps17#U=&pL@ORgX-6MC>^gL|Y=>?SY+8=Sj1^V}qg@E+Du4K%;L z0}MM~Dg@Mduf~r@3bR51P5Haf*_P^kNh;0*P#S}Ih1c;3*#)XFo&{m!VaW-t3VYgwVfhYcx z0r_{FALfLdnqYS+g+6g3EGVgY>t2PUpm&E#wSnVMVaV}%{k0nPmM^7Bme5WIw9$bI zy-l_1*|EgvowD7c$Cw(#*ATy5vAqOmQYc$2~x=_i$F9%=U-qcB*$uD zgpxSEMxG#eJj})=3BwB-OW&d?L4GfU9fxK*M6P$v6nMui7GHD5Y(`g%p7{2C9PA3< z3J>f2ZFIr_^*;9X0T`e7^}o0_DPZs|(SB8q$X}J?|HU2Xe^ZV89nXx4`y~s)h%{2t z+8U5wN+L>+jVR1H<9<`f$S918@-~`(-lwENCdFRFx=9zOcE1DqB0sDF-49$4B4NhW z^V`kz&)@xlO-6HFo!>Sj2F2}3ohP*<3s12E71f3{TPIQK8-O_N zw2@S<(kDgTY0(XmlI<~ZxNVPU0yhcgWf2$?%PuH87uGm-3uh?<137tb6Lx^P7TUzt z9{FRv3XECEW)Si12-euuddiz0fvTKW$X{xWtS1wsrA913>*+J=crx8zNH+a)=Q*MD z^h({u?O=uq#)43k`0&^=!{v4MKTY7u8+5Ndp+%$nKKh@`A}W~mrLwJtBl1-Yt{M-xN>Gp{<~FNSk`S>pt7t+gGJY!pG$u<{@zEN{ zYERXVty=ROZuSgf=$*rs@|JYJ(!cEKDZZPs3xH4_JzT72aX*i+Z+AJFJ=HA#>;$n# z-NqI-=YcYQg?G+{4>g!# zv;3q6mcP1@?5ApbA?~j{kA-h$fTWUSnMoVcq6z-?lmmhU5x0k z0YN{!FMhb-J^l0L*Pzi|$$s3ae~Cvzsq|Z^X-92m^SNZr z3hLeHU1gUlrQ4FtwBx1edYyO2uB%}vz4*PR$?~6BDz0QL`eeL{#d5Z{CeiiHw$Dzo zjPac4TT?$824+l9;C+rv1-FJ>Vw-K(aP*EtL|F&(`Rb13?I+{dpY)S=7FQF$ljg>E zb|{M%;}7?vkW!~yf7t%XzFdNK3-9c;H@kldQ~{^UCKJpVjEgyoVa~lkoVYIrr}Nof zJ`qn5t)oM#qr_~Yi!aMwOfo&78M@ud-mt@eJXG(=FU!I!Z3dA7O+1O}8#XPtTvQfI z7&G4P?#UCB(H<;~u8~%*HQ2-EV_@{J08#o}uDWQx*K+2{WUR%_tiGC=sNr zeo<-jAh)RT%x@)(JhbWM$fG_s z8+XM&XoNX&Ij!+@ku+M>?s3gL*}6}N_@NX2y<`*Iu&UT7VavKl_H_L!ft<%C=p;Z%kq)5M=CCu6|N-|n3sX$)Bn2j{#6);Kmbe7HM_$wJrHwUc~!^|U(bnUp~ zQ=gwdyyp28{$!`k8cHCzRzx^WW!}?XKWEu-{(1fR@rNDg^@cErLYmW9DAYi-nvW7v z3ZWS{6KQXBY>^dw8GRBk6UzD9M+l*YsuimrVZ(Be%Ucqm1>L(H+2A+wu#Ln$7N<8` z5bcXLRL)42s5fxU*scq>p7ITVr%fe>USdoynLy8CP|ZQCZ@KWGhWbSms^jJtQg^T& z^-FZXHPuVDfRm!r!&oJ&TmL9WJ83RLda*4jbGprWb8q{8Lzy&P)$v#>vw89**em?J zJp$~5NJzE$a-*;)GdXH?Xm?&EYg%jkzDNJK#F(ogSH==^81nPE`P68kO9ed}8It&& z-(3it62X*=+{qHB4e>x$a-Oy1M5IMBQP2A?&w;?WWZdedOe15Ig7*0lAs@D%E5<9J zM;rS7>XFCK(HQ1nhmWd+GSXJXj0qFw(Q&M(1FKH$mn+}@G@7OwFPa^&xqxR<21cJz z?k<~|IZvc6$%svmC}!utZOW3sO5H8$Bq5-z$nP=(oAlpD^k%DY$?NYs(*OE(z}sZi z=JjXd@o@z48L!xH$r2JIFQ5)=oxxH%Jw2g;;@N)4Mhd{H?e4DVc88%9SzJODNTKS` zNA!!OA=-->te$N7nkHhq+tPuWHmqvNP6dd0bgcpw@A+a1Qg8N(RZ}53Wza#OxbhIr z>|UAu;el~e_S7^z;9@>Sk4Y&Q6${&pMG7CvIz|FB;CoX3`Q&$wqzjm(vFq zrF35XbtZ2UPh)Ub;fen8Ggb&XtyK%t!lOGBi7271kCXBMqarACaSbkbqJkg?2XtV1 z@l{0$3VACjA{%ru-Mc3>7(FTTkVa+6mdh-!=c}UK2CoS2*Ul`T4Xj^Bm5EayL=kR` zf?kEv=oq*4Fz~2UC@U3vBoHc@$pgTdinp1#-7y_hTZ4#TPoMOx>bXuu>CB_FLKB$m z+8_JLNlhft1m!QtzLk44q9^&ECGMp!(7xq+W-o2wEjLe^MMkif2Sb_H_+-h}J83Om9uG|^aO*Lw=f_%%Wdt*|hDRm{W5>>}(w8$!>W~Pn5%LYaM z76~;*>}qRDX2r=vRAx{dWhKg0VnTe7I$nHCo)BN#~X=BU35}eUJH}S4K$L(vn%^l9;hA=l4} zN^rTtaZ=q*)fQ=)bnC{In(yT~OPLF3IYu-l3K}>#WzFhq>jgzkmc3s#uS5gM=#1JX zT70nYt^<&>OiS@>3yN(MAk!ZVmD7sCz0M^|=4CD=DE^P45^`L-Y}j1>b8F#2W7cFsi@G>)mZuK_WCIHnHUc8?-4RKt zM*AyMp9qYjIWR=9jF!Jgz==b-C^mRet}i_O)}~0o0GtbWF!pdyOAgAOfw#@=SIs*| zy(niGvkWoCyKb}Yd9T0=&wCN(nu7N}lJNPcyif{v^NA}1Jw!;;Uu}XS1t&ug4nUWC zgw5eXCuq|JVh=<_e;nj-hhg`?d4#f&7ZRug-rbWG*>XXI{DMOt($ilYu0M&f-ID1+TWHr5!h@pTu<%CFzj1_+kOfZjkCm{_v?k_Cm z7gXnhypEqQVQMjvfQaM~v$J+g@LqtsL3-C2pd)BRRXjue0MbfcI|ivHC+=YnS?;$V z5ljs|^@R708nUGgY=gM@r(gS8@NcnC7#g&l#!+iDh_dP(N(XeWAPtbBJfOodki=9( zQWApHZnv#HTzlY7Axe(L!}IHtyT@zHs|(%1sg6=uq+Wh0!4XjXxGk~@A)sX)AcreA z`LPi!!6up{WDJ2Q*d0_FS$nmVjr;_9R{VFyX^cY2Z>7d%w}O}GokRpfd^cG9Gg{k2 z)v$=QUKAg(r$c`0PTlvqSi@=x^tOWNEvX+ZQvIFil!ctj%#AL@_cv(MbQn|d;Ajcw z=V`{MAMd0bQp-z2@0m|mWGA-SE-D@xN{~Y3#P{fbwv6}=GLRx0%tC|9H}F#l+jvL7 z9Tr`*;hE^(S=u?=W;QrpRmiV-C)>Q-K$je@RyS|-{^FOGmpuwz{6|1U@I??}df za0C;wU(+^~ySpIy|Ktd4d8DMFECu)e;s{u(X%VnYe_heU>D})@z9NiW`0lSbfw?VN;qCMV z^3SOft}6+Bw?VVlI!tLk+G2Dw9iH=)qh&@HU&47Op@#L>o{j;DnMyo564cVf{^Os2 zL--+-yA~CxV$`mb*S_3{gb421eLBjy<2n`}rdO%)8t8awbtsc|;%rB6$AwXX&McQvJhxp|2xCx-Z-vU>`{PxU*R5pB}-hjnKwgNqA4ag18) zd&TrnE6D2?M}UeXZa?_N5r8R*J9Q6gIQE91roqdRKZKLx`?m{Z02`--ZLs2dUr;W%!~y{tDnJA?6xii z`C`#lpMkKSpNY*BHtKwOv>y*Tn`R1I zNi(V^itK1T;jh%6`&-Usc3E0!jtLmd_tErEDq&LO*fFfMw_2@|q!`9^_+M74W!RrbAK#0n5j{#v7_OiyjpZ&AlfsR(P^RU%HB_rf z(c188!A5?g3SuYIUHYv^$g{lckYsRNnd)|#OG#OTf|E7=JLc5nC81Q8wu*RUN!fSUhO$TmLQE+o=qKCa zvEEa=kG+-#;*~dA9hh}Irs8(p7JGF#EFqIU9sEjKg!%OWR^95w&5ymX^ua_e7NDA= zY<##yb{g1cDL|WO?XiRSo)xoZv=V0R@>JjW1AIjHP~!h&WfG**8gIaqeqB!iM5WJ65_yJ;uoxJv^1s!?+L97oa)faV2J)wn=!m>GVET?}&#>>g;@z=PJs?rw&LDaLl*v!cp+JkXr@(!#E z(1G?2`R%LY`%|1(96Y4V{hJ5w2-GTu0^E9;{2K$SQ)Ie$+y#n3h`2gAQ3!O6dVOL- z5rjCgBbtg3R)M>}=9wOj#Gr#82eGmPo(i$@!V`48EFk&uzmRiz@}H5HUm553bx@-H zTjnXcSpP%0KUnT>X0Sd^>6KyF1zEwEG>Yx&TF|--v6!54I2FGbalNcv59={T^%`y< zUkV0wVCQi;7?=^aMi}(A337mJ?aAzk8PGULA98e*FnDGG&|Q^`-a2Jb#F=JMkDfy{ zo>eJ;>q-}0kIRd6hIElAmhoi8cVs4`X|{YVL9+sBRN|3O@tn-rAvR3mr@K_SW6It9 z&G?FTV}eArOK(eebf)`D?vd973$6}w=VObHS}6UUGey;?McrX~=mDK^Lk)*r=#;9y zj^zn9^m_Eujq{oRv+KFjY5P}14&MhFa#kr8uw`Dz+k&*-{OLI` zRY3?y>4m|{#9~O>1JpnPT+Hdhd4Z4iB&0cCzSyDLu|~`{k>mI z_R(?6%1auMPewOtuGuLk0dLJbtoBcZl4}Ta8lRZmSFU$Lfh28;>)li+`TlAec2Y3eujNsl6w8oP1DV^x)p)J81?d)%6tck` zWt#L<0-2FEI-Jc_liNtqg7oBL0mb<^K+cu2r-)2O+Srl^GZ`)}`q{OryCjT)kWra7 z)4Ev>G8Z;0lc5E3I_oqebDOYgL0z6iG+(8!JEhcde5$nOS`267W9v-bAB`-8?lp64 zkckGv?Tuw6%iZ5ugJd zBZ`UAN9_llh4-PYYZf_P`*G7*(~o*}XB?O24&{$#`rr7RTrkE>y&U|cUP2H=J#Cw?pacVW$B9hXou8H>gD{|Th?=^JSO(A8a?uBOM71t6!gT~m;~dt; zPK>IH2?pKiV;j?Ld@VaNEo-@GoJ|QX7do|G{Z#Ir-#DR+m;DULQ)~%S!nj|$c z3E(h$Ao59jamTlr;asqsS!Ka!%Xc1TIRVkMo3nn`LaK zcHjdynl)xhf~R8*l&I|a!9Gh1@t*M!`243cplyM)7Jc63&tR_HDf7V{@Et|Jq)zCX zHqWeWah-m$P3^cqsKv^7Iib`^Z`^|I46k#|kIhE;Wo>|}=<#{_`V3DxMnHK$nn{^< ze%7MvVKUhsV-%oF%gns}XrAJZpTt4v-U?WVdKm;898&TK!eurXjx$iz!2&&{-D6d4 zUIZ?MsnVb|(tvgV9ZrqOTE8`X*AifbS#8o9z3U0U!E9!*HffDBz!^Z;%E^FlUj(^W zpmS}D(78IAv!&Y0hPsVvPyObMP8FN3J<8% zzm9R>I~{5X>Ro(ScUPt)XFD#J>*Bu=wC}s!i-t_jfT3b2mNS8g?D9^;IpEzL} z&cUDqR6L}wNt_DMT8a;oipWJIk~yCJ9p9k2(6{G1b95K}twA74%CVI*cs!1L%;R@< zZhi3UXqOmP4h`mYgIU8M{?FpfDC8?rIVFxcsjV+>P`-*WA&ei-DX>RI;&h0o52WER z@1v*jF2%-=q5>5J+BtsaIw1-v81^2QO}A^>j2D>^ZH);E_qjC+Rv>AJ{QSQDUgnlg z2b_1x?3+TnM`vUewB{}Fc6FMON}J|)_?Ncno&0w+9>lNDf{s8++?nIM3<3qWxKb)C zx=U6&)-0MY9w0JBN;A5Fic!2#Lo6Wf@RrMlgJhAbFx@u#7kxT+qSzAaefGT7+3bF1 z)U7T4T_I$-HP}9^jo{u|eO>Suye#mSB?a12+_gmPVMS@sM=)<|$RKnKZKXnqWGgoF z42X1X9u5a6?I&<&!Wp6y!nr%CAj6kKJis{PTJ3rLQ2dhBJn+aBT#3|cz+9Cn0E5f& z^qgE6;dx|qv8OqOjS#URdja~W(Rp#puWl`y80{U$!#bfrYmu$+{=aGNS;P*13m0D=%fPK4E2XMXFeA_op^*#bz0 zbx1}-#Nms9ldiva{)6ZW_fUw8!PY;Z7zcXe%8|Tw^7b z>?@aJ?7R&HxUGDLf�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 TY(h;@!?}i$7z!3V8^-w`q)kqw literal 0 HcmV?d00001 diff --git a/lib/junit/junit4.jar b/lib/junit/junit4.jar deleted file mode 100644 index 954851e67d7424440592e8176c4aa034cc46aa85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 253160 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 z z<&GZnJD5i#rcYN>CbOyu=E!{ub85kK9YB(<2X-@MGE13YR%R}Y7y&1{hl!5%eHiYB z=%-V>moqNO+jnOD63m*twPB2RcNTHXv)MrNTrs%eXAc0@;0aLPiTqja{?M`3lejfu?5{LPsb3lpm(Z(534|4n9Z8=(kqRBc%MLi4kS&q7`LZ-;u@x-moDmV1ITtb5ge z)XodulV}Fked10pv;H%3Ui5k_=PLaeq;G^G^dDC9LQChUp^b|aKZx|-p726_Q#mLX X1+~N^gww`motp(s)wBZqKTZ1|e=N@s From be78bfbd8cb10c2769641101bf44a59ea53ed8a5 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Sun, 5 Aug 2018 16:36:09 -0700 Subject: [PATCH 048/189] Add `Unsafe` based storage backend Summary: @public Adds another version of property storage for `YogaNode`, using `sun.misc.Unsafe`. Adopts the stub concept from Litho for `Unsafe`, as it is hidden by the Android SDK. Reviewed By: pasqualeanatriello Differential Revision: D9140103 fbshipit-source-id: a4b376eca341b724a00f873467ae8bf8eaac69f4 --- java/BUCK | 10 + java/build.gradle | 1 + java/com/facebook/yoga/YogaNode.java | 7 + .../yoga/YogaNodePropertiesByteBuffer.java | 9 +- .../yoga/YogaNodePropertiesUnsafe.java | 580 ++++++++++++++++++ java/jni/YGJNI.cpp | 30 +- java/stubs/build.gradle | 10 + java/stubs/src/sun/misc/Unsafe.java | 27 + .../facebook/yoga/TestParametrization.java | 16 + settings.gradle | 3 +- 10 files changed, 682 insertions(+), 11 deletions(-) create mode 100644 java/com/facebook/yoga/YogaNodePropertiesUnsafe.java create mode 100644 java/stubs/build.gradle create mode 100644 java/stubs/src/sun/misc/Unsafe.java diff --git a/java/BUCK b/java/BUCK index 4ddabcef..dbd2d335 100644 --- a/java/BUCK +++ b/java/BUCK @@ -29,9 +29,19 @@ yoga_cxx_library( ], ) +yoga_java_library( + name = "stubs", + srcs = glob(["stubs/**/*.java"]), + source = "1.7", + target = "1.7", +) + yoga_java_library( name = "java", srcs = glob(["com/facebook/yoga/*.java"]), + provided_deps = [ + ":stubs", + ], required_for_source_only_abi = True, source = "1.7", target = "1.7", diff --git a/java/build.gradle b/java/build.gradle index 21034e42..2ed33d0c 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -52,6 +52,7 @@ android { dependencies { compileOnly 'com.google.code.findbugs:jsr305:3.0.1' compileOnly project(':yoga:proguard-annotations') + compileOnly project(':yoga:stubs') implementation 'com.facebook.soloader:soloader:0.5.1' testImplementation 'junit:junit:4.12' } diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 73305370..2924f0c3 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -23,6 +23,7 @@ public class YogaNode implements Cloneable { public static final int BYTE_BUFFER = 1; public static final int HYBRID = 2; + public static final int UNSAFE = 3; /** Get native instance count. Useful for testing only. */ static native int jni_YGNodeGetInstanceCount(); @@ -50,6 +51,9 @@ public class YogaNode implements Cloneable { case HYBRID: mDelegate = new YogaNodePropertiesHybrid(this); break; + case UNSAFE: + mDelegate = new YogaNodePropertiesUnsafe(this); + break; default: mDelegate = new YogaNodePropertiesJNI(this); } @@ -63,6 +67,9 @@ public class YogaNode implements Cloneable { case HYBRID: mDelegate = new YogaNodePropertiesHybrid(this, config); break; + case UNSAFE: + mDelegate = new YogaNodePropertiesUnsafe(this, config); + break; default: mDelegate = new YogaNodePropertiesJNI(this, config); } diff --git a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java index daca67db..f189a5b4 100644 --- a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java +++ b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java @@ -31,16 +31,16 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab private static native ByteBuffer jni_getLayoutBuffer(long nativePointer); - private static native long jni_YGNodeNewByteBuffer(YogaNode node); + private static native long jni_YGNodeNewNoProps(YogaNode node); public YogaNodePropertiesByteBuffer(YogaNode node) { - this(jni_YGNodeNewByteBuffer(node)); + this(jni_YGNodeNewNoProps(node)); } - private static native long jni_YGNodeNewByteBufferWithConfig(YogaNode node, long configPointer); + private static native long jni_YGNodeNewNoPropsWithConfig(YogaNode node, long configPointer); public YogaNodePropertiesByteBuffer(YogaNode node, YogaConfig config) { - this(jni_YGNodeNewByteBufferWithConfig(node, config.mNativePointer)); + this(jni_YGNodeNewNoPropsWithConfig(node, config.mNativePointer)); } public YogaNodePropertiesByteBuffer(long nativePointer) { @@ -84,6 +84,7 @@ public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneab @Override public void reset() { mHasBorderSet = false; + mHasNewLayout = true; jni_YGNodeReset(getNativePointer()); } diff --git a/java/com/facebook/yoga/YogaNodePropertiesUnsafe.java b/java/com/facebook/yoga/YogaNodePropertiesUnsafe.java new file mode 100644 index 00000000..f8af890b --- /dev/null +++ b/java/com/facebook/yoga/YogaNodePropertiesUnsafe.java @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; +import java.lang.reflect.Field; +import sun.misc.Unsafe; + +@DoNotStrip +public class YogaNodePropertiesUnsafe implements YogaNodeProperties { + + private static final int TRUE_BITS = 0x01000001; + private static final int FLOAT_SIZE = 4; + private static final int AUTO = YogaUnit.AUTO.intValue(); + private static final int POINT = YogaUnit.POINT.intValue(); + private static final int PERCENT = YogaUnit.PERCENT.intValue(); + private static final int UNDEFINED = YogaUnit.UNDEFINED.intValue(); + private static final int RTL = YogaDirection.RTL.intValue(); + private static final Unsafe UNSAFE; + + private final long mNativePointer; + private final long mStyleNativePointer; + private final long mLayoutNativePointer; + private boolean mHasBorderSet = false; + private boolean mHasNewLayout = true; + private boolean mIsFreed = false; + + static { + SoLoader.loadLibrary("yoga"); + Field instanceField = null; + try { + instanceField = Unsafe.class.getDeclaredField("theUnsafe"); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + instanceField.setAccessible(true); + try { + UNSAFE = (Unsafe) instanceField.get(null); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static native long jni_YGNodeNewNoProps(YogaNode node); + private static native long jni_YGNodeNewNoPropsWithConfig(YogaNode node, long configPointer); + private static native long jni_YGNodeStylePointer(long nativePointer); + private static native long jni_YGNodeLayoutPointer(long nativePointer); + + public YogaNodePropertiesUnsafe(YogaNode node) { + this(jni_YGNodeNewNoProps(node)); + } + + public YogaNodePropertiesUnsafe(YogaNode node, YogaConfig config) { + this(jni_YGNodeNewNoPropsWithConfig(node, config.mNativePointer)); + } + + public YogaNodePropertiesUnsafe(long nativePointer) { + mNativePointer = nativePointer; + mStyleNativePointer = jni_YGNodeStylePointer(nativePointer); + mLayoutNativePointer = jni_YGNodeLayoutPointer(nativePointer); + } + + private static native long jni_YGNodeCloneNoProps(long nativePointer, YogaNode newNode); + + @Override + public YogaNodeProperties clone(YogaNode node) { + long clonedNativePointer = jni_YGNodeCloneNoProps(getNativePointer(), node); + YogaNodePropertiesUnsafe clone = + new YogaNodePropertiesUnsafe(clonedNativePointer); + clone.mHasBorderSet = mHasBorderSet; + clone.mHasNewLayout = mHasNewLayout; + return clone; + } + + @Override + public long getNativePointer() { + return mNativePointer; + } + + @Override + public void onAfterCalculateLayout(boolean hasNewLayout) { + mHasNewLayout = hasNewLayout; + } + + private static native void jni_YGNodeReset(long nativePointer); + + @Override + public void reset() { + mHasNewLayout = true; + jni_YGNodeReset(getNativePointer()); + } + + @Override + public boolean hasNewLayout() { + return mHasNewLayout; + } + + private static native boolean jni_YGNodeIsDirty(long nativePointer); + + @Override + public boolean isDirty() { + return jni_YGNodeIsDirty(mNativePointer); + } + + @Override + public void markLayoutSeen() { + mHasNewLayout = false; + } + + @Override + public YogaDirection getStyleDirection() { + return YogaDirection.fromInt(getStyleInt(YogaNodeMemoryLayout.styleDirection)); + } + + @Override + public void setDirection(YogaDirection direction) { + putStyleInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); + } + + @Override + public YogaFlexDirection getFlexDirection() { + return YogaFlexDirection.fromInt(getStyleInt(YogaNodeMemoryLayout.styleFlexDirection)); + } + + @Override + public void setFlexDirection(YogaFlexDirection flexDirection) { + putStyleInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); + } + + @Override + public YogaJustify getJustifyContent() { + return YogaJustify.fromInt(getStyleInt(YogaNodeMemoryLayout.styleJustifyContent)); + } + + @Override + public void setJustifyContent(YogaJustify justifyContent) { + putStyleInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); + } + + @Override + public YogaAlign getAlignItems() { + return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignItems)); + } + + @Override + public void setAlignItems(YogaAlign alignItems) { + putStyleInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); + } + + @Override + public YogaAlign getAlignSelf() { + return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignSelf)); + } + + @Override + public void setAlignSelf(YogaAlign alignSelf) { + putStyleInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); + } + + @Override + public YogaAlign getAlignContent() { + return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignContent)); + } + + @Override + public void setAlignContent(YogaAlign alignContent) { + putStyleInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); + } + + @Override + public YogaPositionType getPositionType() { + return YogaPositionType.fromInt(getStyleInt(YogaNodeMemoryLayout.stylePositionType)); + } + + @Override + public void setPositionType(YogaPositionType positionType) { + putStyleInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); + } + + @Override + public void setWrap(YogaWrap flexWrap) { + putStyleInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); + } + + @Override + public YogaOverflow getOverflow() { + return YogaOverflow.fromInt(getStyleInt(YogaNodeMemoryLayout.styleOverflow)); + } + + @Override + public void setOverflow(YogaOverflow overflow) { + putStyleInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); + } + + @Override + public YogaDisplay getDisplay() { + return YogaDisplay.fromInt(getStyleInt(YogaNodeMemoryLayout.styleDisplay)); + } + + @Override + public void setDisplay(YogaDisplay display) { + putStyleInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); + } + + @Override + public void setFlex(float flex) { + putStyleOptional(YogaNodeMemoryLayout.styleFlex, flex); + } + + @Override + public float getFlexGrow() { + return getStyleFloat(YogaNodeMemoryLayout.styleFlexGrow); + } + + @Override + public void setFlexGrow(float flexGrow) { + putStyleOptional(YogaNodeMemoryLayout.styleFlexGrow, flexGrow); + } + + @Override + public float getFlexShrink() { + return getStyleFloat(YogaNodeMemoryLayout.styleFlexShrink); + } + + @Override + public void setFlexShrink(float flexShrink) { + putStyleOptional(YogaNodeMemoryLayout.styleFlexShrink, flexShrink); + } + + @Override + public YogaValue getFlexBasis() { + return getStyleValue(YogaNodeMemoryLayout.styleFlexBasis); + } + + @Override + public void setFlexBasis(float flexBasis) { + putStylePoints(YogaNodeMemoryLayout.styleFlexBasis, flexBasis); + } + + @Override + public void setFlexBasisPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleFlexBasis, percent); + } + + @Override + public void setFlexBasisAuto() { + putStyleAuto(YogaNodeMemoryLayout.styleFlexBasis); + } + + @Override + public YogaValue getMargin(YogaEdge edge) { + return getStyleValue(YogaNodeMemoryLayout.styleMarginOffset(edge)); + } + + @Override + public void setMargin(YogaEdge edge, float margin) { + putStylePoints(YogaNodeMemoryLayout.styleMarginOffset(edge), margin); + } + + @Override + public void setMarginPercent(YogaEdge edge, float percent) { + putStylePercent(YogaNodeMemoryLayout.styleMarginOffset(edge), percent); + } + + @Override + public void setMarginAuto(YogaEdge edge) { + putStyleAuto(YogaNodeMemoryLayout.styleMarginOffset(edge)); + } + + @Override + public YogaValue getPadding(YogaEdge edge) { + return getStyleValue(YogaNodeMemoryLayout.stylePaddingOffset(edge)); + } + + @Override + public void setPadding(YogaEdge edge, float padding) { + putStylePoints(YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); + } + + @Override + public void setPaddingPercent(YogaEdge edge, float percent) { + putStylePercent(YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); + } + + @Override + public float getBorder(YogaEdge edge) { + return mHasBorderSet + ? getStyleFloat(YogaNodeMemoryLayout.styleBorderOffset(edge)) + : YogaConstants.UNDEFINED; + } + + @Override + public void setBorder(YogaEdge edge, float border) { + mHasBorderSet = true; + putStylePoints(YogaNodeMemoryLayout.styleBorderOffset(edge), border); + } + + @Override + public YogaValue getPosition(YogaEdge edge) { + return getStyleValue(YogaNodeMemoryLayout.stylePositionOffset(edge)); + } + + @Override + public void setPosition(YogaEdge edge, float position) { + putStylePoints(YogaNodeMemoryLayout.stylePositionOffset(edge), position); + } + + @Override + public void setPositionPercent(YogaEdge edge, float percent) { + putStylePercent(YogaNodeMemoryLayout.stylePositionOffset(edge), percent); + } + + @Override + public YogaValue getWidth() { + return getStyleValue(YogaNodeMemoryLayout.styleWidth); + } + + @Override + public void setWidth(float width) { + putStylePoints(YogaNodeMemoryLayout.styleWidth, width); + } + + @Override + public void setWidthPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleWidth, percent); + } + + @Override + public void setWidthAuto() { + putStyleAuto(YogaNodeMemoryLayout.styleWidth); + } + + @Override + public YogaValue getHeight() { + return getStyleValue(YogaNodeMemoryLayout.styleHeight); + } + + @Override + public void setHeight(float height) { + putStylePoints(YogaNodeMemoryLayout.styleHeight, height); + } + + @Override + public void setHeightPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleHeight, percent); + } + + @Override + public void setHeightAuto() { + putStyleAuto(YogaNodeMemoryLayout.styleHeight); + } + + @Override + public YogaValue getMinWidth() { + return getStyleValue(YogaNodeMemoryLayout.styleMinWidth); + } + + @Override + public void setMinWidth(float minWidth) { + putStylePoints(YogaNodeMemoryLayout.styleMinWidth, minWidth); + } + + @Override + public void setMinWidthPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleMinWidth, percent); + } + + @Override + public YogaValue getMinHeight() { + return getStyleValue(YogaNodeMemoryLayout.styleMinHeight); + } + + @Override + public void setMinHeight(float minHeight) { + putStylePoints(YogaNodeMemoryLayout.styleMinHeight, minHeight); + } + + @Override + public void setMinHeightPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleMinHeight, percent); + } + + @Override + public YogaValue getMaxWidth() { + return getStyleValue(YogaNodeMemoryLayout.styleMaxWidth); + } + + @Override + public void setMaxWidth(float maxWidth) { + putStylePoints(YogaNodeMemoryLayout.styleMaxWidth, maxWidth); + } + + @Override + public void setMaxWidthPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleMaxWidth, percent); + } + + @Override + public YogaValue getMaxHeight() { + return getStyleValue(YogaNodeMemoryLayout.styleMaxHeight); + } + + @Override + public void setMaxHeight(float maxHeight) { + putStylePoints(YogaNodeMemoryLayout.styleMaxHeight, maxHeight); + } + + @Override + public void setMaxHeightPercent(float percent) { + putStylePercent(YogaNodeMemoryLayout.styleMaxHeight, percent); + } + + @Override + public float getAspectRatio() { + return getStyleOptional(YogaNodeMemoryLayout.styleAspectRatio); + } + + @Override + public void setAspectRatio(float aspectRatio) { + putStyleOptional(YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); + } + + @Override + public float getLayoutX() { + return getLayoutFloat(YogaNodeMemoryLayout.layoutX); + } + + @Override + public float getLayoutY() { + return getLayoutFloat(YogaNodeMemoryLayout.layoutY); + } + + @Override + public float getLayoutWidth() { + return getLayoutFloat(YogaNodeMemoryLayout.layoutWidth); + } + + @Override + public float getLayoutHeight() { + return getLayoutFloat(YogaNodeMemoryLayout.layoutHeight); + } + + @Override + public boolean getDoesLegacyStretchFlagAffectsLayout() { + return getBool(mLayoutNativePointer + YogaNodeMemoryLayout.layoutDoesLegacyStretchFlagAffectsLayout); + } + + @Override + public float getLayoutMargin(YogaEdge edge) { + return getLayoutFloat(YogaNodeMemoryLayout.layoutMarginOffset(layoutEdge(edge))); + } + + @Override + public float getLayoutPadding(YogaEdge edge) { + return getLayoutFloat(YogaNodeMemoryLayout.layoutPaddingOffset(layoutEdge(edge))); + } + + @Override + public float getLayoutBorder(YogaEdge edge) { + return getLayoutFloat(YogaNodeMemoryLayout.layoutBorderOffset(layoutEdge(edge))); + } + + @Override + public YogaDirection getLayoutDirection() { + return YogaDirection.fromInt(getLayoutDirectionInt()); + } + + private static native void jni_YGNodeFree(long nativePointer); + + @Override + public void freeNatives() { + if (!mIsFreed) { + mIsFreed = true; + jni_YGNodeFree(mNativePointer); + } + } + + private int getLayoutDirectionInt() { + return UNSAFE.getInt(null, mLayoutNativePointer + YogaNodeMemoryLayout.layoutDirection); + } + + private YogaEdge layoutEdge(YogaEdge edge) { + int layoutDirection = getLayoutDirectionInt(); + switch (edge) { + case LEFT: + return layoutDirection == RTL ? YogaEdge.END : YogaEdge.START; + case RIGHT: + return layoutDirection == RTL ? YogaEdge.START : YogaEdge.END; + case TOP: + case BOTTOM: + case START: + case END: + return edge; + default: + throw new IllegalArgumentException("Cannot get layout properties of multi-edge shorthands"); + } + } + + private int getStyleInt(int offset) { + return UNSAFE.getInt(null, mStyleNativePointer + offset); + } + + private void putStyleInt(int offset, int value) { + UNSAFE.putInt(null, mStyleNativePointer + offset, value); + } + + private float getStyleFloat(int offset) { + return getFloat(mStyleNativePointer + offset); + } + + private void putStyleFloat(int offset, float value) { + putFloat(mStyleNativePointer + offset, value); + } + + private void putStylePoints(int offset, float value) { + putStyleValue(offset, value, POINT); + } + + private void putStylePercent(int offset, float value) { + putStyleValue(offset, value, PERCENT); + } + + private void putStyleAuto(int offset) { + putStyleValue(offset, 0, AUTO); + } + + private void putStyleValue(int offset, float value, int unit) { + if (YogaConstants.isUndefined(value)) { + value = YogaConstants.UNDEFINED; + unit = UNDEFINED; + } + putStyleFloat(offset, value); + putStyleInt(offset + FLOAT_SIZE, unit); + } + + private YogaValue getStyleValue(int offset) { + float value = getStyleFloat(offset); + int unit = getStyleInt(offset + FLOAT_SIZE); + return new YogaValue(value, YogaUnit.fromInt(unit)); + } + + private void putStyleOptional(int offset, float value) { + int isUndefinedBits = YogaConstants.isUndefined(value) ? TRUE_BITS : 0; + putStyleFloat(offset, value); + putStyleInt(offset + FLOAT_SIZE, isUndefinedBits); + } + + private float getStyleOptional(int offset) { + boolean isUndefined = getBool(mStyleNativePointer + offset + FLOAT_SIZE); + return isUndefined + ? YogaConstants.UNDEFINED + : getStyleFloat(offset); + } + + private float getLayoutFloat(int offset) { + return getFloat(mLayoutNativePointer + offset); + } + + private static float getFloat(long offset) { + int intBits = UNSAFE.getInt(null, offset); + return Float.intBitsToFloat(intBits); + } + + private static void putFloat(long offset, float value) { + int intBits = Float.floatToRawIntBits(value); + UNSAFE.putInt(null, offset, intBits); + } + + private static boolean getBool(long offset) { + // assumes little endian + return (UNSAFE.getInt(null, offset) & 0xFF) != 0; + } + +} diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 7f4dc041..482c14ae 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -344,13 +344,11 @@ jlong jni_YGNodeNewWithConfig( return reinterpret_cast(node); } -jlong jni_YGNodeNewByteBuffer( - alias_ref, - alias_ref javaNode) { +jlong jni_YGNodeNewNoProps(alias_ref, alias_ref javaNode) { return jni_YGNodeNew(nullptr, javaNode); } -jlong jni_YGNodeNewByteBufferWithConfig( +jlong jni_YGNodeNewNoPropsWithConfig( alias_ref, alias_ref javaNode, jlong configPointer) { @@ -747,6 +745,14 @@ local_ref jni_getLayoutBuffer( reinterpret_cast(layout), sizeof(YGLayout)); } +jlong jni_YGNodeStylePointer(alias_ref, jlong nativePointer) { + return reinterpret_cast(&_jlong2YGNodeRef(nativePointer)->getStyle()); +} + +jlong jni_YGNodeLayoutPointer(alias_ref, jlong nativePointer) { + return reinterpret_cast(&_jlong2YGNodeRef(nativePointer)->getLayout()); +} + #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) jint JNI_OnLoad(JavaVM* vm, void*) { @@ -860,8 +866,8 @@ jint JNI_OnLoad(JavaVM* vm, void*) { { YGMakeNativeMethod(jni_YGNodeCloneNoProps), YGMakeNativeMethod(jni_YGNodeFree), - YGMakeNativeMethod(jni_YGNodeNewByteBuffer), - YGMakeNativeMethod(jni_YGNodeNewByteBufferWithConfig), + YGMakeNativeMethod(jni_YGNodeNewNoProps), + YGMakeNativeMethod(jni_YGNodeNewNoPropsWithConfig), YGMakeNativeMethod(jni_YGNodeReset), YGMakeNativeMethod(jni_YGNodeIsDirty), YGMakeNativeMethod(jni_getStyleBuffer), @@ -872,5 +878,17 @@ jint JNI_OnLoad(JavaVM* vm, void*) { { YGMakeNativeMethod(jni_getStyleBuffer), }); + registerNatives( + "com/facebook/yoga/YogaNodePropertiesUnsafe", + { + YGMakeNativeMethod(jni_YGNodeCloneNoProps), + YGMakeNativeMethod(jni_YGNodeFree), + YGMakeNativeMethod(jni_YGNodeNewNoProps), + YGMakeNativeMethod(jni_YGNodeNewNoPropsWithConfig), + YGMakeNativeMethod(jni_YGNodeStylePointer), + YGMakeNativeMethod(jni_YGNodeLayoutPointer), + YGMakeNativeMethod(jni_YGNodeIsDirty), + YGMakeNativeMethod(jni_YGNodeReset), + }); }); } diff --git a/java/stubs/build.gradle b/java/stubs/build.gradle new file mode 100644 index 00000000..f2faa446 --- /dev/null +++ b/java/stubs/build.gradle @@ -0,0 +1,10 @@ +apply plugin: 'java' + +sourceSets { + main { + java { + srcDirs = ['src'] + } + } +} + diff --git a/java/stubs/src/sun/misc/Unsafe.java b/java/stubs/src/sun/misc/Unsafe.java new file mode 100644 index 00000000..01ff08dc --- /dev/null +++ b/java/stubs/src/sun/misc/Unsafe.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ + +package sun.misc; + +/** + * Stub for sun.misc.Unsafe, which is not exposed by the Android SDK. + * + * This only contains the methods and fields we need for Yoga. + */ +public final class Unsafe { + private static final Unsafe theUnsafe = null; + + public final int getInt(Object object, long offset) { + throw new RuntimeException("Stub!"); + } + + public final void putInt(Object object, long offset, int value) { + throw new RuntimeException("Stub!"); + } +} + diff --git a/java/tests/com/facebook/yoga/TestParametrization.java b/java/tests/com/facebook/yoga/TestParametrization.java index ecb81ca1..23fe67d1 100644 --- a/java/tests/com/facebook/yoga/TestParametrization.java +++ b/java/tests/com/facebook/yoga/TestParametrization.java @@ -59,6 +59,22 @@ public class TestParametrization { public String toString() { return "Hybrid"; } + }, + new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(YogaNode.UNSAFE); + } + + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(YogaNode.UNSAFE, config); + } + + @Override + public String toString() { + return "Unsafe"; + } }); } diff --git a/settings.gradle b/settings.gradle index 93d836ba..f18ef534 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,6 @@ -include ':yoga', ':yogacore', ':yoga-layout', ':yoga:proguard-annotations', ':libfb' +include ':yoga', ':yogacore', ':yoga-layout', ':yoga:proguard-annotations', ':yoga:stubs', ':libfb' project(':yoga').projectDir = file('java') project(':yoga:proguard-annotations').projectDir = file('java/proguard-annotations') +project(':yoga:stubs').projectDir = file('java/stubs') project(':yoga-layout').projectDir = file('android') project(':libfb').projectDir = file('lib/fb') From 78cdf3cadcae48825d644a1c04128faec1511e83 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 6 Aug 2018 02:10:43 -0700 Subject: [PATCH 049/189] Back to JNI storage Summary: @public This reverts the Yoga/Java storage experiment. I will follow up with any learnings. Reviewed By: pasqualeanatriello Differential Revision: D9168405 fbshipit-source-id: fb227fb9353bd4c4e3bebbe9b04eec1132e532e8 --- java/BUCK | 10 - java/build.gradle | 1 - java/com/facebook/yoga/YogaNode.java | 454 +++++++---- .../facebook/yoga/YogaNodeMemoryLayout.java | 151 ---- .../com/facebook/yoga/YogaNodeProperties.java | 169 ----- .../yoga/YogaNodePropertiesByteBuffer.java | 515 ------------- .../yoga/YogaNodePropertiesHybrid.java | 261 ------- .../facebook/yoga/YogaNodePropertiesJNI.java | 704 ------------------ .../yoga/YogaNodePropertiesUnsafe.java | 580 --------------- java/jni/YGJNI.cpp | 185 +---- java/stubs/build.gradle | 10 - java/stubs/src/sun/misc/Unsafe.java | 27 - .../facebook/yoga/TestParametrization.java | 79 +- settings.gradle | 3 +- 14 files changed, 369 insertions(+), 2780 deletions(-) delete mode 100644 java/com/facebook/yoga/YogaNodeMemoryLayout.java delete mode 100644 java/com/facebook/yoga/YogaNodeProperties.java delete mode 100644 java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java delete mode 100644 java/com/facebook/yoga/YogaNodePropertiesHybrid.java delete mode 100644 java/com/facebook/yoga/YogaNodePropertiesJNI.java delete mode 100644 java/com/facebook/yoga/YogaNodePropertiesUnsafe.java delete mode 100644 java/stubs/build.gradle delete mode 100644 java/stubs/src/sun/misc/Unsafe.java diff --git a/java/BUCK b/java/BUCK index dbd2d335..4ddabcef 100644 --- a/java/BUCK +++ b/java/BUCK @@ -29,19 +29,9 @@ yoga_cxx_library( ], ) -yoga_java_library( - name = "stubs", - srcs = glob(["stubs/**/*.java"]), - source = "1.7", - target = "1.7", -) - yoga_java_library( name = "java", srcs = glob(["com/facebook/yoga/*.java"]), - provided_deps = [ - ":stubs", - ], required_for_source_only_abi = True, source = "1.7", target = "1.7", diff --git a/java/build.gradle b/java/build.gradle index 2ed33d0c..21034e42 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -52,7 +52,6 @@ android { dependencies { compileOnly 'com.google.code.findbugs:jsr305:3.0.1' compileOnly project(':yoga:proguard-annotations') - compileOnly project(':yoga:stubs') implementation 'com.facebook.soloader:soloader:0.5.1' testImplementation 'junit:junit:4.12' } diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 2924f0c3..7c03e718 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -21,74 +21,132 @@ public class YogaNode implements Cloneable { SoLoader.loadLibrary("yoga"); } - public static final int BYTE_BUFFER = 1; - public static final int HYBRID = 2; - public static final int UNSAFE = 3; - - /** Get native instance count. Useful for testing only. */ + /** + * Get native instance count. Useful for testing only. + */ static native int jni_YGNodeGetInstanceCount(); - private YogaNodeProperties mDelegate; private YogaNode mOwner; @Nullable private List mChildren; private YogaMeasureFunction mMeasureFunction; private YogaBaselineFunction mBaselineFunction; + private long mNativePointer; private Object mData; + /* Those flags needs be in sync with YGJNI.cpp */ + private static final int MARGIN = 1; + private static final int PADDING = 2; + private static final int BORDER = 4; + + @DoNotStrip + private int mEdgeSetFlag = 0; + + private boolean mHasSetPosition = false; + + @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; + + private native long jni_YGNodeNew(); public YogaNode() { - mDelegate = new YogaNodePropertiesJNI(this); + mNativePointer = jni_YGNodeNew(); + if (mNativePointer == 0) { + throw new IllegalStateException("Failed to allocate native memory"); + } } + private native long jni_YGNodeNewWithConfig(long configPointer); public YogaNode(YogaConfig config) { - mDelegate = new YogaNodePropertiesJNI(this, config); - } - - public YogaNode(int storageType) { - switch (storageType) { - case BYTE_BUFFER: - mDelegate = new YogaNodePropertiesByteBuffer(this); - break; - case HYBRID: - mDelegate = new YogaNodePropertiesHybrid(this); - break; - case UNSAFE: - mDelegate = new YogaNodePropertiesUnsafe(this); - break; - default: - mDelegate = new YogaNodePropertiesJNI(this); + mNativePointer = jni_YGNodeNewWithConfig(config.mNativePointer); + if (mNativePointer == 0) { + throw new IllegalStateException("Failed to allocate native memory"); } } - public YogaNode(int storageType, YogaConfig config) { - switch (storageType) { - case BYTE_BUFFER: - mDelegate = new YogaNodePropertiesByteBuffer(this, config); - break; - case HYBRID: - mDelegate = new YogaNodePropertiesHybrid(this, config); - break; - case UNSAFE: - mDelegate = new YogaNodePropertiesUnsafe(this, config); - break; - default: - mDelegate = new YogaNodePropertiesJNI(this, config); + @Override + protected void finalize() throws Throwable { + try { + freeNatives(); + } finally { + super.finalize(); } } - public long getNativePointer() { - return mDelegate.getNativePointer(); - } + private static native void jni_YGNodeFree(long nativePointer); /* frees the native underlying YGNode. Useful for testing. */ public void freeNatives() { - mDelegate.freeNatives(); + if (mNativePointer > 0) { + long nativePointer = mNativePointer; + mNativePointer = 0; + jni_YGNodeFree(nativePointer); + } } + private native void jni_YGNodeReset(long nativePointer); public void reset() { + mEdgeSetFlag = 0; + mHasSetPosition = false; + 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; + mMeasureFunction = null; mBaselineFunction = null; mData = null; - mDelegate.reset(); + mDoesLegacyStretchFlagAffectsLayout = false; + + jni_YGNodeReset(mNativePointer); } public int getChildCount() { @@ -113,7 +171,7 @@ public class YogaNode implements Cloneable { } mChildren.add(i, child); child.mOwner = this; - jni_YGNodeInsertChild(getNativePointer(), child.getNativePointer(), i); + jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i); } private native void jni_YGNodeInsertSharedChild(long nativePointer, long childPointer, int index); @@ -124,24 +182,27 @@ public class YogaNode implements Cloneable { } mChildren.add(i, child); child.mOwner = null; - jni_YGNodeInsertSharedChild(getNativePointer(), child.getNativePointer(), i); + jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i); } private native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); + private native long jni_YGNodeClone(long nativePointer, Object newNode); + @Override public YogaNode clone() { try { YogaNode clonedYogaNode = (YogaNode) super.clone(); + long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); if (mChildren != null) { for (YogaNode child : mChildren) { - child.jni_YGNodeSetOwner(child.getNativePointer(), 0); + child.jni_YGNodeSetOwner(child.mNativePointer, 0); child.mOwner = null; } } - clonedYogaNode.mDelegate = mDelegate.clone(clonedYogaNode); + clonedYogaNode.mNativePointer = clonedNativePointer; clonedYogaNode.mOwner = null; clonedYogaNode.mChildren = mChildren != null ? (List) ((ArrayList) mChildren).clone() : null; @@ -160,8 +221,9 @@ public class YogaNode implements Cloneable { public YogaNode cloneWithNewChildren() { try { YogaNode clonedYogaNode = (YogaNode) super.clone(); - clonedYogaNode.mDelegate = mDelegate.clone(clonedYogaNode); + long clonedNativePointer = jni_YGNodeClone(mNativePointer, clonedYogaNode); clonedYogaNode.mOwner = null; + clonedYogaNode.mNativePointer = clonedNativePointer; clonedYogaNode.clearChildren(); return clonedYogaNode; } catch (CloneNotSupportedException ex) { @@ -174,7 +236,7 @@ public class YogaNode implements Cloneable { private void clearChildren() { mChildren = null; - jni_YGNodeClearChildren(getNativePointer()); + jni_YGNodeClearChildren(mNativePointer); } private native void jni_YGNodeRemoveChild(long nativePointer, long childPointer); @@ -185,7 +247,7 @@ public class YogaNode implements Cloneable { } final YogaNode child = mChildren.remove(i); child.mOwner = null; - jni_YGNodeRemoveChild(getNativePointer(), child.getNativePointer()); + jni_YGNodeRemoveChild(mNativePointer, child.mNativePointer); return child; } @@ -213,329 +275,455 @@ public class YogaNode implements Cloneable { return mChildren == null ? -1 : mChildren.indexOf(child); } - private native boolean jni_YGNodeCalculateLayout(long nativePointer, float width, float height); - + private native void jni_YGNodeCalculateLayout(long nativePointer, float width, float height); public void calculateLayout(float width, float height) { - boolean hasNewLayout = jni_YGNodeCalculateLayout(getNativePointer(), width, height); - mDelegate.onAfterCalculateLayout(hasNewLayout); + jni_YGNodeCalculateLayout(mNativePointer, width, height); } public boolean hasNewLayout() { - return mDelegate.hasNewLayout(); + return mHasNewLayout; } private native void jni_YGNodeMarkDirty(long nativePointer); public void dirty() { - jni_YGNodeMarkDirty(getNativePointer()); + jni_YGNodeMarkDirty(mNativePointer); } private native void jni_YGNodeMarkDirtyAndPropogateToDescendants(long nativePointer); public void dirtyAllDescendants() { - jni_YGNodeMarkDirtyAndPropogateToDescendants(getNativePointer()); + jni_YGNodeMarkDirtyAndPropogateToDescendants(mNativePointer); } + private native boolean jni_YGNodeIsDirty(long nativePointer); public boolean isDirty() { - return mDelegate.isDirty(); + return jni_YGNodeIsDirty(mNativePointer); } private native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer); public void copyStyle(YogaNode srcNode) { - jni_YGNodeCopyStyle(getNativePointer(), srcNode.getNativePointer()); + jni_YGNodeCopyStyle(mNativePointer, srcNode.mNativePointer); } public void markLayoutSeen() { - mDelegate.markLayoutSeen(); + mHasNewLayout = false; } + private native int jni_YGNodeStyleGetDirection(long nativePointer); public YogaDirection getStyleDirection() { - return mDelegate.getStyleDirection(); + return YogaDirection.fromInt(jni_YGNodeStyleGetDirection(mNativePointer)); } + private native void jni_YGNodeStyleSetDirection(long nativePointer, int direction); public void setDirection(YogaDirection direction) { - mDelegate.setDirection(direction); + jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue()); } + private native int jni_YGNodeStyleGetFlexDirection(long nativePointer); public YogaFlexDirection getFlexDirection() { - return mDelegate.getFlexDirection(); + return YogaFlexDirection.fromInt(jni_YGNodeStyleGetFlexDirection(mNativePointer)); } + private native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection); public void setFlexDirection(YogaFlexDirection flexDirection) { - mDelegate.setFlexDirection(flexDirection); + jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue()); } + private native int jni_YGNodeStyleGetJustifyContent(long nativePointer); public YogaJustify getJustifyContent() { - return mDelegate.getJustifyContent(); + return YogaJustify.fromInt(jni_YGNodeStyleGetJustifyContent(mNativePointer)); } + private native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent); public void setJustifyContent(YogaJustify justifyContent) { - mDelegate.setJustifyContent(justifyContent); + jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue()); } + private native int jni_YGNodeStyleGetAlignItems(long nativePointer); public YogaAlign getAlignItems() { - return mDelegate.getAlignItems(); + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignItems(mNativePointer)); } + private native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems); public void setAlignItems(YogaAlign alignItems) { - mDelegate.setAlignItems(alignItems); + jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue()); } + private native int jni_YGNodeStyleGetAlignSelf(long nativePointer); public YogaAlign getAlignSelf() { - return mDelegate.getAlignSelf(); + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignSelf(mNativePointer)); } + private native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf); public void setAlignSelf(YogaAlign alignSelf) { - mDelegate.setAlignSelf(alignSelf); + jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue()); } + private native int jni_YGNodeStyleGetAlignContent(long nativePointer); public YogaAlign getAlignContent() { - return mDelegate.getAlignContent(); + return YogaAlign.fromInt(jni_YGNodeStyleGetAlignContent(mNativePointer)); } + private native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent); public void setAlignContent(YogaAlign alignContent) { - mDelegate.setAlignContent(alignContent); + jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue()); } + private native int jni_YGNodeStyleGetPositionType(long nativePointer); public YogaPositionType getPositionType() { - return mDelegate.getPositionType(); + return YogaPositionType.fromInt(jni_YGNodeStyleGetPositionType(mNativePointer)); } + private native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType); public void setPositionType(YogaPositionType positionType) { - mDelegate.setPositionType(positionType); + jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue()); } + private native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType); public void setWrap(YogaWrap flexWrap) { - mDelegate.setWrap(flexWrap); + jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue()); } + private native int jni_YGNodeStyleGetOverflow(long nativePointer); public YogaOverflow getOverflow() { - return mDelegate.getOverflow(); + return YogaOverflow.fromInt(jni_YGNodeStyleGetOverflow(mNativePointer)); } + private native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow); public void setOverflow(YogaOverflow overflow) { - mDelegate.setOverflow(overflow); + jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue()); } + private native int jni_YGNodeStyleGetDisplay(long nativePointer); public YogaDisplay getDisplay() { - return mDelegate.getDisplay(); + return YogaDisplay.fromInt(jni_YGNodeStyleGetDisplay(mNativePointer)); } + private native void jni_YGNodeStyleSetDisplay(long nativePointer, int display); public void setDisplay(YogaDisplay display) { - mDelegate.setDisplay(display); + jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue()); } + private native void jni_YGNodeStyleSetFlex(long nativePointer, float flex); public void setFlex(float flex) { - mDelegate.setFlex(flex); + jni_YGNodeStyleSetFlex(mNativePointer, flex); } + private native float jni_YGNodeStyleGetFlexGrow(long nativePointer); public float getFlexGrow() { - return mDelegate.getFlexGrow(); + return jni_YGNodeStyleGetFlexGrow(mNativePointer); } + private native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); public void setFlexGrow(float flexGrow) { - mDelegate.setFlexGrow(flexGrow); + jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow); } + private native float jni_YGNodeStyleGetFlexShrink(long nativePointer); public float getFlexShrink() { - return mDelegate.getFlexShrink(); + return jni_YGNodeStyleGetFlexShrink(mNativePointer); } + private native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); public void setFlexShrink(float flexShrink) { - mDelegate.setFlexShrink(flexShrink); + jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); } + private native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); public YogaValue getFlexBasis() { - return mDelegate.getFlexBasis(); + return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); } + private native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); public void setFlexBasis(float flexBasis) { - mDelegate.setFlexBasis(flexBasis); + jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); } + private native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); public void setFlexBasisPercent(float percent) { - mDelegate.setFlexBasisPercent(percent); + jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); } + private native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); public void setFlexBasisAuto() { - mDelegate.setFlexBasisAuto(); + jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); } + private native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); public YogaValue getMargin(YogaEdge edge) { - return mDelegate.getMargin(edge); + if (!((mEdgeSetFlag & MARGIN) == MARGIN)) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); } + private native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); public void setMargin(YogaEdge edge, float margin) { - mDelegate.setMargin(edge, margin); + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); } + private native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); public void setMarginPercent(YogaEdge edge, float percent) { - mDelegate.setMarginPercent(edge, percent); + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); } + private native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); public void setMarginAuto(YogaEdge edge) { - mDelegate.setMarginAuto(edge); + mEdgeSetFlag |= MARGIN; + jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); } + private native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); public YogaValue getPadding(YogaEdge edge) { - return mDelegate.getPadding(edge); + if (!((mEdgeSetFlag & PADDING) == PADDING)) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); } + private native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); public void setPadding(YogaEdge edge, float padding) { - mDelegate.setPadding(edge, padding); + mEdgeSetFlag |= PADDING; + jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); } + private native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); public void setPaddingPercent(YogaEdge edge, float percent) { - mDelegate.setPaddingPercent(edge, percent); + mEdgeSetFlag |= PADDING; + jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); } + private native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); public float getBorder(YogaEdge edge) { - return mDelegate.getBorder(edge); + if (!((mEdgeSetFlag & BORDER) == BORDER)) { + return YogaConstants.UNDEFINED; + } + return jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); } + private native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); public void setBorder(YogaEdge edge, float border) { - mDelegate.setBorder(edge, border); + mEdgeSetFlag |= BORDER; + jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); } + private native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); public YogaValue getPosition(YogaEdge edge) { - return mDelegate.getPosition(edge); + if (!mHasSetPosition) { + return YogaValue.UNDEFINED; + } + return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); } + private native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); public void setPosition(YogaEdge edge, float position) { - mDelegate.setPosition(edge, position); + mHasSetPosition = true; + jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); } + private native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent); public void setPositionPercent(YogaEdge edge, float percent) { - mDelegate.setPositionPercent(edge, percent); + mHasSetPosition = true; + jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); } + private native Object jni_YGNodeStyleGetWidth(long nativePointer); public YogaValue getWidth() { - return mDelegate.getWidth(); + return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); } + private native void jni_YGNodeStyleSetWidth(long nativePointer, float width); public void setWidth(float width) { - mDelegate.setWidth(width); + jni_YGNodeStyleSetWidth(mNativePointer, width); } + private native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); public void setWidthPercent(float percent) { - mDelegate.setWidthPercent(percent); + jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); } + private native void jni_YGNodeStyleSetWidthAuto(long nativePointer); public void setWidthAuto() { - mDelegate.setWidthAuto(); + jni_YGNodeStyleSetWidthAuto(mNativePointer); } + private native Object jni_YGNodeStyleGetHeight(long nativePointer); public YogaValue getHeight() { - return mDelegate.getHeight(); + return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); } + private native void jni_YGNodeStyleSetHeight(long nativePointer, float height); public void setHeight(float height) { - mDelegate.setHeight(height); + jni_YGNodeStyleSetHeight(mNativePointer, height); } + private native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); public void setHeightPercent(float percent) { - mDelegate.setHeightPercent(percent); + jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); } + private native void jni_YGNodeStyleSetHeightAuto(long nativePointer); public void setHeightAuto() { - mDelegate.setHeightAuto(); + jni_YGNodeStyleSetHeightAuto(mNativePointer); } + private native Object jni_YGNodeStyleGetMinWidth(long nativePointer); public YogaValue getMinWidth() { - return mDelegate.getMinWidth(); + return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); } + private native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); public void setMinWidth(float minWidth) { - mDelegate.setMinWidth(minWidth); + jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); } + private native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); public void setMinWidthPercent(float percent) { - mDelegate.setMinWidthPercent(percent); + jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); } + private native Object jni_YGNodeStyleGetMinHeight(long nativePointer); public YogaValue getMinHeight() { - return mDelegate.getMinHeight(); + return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); } + private native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); public void setMinHeight(float minHeight) { - mDelegate.setMinHeight(minHeight); + jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); } + private native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); public void setMinHeightPercent(float percent) { - mDelegate.setMinHeightPercent(percent); + jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); } + private native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); public YogaValue getMaxWidth() { - return mDelegate.getMaxWidth(); + return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); } + private native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); public void setMaxWidth(float maxWidth) { - mDelegate.setMaxWidth(maxWidth); + jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); } + private native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); public void setMaxWidthPercent(float percent) { - mDelegate.setMaxWidthPercent(percent); + jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); } + private native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); public YogaValue getMaxHeight() { - return mDelegate.getMaxHeight(); + return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); } + private native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); public void setMaxHeight(float maxheight) { - mDelegate.setMaxHeight(maxheight); + jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); } + private native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); public void setMaxHeightPercent(float percent) { - mDelegate.setMaxHeightPercent(percent); + jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); } + private native float jni_YGNodeStyleGetAspectRatio(long nativePointer); public float getAspectRatio() { - return mDelegate.getAspectRatio(); + return jni_YGNodeStyleGetAspectRatio(mNativePointer); } + private native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio); public void setAspectRatio(float aspectRatio) { - mDelegate.setAspectRatio(aspectRatio); + jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio); } public float getLayoutX() { - return mDelegate.getLayoutX(); + return mLeft; } public float getLayoutY() { - return mDelegate.getLayoutY(); + return mTop; } public float getLayoutWidth() { - return mDelegate.getLayoutWidth(); + return mWidth; } public float getLayoutHeight() { - return mDelegate.getLayoutHeight(); + return mHeight; } public boolean getDoesLegacyStretchFlagAffectsLayout() { - return mDelegate.getDoesLegacyStretchFlagAffectsLayout(); + return mDoesLegacyStretchFlagAffectsLayout; } public float getLayoutMargin(YogaEdge edge) { - return mDelegate.getLayoutMargin(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"); + } } public float getLayoutPadding(YogaEdge edge) { - return mDelegate.getLayoutPadding(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"); + } } public float getLayoutBorder(YogaEdge edge) { - return mDelegate.getLayoutBorder(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"); + } } public YogaDirection getLayoutDirection() { - return mDelegate.getLayoutDirection(); + return YogaDirection.fromInt(mLayoutDirection); } private native void jni_YGNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); public void setMeasureFunction(YogaMeasureFunction measureFunction) { mMeasureFunction = measureFunction; - jni_YGNodeSetHasMeasureFunc(getNativePointer(), measureFunction != null); + jni_YGNodeSetHasMeasureFunc(mNativePointer, measureFunction != null); } // Implementation Note: Why this method needs to stay final @@ -560,7 +748,7 @@ public class YogaNode implements Cloneable { private native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc); public void setBaselineFunction(YogaBaselineFunction baselineFunction) { mBaselineFunction = baselineFunction; - jni_YGNodeSetHasBaselineFunc(getNativePointer(), baselineFunction != null); + jni_YGNodeSetHasBaselineFunc(mNativePointer, baselineFunction != null); } @DoNotStrip @@ -587,7 +775,7 @@ public class YogaNode implements Cloneable { * layout of the tree rooted at this node. */ public void print() { - jni_YGNodePrint(getNativePointer()); + jni_YGNodePrint(mNativePointer); } /** @@ -605,6 +793,6 @@ public class YogaNode implements Cloneable { mChildren.remove(childIndex); mChildren.add(childIndex, newNode); newNode.mOwner = this; - return newNode.getNativePointer(); + return newNode.mNativePointer; } } diff --git a/java/com/facebook/yoga/YogaNodeMemoryLayout.java b/java/com/facebook/yoga/YogaNodeMemoryLayout.java deleted file mode 100644 index 212c27ec..00000000 --- a/java/com/facebook/yoga/YogaNodeMemoryLayout.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ - -package com.facebook.yoga; - -import com.facebook.proguard.annotations.DoNotStrip; -import java.nio.ByteBuffer; - -@DoNotStrip -/* package */ final class YogaNodeMemoryLayout { - - private static final int FLOAT_SIZE = 4; - private static final int INT_SIZE = 4; - private static final int VALUE_SIZE = FLOAT_SIZE + INT_SIZE; - private static final byte FALSE = 0; - private static final byte TRUE = 1; - private static final int AUTO = YogaUnit.AUTO.intValue(); - private static final int POINT = YogaUnit.POINT.intValue(); - private static final int PERCENT = YogaUnit.PERCENT.intValue(); - private static final int UNDEFINED = YogaUnit.UNDEFINED.intValue(); - - // TODO(davidaurelio) code-gen these values - static final int styleDirection = 0; - static final int styleFlexDirection = 4; - static final int styleJustifyContent = 8; - static final int styleAlignContent = 12; - static final int styleAlignItems = 16; - static final int styleAlignSelf = 20; - static final int stylePositionType = 24; - static final int styleFlexWrap = 28; - static final int styleOverflow = 32; - static final int styleDisplay = 36; - static final int styleFlex = 40; - static final int styleFlexGrow = 48; - static final int styleFlexShrink = 56; - static final int styleFlexBasis = 64; - static final int styleMargin = 72; - static final int stylePosition = 144; - static final int stylePadding = 216; - static final int styleBorder = 288; - static final int styleDimensions = 360; - static final int styleMinDimensions = 376; - static final int styleMaxDimensions = 392; - static final int styleAspectRatio = 408; - - static final int styleWidth = styleDimensions; - static final int styleHeight = styleDimensions + VALUE_SIZE; - static final int styleMinWidth = styleMinDimensions; - static final int styleMinHeight = styleMinDimensions + VALUE_SIZE; - static final int styleMaxWidth = styleMaxDimensions; - static final int styleMaxHeight = styleMaxDimensions + VALUE_SIZE; - - static final int layoutPosition = 0; - static final int layoutDimensions = 16; - static final int layoutMargin = 24; - static final int layoutBorder = 48; - static final int layoutPadding = 72; - static final int layoutDirection = 96; - static final int layoutComputedFlexBasisGeneration = 100; - static final int layoutComputedFlexBasis = 104; - static final int layoutHadOverflow = 112; - static final int layoutGenerationCount = 116; - static final int layoutLastOwnerDirection = 120; - static final int layoutNextCachedMeasurementsIndex = 124; - static final int layoutCachedMeasurements = 128; - static final int layoutMeasuredDimensions = 512; - static final int layoutCachedLayout = 520; - static final int layoutDidUseLegacyFlag = 544; - static final int layoutDoesLegacyStretchFlagAffectsLayout = 545; - - static final int layoutX = layoutPosition; - static final int layoutY = layoutPosition + FLOAT_SIZE; - static final int layoutWidth = layoutDimensions; - static final int layoutHeight = layoutDimensions + FLOAT_SIZE; - - static int stylePositionOffset(YogaEdge edge) { - return stylePosition + edge.intValue() * VALUE_SIZE; - } - - static int styleMarginOffset(YogaEdge edge) { - return styleMargin + edge.intValue() * VALUE_SIZE; - } - - static int layoutMarginOffset(YogaEdge edge) { - return layoutMargin + edge.intValue() * FLOAT_SIZE; - } - - static int stylePaddingOffset(YogaEdge edge) { - return stylePadding + edge.intValue() * VALUE_SIZE; - } - - static int layoutPaddingOffset(YogaEdge edge) { - return layoutPadding + edge.intValue() * FLOAT_SIZE; - } - - static int styleBorderOffset(YogaEdge edge) { - return styleBorder + edge.intValue() * VALUE_SIZE; - } - - static int layoutBorderOffset(YogaEdge edge) { - return layoutBorder + edge.intValue() * FLOAT_SIZE; - } - - static void putOptional(ByteBuffer buffer, int offset, float value) { - buffer.putFloat(offset, value); - buffer.put( - offset + FLOAT_SIZE, YogaConstants.isUndefined(value) ? TRUE : FALSE); // bool isUndefined_ - } - - static float getOptional(ByteBuffer buffer, int offset) { - return getBoolean(buffer, offset + FLOAT_SIZE) - ? YogaConstants.UNDEFINED - : buffer.getFloat(offset); - } - - private static void putValue(ByteBuffer buffer, int offset, float value, int unit) { - if (YogaConstants.isUndefined(value)) { - value = YogaConstants.UNDEFINED; - unit = UNDEFINED; - } - buffer.putFloat(offset, value); - buffer.putInt(offset + FLOAT_SIZE, unit); - } - - static void putAutoValue(ByteBuffer buffer, int offset) { - putValue(buffer, offset, 0, AUTO); - } - - static void putPointValue(ByteBuffer buffer, int offset, float value) { - putValue(buffer, offset, value, POINT); - } - - static void putPercentValue(ByteBuffer buffer, int offset, float value) { - putValue(buffer, offset, value, PERCENT); - } - - static YogaValue getValue(ByteBuffer buffer, int offset) { - float value = buffer.getFloat(offset); - int unit = buffer.getInt(offset + FLOAT_SIZE); - return new YogaValue(value, YogaUnit.fromInt(unit)); - } - - static boolean getBoolean(ByteBuffer buffer, int offset) { - return buffer.get(offset) != 0; - } -} diff --git a/java/com/facebook/yoga/YogaNodeProperties.java b/java/com/facebook/yoga/YogaNodeProperties.java deleted file mode 100644 index c93145e4..00000000 --- a/java/com/facebook/yoga/YogaNodeProperties.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ -package com.facebook.yoga; - -public interface YogaNodeProperties { - - YogaNodeProperties clone(YogaNode node); - - long getNativePointer(); - - void onAfterCalculateLayout(boolean hasNewLayout); - - void reset(); - - boolean hasNewLayout(); - - boolean isDirty(); - - void markLayoutSeen(); - - YogaDirection getStyleDirection(); - - void setDirection(YogaDirection direction); - - YogaFlexDirection getFlexDirection(); - - void setFlexDirection(YogaFlexDirection flexDirection); - - YogaJustify getJustifyContent(); - - void setJustifyContent(YogaJustify justifyContent); - - YogaAlign getAlignItems(); - - void setAlignItems(YogaAlign alignItems); - - YogaAlign getAlignSelf(); - - void setAlignSelf(YogaAlign alignSelf); - - YogaAlign getAlignContent(); - - void setAlignContent(YogaAlign alignContent); - - YogaPositionType getPositionType(); - - void setPositionType(YogaPositionType positionType); - - void setWrap(YogaWrap flexWrap); - - YogaOverflow getOverflow(); - - void setOverflow(YogaOverflow overflow); - - YogaDisplay getDisplay(); - - void setDisplay(YogaDisplay display); - - void setFlex(float flex); - - float getFlexGrow(); - - void setFlexGrow(float flexGrow); - - float getFlexShrink(); - - void setFlexShrink(float flexShrink); - - YogaValue getFlexBasis(); - - void setFlexBasis(float flexBasis); - - void setFlexBasisPercent(float percent); - - void setFlexBasisAuto(); - - YogaValue getMargin(YogaEdge edge); - - void setMargin(YogaEdge edge, float margin); - - void setMarginPercent(YogaEdge edge, float percent); - - void setMarginAuto(YogaEdge edge); - - YogaValue getPadding(YogaEdge edge); - - void setPadding(YogaEdge edge, float padding); - - void setPaddingPercent(YogaEdge edge, float percent); - - float getBorder(YogaEdge edge); - - void setBorder(YogaEdge edge, float border); - - YogaValue getPosition(YogaEdge edge); - - void setPosition(YogaEdge edge, float position); - - void setPositionPercent(YogaEdge edge, float percent); - - YogaValue getWidth(); - - void setWidth(float width); - - void setWidthPercent(float percent); - - void setWidthAuto(); - - YogaValue getHeight(); - - void setHeight(float height); - - void setHeightPercent(float percent); - - void setHeightAuto(); - - YogaValue getMinWidth(); - - void setMinWidth(float minWidth); - - void setMinWidthPercent(float percent); - - YogaValue getMinHeight(); - - void setMinHeight(float minHeight); - - void setMinHeightPercent(float percent); - - YogaValue getMaxWidth(); - - void setMaxWidth(float maxWidth); - - void setMaxWidthPercent(float percent); - - YogaValue getMaxHeight(); - - void setMaxHeight(float maxheight); - - void setMaxHeightPercent(float percent); - - float getAspectRatio(); - - void setAspectRatio(float aspectRatio); - - float getLayoutX(); - - float getLayoutY(); - - float getLayoutWidth(); - - float getLayoutHeight(); - - boolean getDoesLegacyStretchFlagAffectsLayout(); - - float getLayoutMargin(YogaEdge edge); - - float getLayoutPadding(YogaEdge edge); - - float getLayoutBorder(YogaEdge edge); - - YogaDirection getLayoutDirection(); - - void freeNatives(); -} diff --git a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java b/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java deleted file mode 100644 index f189a5b4..00000000 --- a/java/com/facebook/yoga/YogaNodePropertiesByteBuffer.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ -package com.facebook.yoga; - -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.soloader.SoLoader; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -@DoNotStrip -public class YogaNodePropertiesByteBuffer implements YogaNodeProperties, Cloneable { - - static { - SoLoader.loadLibrary("yoga"); - } - - private static final int RTL = YogaDirection.RTL.intValue(); - private final ByteBuffer mStyleBuffer; - private final ByteBuffer mLayoutBuffer; - private final long mNativePointer; - private boolean mHasBorderSet = false; - private boolean mHasNewLayout = true; - private boolean isFreed = false; - - private static native ByteBuffer jni_getStyleBuffer(long nativePointer); - - private static native ByteBuffer jni_getLayoutBuffer(long nativePointer); - - private static native long jni_YGNodeNewNoProps(YogaNode node); - - public YogaNodePropertiesByteBuffer(YogaNode node) { - this(jni_YGNodeNewNoProps(node)); - } - - private static native long jni_YGNodeNewNoPropsWithConfig(YogaNode node, long configPointer); - - public YogaNodePropertiesByteBuffer(YogaNode node, YogaConfig config) { - this(jni_YGNodeNewNoPropsWithConfig(node, config.mNativePointer)); - } - - public YogaNodePropertiesByteBuffer(long nativePointer) { - mNativePointer = nativePointer; - mStyleBuffer = jni_getStyleBuffer(nativePointer).order(ByteOrder.LITTLE_ENDIAN); - mLayoutBuffer = jni_getLayoutBuffer(nativePointer).order(ByteOrder.LITTLE_ENDIAN); - } - - @Override - protected void finalize() throws Throwable { - try { - freeNatives(); - } finally { - super.finalize(); - } - } - - private static native long jni_YGNodeCloneNoProps(long nativePointer, YogaNode newNode); - - @Override - public YogaNodeProperties clone(YogaNode node) { - long clonedNativePointer = jni_YGNodeCloneNoProps(getNativePointer(), node); - YogaNodePropertiesByteBuffer clone = new YogaNodePropertiesByteBuffer(clonedNativePointer); - clone.mHasBorderSet = mHasBorderSet; - clone.mHasNewLayout = mHasNewLayout; - return clone; - } - - @Override - public long getNativePointer() { - return mNativePointer; - } - - @Override - public void onAfterCalculateLayout(boolean hasNewLayout) { - mHasNewLayout = hasNewLayout; - } - - private static native void jni_YGNodeReset(long nativePointer); - - @Override - public void reset() { - mHasBorderSet = false; - mHasNewLayout = true; - jni_YGNodeReset(getNativePointer()); - } - - @Override - public boolean hasNewLayout() { - return mHasNewLayout; - } - - private static native boolean jni_YGNodeIsDirty(long nativePointer); - - @Override - public boolean isDirty() { - return jni_YGNodeIsDirty(mNativePointer); - } - - @Override - public void markLayoutSeen() { - mHasNewLayout = false; - } - - @Override - public YogaDirection getStyleDirection() { - return YogaDirection.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleDirection)); - } - - @Override - public YogaValue getPosition(YogaEdge edge) { - return YogaNodeMemoryLayout.getValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge)); - } - - @Override - public YogaValue getMargin(YogaEdge edge) { - return YogaNodeMemoryLayout.getValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); - } - - @Override - public YogaValue getPadding(YogaEdge edge) { - return YogaNodeMemoryLayout.getValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge)); - } - - @Override - public float getBorder(YogaEdge edge) { - return mHasBorderSet - ? mStyleBuffer.getFloat(YogaNodeMemoryLayout.styleBorderOffset(edge)) - : YogaConstants.UNDEFINED; - } - - @Override - public void setDirection(YogaDirection direction) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); - } - - @Override - public YogaFlexDirection getFlexDirection() { - return YogaFlexDirection.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleFlexDirection)); - } - - @Override - public void setFlexDirection(YogaFlexDirection flexDirection) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); - } - - @Override - public YogaJustify getJustifyContent() { - return YogaJustify.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleJustifyContent)); - } - - @Override - public void setJustifyContent(YogaJustify justifyContent) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); - } - - @Override - public YogaAlign getAlignItems() { - return YogaAlign.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleAlignItems)); - } - - @Override - public void setAlignItems(YogaAlign alignItems) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); - } - - @Override - public YogaAlign getAlignSelf() { - return YogaAlign.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleAlignSelf)); - } - - @Override - public void setAlignSelf(YogaAlign alignSelf) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); - } - - @Override - public YogaAlign getAlignContent() { - return YogaAlign.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleAlignContent)); - } - - @Override - public void setAlignContent(YogaAlign alignContent) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); - } - - @Override - public YogaPositionType getPositionType() { - return YogaPositionType.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.stylePositionType)); - } - - @Override - public void setPositionType(YogaPositionType positionType) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); - } - - @Override - public void setWrap(YogaWrap flexWrap) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); - } - - @Override - public YogaOverflow getOverflow() { - return YogaOverflow.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleOverflow)); - } - - @Override - public void setOverflow(YogaOverflow overflow) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); - } - - @Override - public YogaDisplay getDisplay() { - return YogaDisplay.fromInt(mStyleBuffer.getInt(YogaNodeMemoryLayout.styleDisplay)); - } - - @Override - public void setDisplay(YogaDisplay display) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); - } - - @Override - public void setFlex(float flex) { - YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlex, flex); - } - - @Override - public float getFlexGrow() { - return mStyleBuffer.getFloat(YogaNodeMemoryLayout.styleFlexGrow); - } - - @Override - public void setFlexGrow(float flexGrow) { - YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlexGrow, flexGrow); - } - - @Override - public float getFlexShrink() { - return mStyleBuffer.getFloat(YogaNodeMemoryLayout.styleFlexShrink); - } - - @Override - public void setFlexShrink(float flexShrink) { - YogaNodeMemoryLayout.putOptional( - mStyleBuffer, YogaNodeMemoryLayout.styleFlexShrink, flexShrink); - } - - @Override - public YogaValue getFlexBasis() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); - } - - @Override - public void setFlexBasis(float flexBasis) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, flexBasis); - } - - @Override - public void setFlexBasisPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, percent); - } - - @Override - public void setFlexBasisAuto() { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); - } - - @Override - public void setMargin(YogaEdge edge, float margin) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), margin); - } - - @Override - public void setMarginPercent(YogaEdge edge, float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), percent); - } - - @Override - public void setMarginAuto(YogaEdge edge) { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); - } - - @Override - public void setPadding(YogaEdge edge, float padding) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); - } - - @Override - public void setPaddingPercent(YogaEdge edge, float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); - } - - @Override - public void setBorder(YogaEdge edge, float border) { - mHasBorderSet = true; - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleBorderOffset(edge), border); - } - - @Override - public void setPosition(YogaEdge edge, float position) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), position); - } - - @Override - public void setPositionPercent(YogaEdge edge, float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), percent); - } - - @Override - public YogaValue getWidth() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); - } - - @Override - public void setWidth(float width) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, width); - } - - @Override - public void setWidthPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, percent); - } - - @Override - public void setWidthAuto() { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); - } - - @Override - public YogaValue getHeight() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); - } - - @Override - public void setHeight(float height) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, height); - } - - @Override - public void setHeightPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, percent); - } - - @Override - public void setHeightAuto() { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); - } - - @Override - public YogaValue getMinWidth() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth); - } - - @Override - public void setMinWidth(float minWidth) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, minWidth); - } - - @Override - public void setMinWidthPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, percent); - } - - @Override - public YogaValue getMinHeight() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight); - } - - @Override - public void setMinHeight(float minHeight) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, minHeight); - } - - @Override - public void setMinHeightPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, percent); - } - - @Override - public YogaValue getMaxWidth() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth); - } - - @Override - public void setMaxWidth(float maxWidth) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, maxWidth); - } - - @Override - public void setMaxWidthPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, percent); - } - - @Override - public YogaValue getMaxHeight() { - return YogaNodeMemoryLayout.getValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight); - } - - @Override - public void setMaxHeight(float maxHeight) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, maxHeight); - } - - @Override - public void setMaxHeightPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, percent); - } - - @Override - public float getAspectRatio() { - return YogaNodeMemoryLayout.getOptional(mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio); - } - - @Override - public void setAspectRatio(float aspectRatio) { - YogaNodeMemoryLayout.putOptional( - mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); - } - - @Override - public float getLayoutX() { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutX); - } - - @Override - public float getLayoutY() { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutY); - } - - @Override - public float getLayoutWidth() { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutWidth); - } - - @Override - public float getLayoutHeight() { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutHeight); - } - - @Override - public boolean getDoesLegacyStretchFlagAffectsLayout() { - return YogaNodeMemoryLayout.getBoolean( - mLayoutBuffer, YogaNodeMemoryLayout.layoutDoesLegacyStretchFlagAffectsLayout); - } - - @Override - public float getLayoutMargin(YogaEdge edge) { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutMarginOffset(layoutEdge(edge))); - } - - @Override - public float getLayoutPadding(YogaEdge edge) { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutPaddingOffset(layoutEdge(edge))); - } - - @Override - public float getLayoutBorder(YogaEdge edge) { - return mLayoutBuffer.getFloat(YogaNodeMemoryLayout.layoutBorderOffset(layoutEdge(edge))); - } - - @Override - public YogaDirection getLayoutDirection() { - return YogaDirection.fromInt(getLayoutDirectionInt()); - } - - private static native void jni_YGNodeFree(long nativePointer); - - @Override - public void freeNatives() { - if (!isFreed) { - isFreed = true; - jni_YGNodeFree(mNativePointer); - } - } - - private int getLayoutDirectionInt() { - return mLayoutBuffer.getInt(YogaNodeMemoryLayout.layoutDirection); - } - - private YogaEdge layoutEdge(YogaEdge edge) { - int layoutDirection = getLayoutDirectionInt(); - switch (edge) { - case LEFT: - return layoutDirection == RTL ? YogaEdge.END : YogaEdge.START; - case RIGHT: - return layoutDirection == RTL ? YogaEdge.START : YogaEdge.END; - case TOP: - case BOTTOM: - case START: - case END: - return edge; - default: - throw new IllegalArgumentException("Cannot get layout properties of multi-edge shorthands"); - } - } -} diff --git a/java/com/facebook/yoga/YogaNodePropertiesHybrid.java b/java/com/facebook/yoga/YogaNodePropertiesHybrid.java deleted file mode 100644 index dc727ccc..00000000 --- a/java/com/facebook/yoga/YogaNodePropertiesHybrid.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ -package com.facebook.yoga; - -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.soloader.SoLoader; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -@DoNotStrip -public class YogaNodePropertiesHybrid extends YogaNodePropertiesJNI { - - static { - SoLoader.loadLibrary("yoga"); - } - - private ByteBuffer mStyleBuffer; - - private static native ByteBuffer jni_getStyleBuffer(long nativePointer); - - public YogaNodePropertiesHybrid(YogaNode node) { - super(node); - mStyleBuffer = jni_getStyleBuffer(getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); - } - - public YogaNodePropertiesHybrid(YogaNode node, YogaConfig config) { - super(node, config); - mStyleBuffer = jni_getStyleBuffer(getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); - } - - @Override - public void setDirection(YogaDirection direction) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); - } - - @Override - public void setFlexDirection(YogaFlexDirection flexDirection) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); - } - - @Override - public void setJustifyContent(YogaJustify justifyContent) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); - } - - @Override - public void setAlignItems(YogaAlign alignItems) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); - } - - @Override - public void setAlignSelf(YogaAlign alignSelf) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); - } - - @Override - public void setAlignContent(YogaAlign alignContent) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); - } - - @Override - public void setPositionType(YogaPositionType positionType) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); - } - - @Override - public void setWrap(YogaWrap flexWrap) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); - } - - @Override - public void setOverflow(YogaOverflow overflow) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); - } - - @Override - public void setDisplay(YogaDisplay display) { - mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); - } - - @Override - public void setFlex(float flex) { - YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlex, flex); - } - - @Override - public void setFlexGrow(float flexGrow) { - YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlexGrow, flexGrow); - } - - @Override - public void setFlexShrink(float flexShrink) { - YogaNodeMemoryLayout.putOptional( - mStyleBuffer, YogaNodeMemoryLayout.styleFlexShrink, flexShrink); - } - - @Override - public void setFlexBasis(float flexBasis) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, flexBasis); - } - - @Override - public void setFlexBasisPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, percent); - } - - @Override - public void setFlexBasisAuto() { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); - } - - @Override - public void setMargin(YogaEdge edge, float margin) { - mEdgeSetFlag |= MARGIN; - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), margin); - } - - @Override - public void setMarginPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= MARGIN; - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), percent); - } - - @Override - public void setMarginAuto(YogaEdge edge) { - mEdgeSetFlag |= MARGIN; - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); - } - - @Override - public void setPadding(YogaEdge edge, float padding) { - mEdgeSetFlag |= PADDING; - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); - } - - @Override - public void setPaddingPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= PADDING; - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); - } - - @Override - public void setBorder(YogaEdge edge, float border) { - mEdgeSetFlag |= BORDER; - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleBorderOffset(edge), border); - } - - @Override - public void setPosition(YogaEdge edge, float position) { - mHasSetPosition = true; - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), position); - } - - @Override - public void setPositionPercent(YogaEdge edge, float percent) { - mHasSetPosition = true; - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), percent); - } - - @Override - public void setWidth(float width) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, width); - } - - @Override - public void setWidthPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, percent); - } - - @Override - public void setWidthAuto() { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); - } - - @Override - public void setHeight(float height) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, height); - } - - @Override - public void setHeightPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, percent); - } - - @Override - public void setHeightAuto() { - YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); - } - - @Override - public void setMinWidth(float minWidth) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, minWidth); - } - - @Override - public void setMinWidthPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, percent); - } - - @Override - public void setMinHeight(float minHeight) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, minHeight); - } - - @Override - public void setMinHeightPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, percent); - } - - @Override - public void setMaxWidth(float maxWidth) { - YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, maxWidth); - } - - @Override - public void setMaxWidthPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, percent); - } - - @Override - public void setMaxHeight(float maxHeight) { - YogaNodeMemoryLayout.putPointValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, maxHeight); - } - - @Override - public void setMaxHeightPercent(float percent) { - YogaNodeMemoryLayout.putPercentValue( - mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, percent); - } - - @Override - public void setAspectRatio(float aspectRatio) { - YogaNodeMemoryLayout.putOptional( - mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); - } - - @Override - public YogaNodeProperties clone(YogaNode node) { - YogaNodePropertiesHybrid clone = (YogaNodePropertiesHybrid) super.clone(node); - clone.mStyleBuffer = - jni_getStyleBuffer(clone.getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); - return clone; - } -} diff --git a/java/com/facebook/yoga/YogaNodePropertiesJNI.java b/java/com/facebook/yoga/YogaNodePropertiesJNI.java deleted file mode 100644 index 2322193c..00000000 --- a/java/com/facebook/yoga/YogaNodePropertiesJNI.java +++ /dev/null @@ -1,704 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ -package com.facebook.yoga; - -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.soloader.SoLoader; - -@DoNotStrip -public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { - - static { - SoLoader.loadLibrary("yoga"); - } - - private long mNativePointer; - - /* Those flags needs be in sync with YGJNI.cpp */ - protected static final int MARGIN = 1; - protected static final int PADDING = 2; - protected static final int BORDER = 4; - - @DoNotStrip protected int mEdgeSetFlag = 0; - - protected boolean mHasSetPosition = false; - - @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; - - private native long jni_YGNodeNew(YogaNode node); - - public YogaNodePropertiesJNI(YogaNode node) { - mNativePointer = jni_YGNodeNew(node); - if (mNativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } - } - - private native long jni_YGNodeNewWithConfig(YogaNode node, long configPointer); - - public YogaNodePropertiesJNI(YogaNode node, YogaConfig config) { - mNativePointer = jni_YGNodeNewWithConfig(node, config.mNativePointer); - if (mNativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } - } - - private static native void jni_YGNodeFree(long nativePointer); - - @Override - public void freeNatives() { - long nativePointer = mNativePointer; - mNativePointer = 0; - jni_YGNodeFree(nativePointer); - } - - @Override - protected void finalize() throws Throwable { - try { - freeNatives(); - } finally { - super.finalize(); - } - } - - private static native long jni_YGNodeClone( - long nativePointer, YogaNode newNode, YogaNodePropertiesJNI newProps); - - @Override - public YogaNodeProperties clone(YogaNode node) { - try { - YogaNodePropertiesJNI clonedProperties = (YogaNodePropertiesJNI) clone(); - clonedProperties.mNativePointer = jni_YGNodeClone(getNativePointer(), node, clonedProperties); - return clonedProperties; - } catch (CloneNotSupportedException ex) { - // This class implements Cloneable, this should not happen - throw new RuntimeException(ex); - } - } - - @Override - public long getNativePointer() { - return mNativePointer; - } - - private static native void jni_YGTransferLayoutOutputsRecursive(long nativePointer); - - @Override - public void onAfterCalculateLayout(boolean hasNewLayoutIgnoredSetByNative) { - jni_YGTransferLayoutOutputsRecursive(mNativePointer); - } - - private native void jni_YGNodeReset(long nativePointer); - - @Override - public void reset() { - mHasSetPosition = false; - mEdgeSetFlag = 0; - mHasNewLayout = true; - mDoesLegacyStretchFlagAffectsLayout = false; - - 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; - jni_YGNodeReset(getNativePointer()); - } - - @Override - public boolean hasNewLayout() { - return mHasNewLayout; - } - - private native boolean jni_YGNodeIsDirty(long nativePointer); - - @Override - public boolean isDirty() { - return jni_YGNodeIsDirty(mNativePointer); - } - - @Override - public void markLayoutSeen() { - mHasNewLayout = false; - } - - private native int jni_YGNodeStyleGetDirection(long nativePointer); - - @Override - public YogaDirection getStyleDirection() { - return YogaDirection.fromInt(jni_YGNodeStyleGetDirection(mNativePointer)); - } - - private native void jni_YGNodeStyleSetDirection(long nativePointer, int direction); - - @Override - public void setDirection(YogaDirection direction) { - jni_YGNodeStyleSetDirection(mNativePointer, direction.intValue()); - } - - private native int jni_YGNodeStyleGetFlexDirection(long nativePointer); - - @Override - public YogaFlexDirection getFlexDirection() { - return YogaFlexDirection.fromInt(jni_YGNodeStyleGetFlexDirection(mNativePointer)); - } - - private native void jni_YGNodeStyleSetFlexDirection(long nativePointer, int flexDirection); - - @Override - public void setFlexDirection(YogaFlexDirection flexDirection) { - jni_YGNodeStyleSetFlexDirection(mNativePointer, flexDirection.intValue()); - } - - private native int jni_YGNodeStyleGetJustifyContent(long nativePointer); - - @Override - public YogaJustify getJustifyContent() { - return YogaJustify.fromInt(jni_YGNodeStyleGetJustifyContent(mNativePointer)); - } - - private native void jni_YGNodeStyleSetJustifyContent(long nativePointer, int justifyContent); - - @Override - public void setJustifyContent(YogaJustify justifyContent) { - jni_YGNodeStyleSetJustifyContent(mNativePointer, justifyContent.intValue()); - } - - private native int jni_YGNodeStyleGetAlignItems(long nativePointer); - - @Override - public YogaAlign getAlignItems() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignItems(mNativePointer)); - } - - private native void jni_YGNodeStyleSetAlignItems(long nativePointer, int alignItems); - - @Override - public void setAlignItems(YogaAlign alignItems) { - jni_YGNodeStyleSetAlignItems(mNativePointer, alignItems.intValue()); - } - - private native int jni_YGNodeStyleGetAlignSelf(long nativePointer); - - @Override - public YogaAlign getAlignSelf() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignSelf(mNativePointer)); - } - - private native void jni_YGNodeStyleSetAlignSelf(long nativePointer, int alignSelf); - - @Override - public void setAlignSelf(YogaAlign alignSelf) { - jni_YGNodeStyleSetAlignSelf(mNativePointer, alignSelf.intValue()); - } - - private native int jni_YGNodeStyleGetAlignContent(long nativePointer); - - @Override - public YogaAlign getAlignContent() { - return YogaAlign.fromInt(jni_YGNodeStyleGetAlignContent(mNativePointer)); - } - - private native void jni_YGNodeStyleSetAlignContent(long nativePointer, int alignContent); - - @Override - public void setAlignContent(YogaAlign alignContent) { - jni_YGNodeStyleSetAlignContent(mNativePointer, alignContent.intValue()); - } - - private native int jni_YGNodeStyleGetPositionType(long nativePointer); - - @Override - public YogaPositionType getPositionType() { - return YogaPositionType.fromInt(jni_YGNodeStyleGetPositionType(mNativePointer)); - } - - private native void jni_YGNodeStyleSetPositionType(long nativePointer, int positionType); - - @Override - public void setPositionType(YogaPositionType positionType) { - jni_YGNodeStyleSetPositionType(mNativePointer, positionType.intValue()); - } - - private native void jni_YGNodeStyleSetFlexWrap(long nativePointer, int wrapType); - - @Override - public void setWrap(YogaWrap flexWrap) { - jni_YGNodeStyleSetFlexWrap(mNativePointer, flexWrap.intValue()); - } - - private native int jni_YGNodeStyleGetOverflow(long nativePointer); - - @Override - public YogaOverflow getOverflow() { - return YogaOverflow.fromInt(jni_YGNodeStyleGetOverflow(mNativePointer)); - } - - private native void jni_YGNodeStyleSetOverflow(long nativePointer, int overflow); - - @Override - public void setOverflow(YogaOverflow overflow) { - jni_YGNodeStyleSetOverflow(mNativePointer, overflow.intValue()); - } - - private native int jni_YGNodeStyleGetDisplay(long nativePointer); - - @Override - public YogaDisplay getDisplay() { - return YogaDisplay.fromInt(jni_YGNodeStyleGetDisplay(mNativePointer)); - } - - private native void jni_YGNodeStyleSetDisplay(long nativePointer, int display); - - @Override - public void setDisplay(YogaDisplay display) { - jni_YGNodeStyleSetDisplay(mNativePointer, display.intValue()); - } - - private native void jni_YGNodeStyleSetFlex(long nativePointer, float flex); - - @Override - public void setFlex(float flex) { - jni_YGNodeStyleSetFlex(mNativePointer, flex); - } - - private native float jni_YGNodeStyleGetFlexGrow(long nativePointer); - - @Override - public float getFlexGrow() { - return jni_YGNodeStyleGetFlexGrow(mNativePointer); - } - - private native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); - - @Override - public void setFlexGrow(float flexGrow) { - jni_YGNodeStyleSetFlexGrow(mNativePointer, flexGrow); - } - - private native float jni_YGNodeStyleGetFlexShrink(long nativePointer); - - @Override - public float getFlexShrink() { - return jni_YGNodeStyleGetFlexShrink(mNativePointer); - } - - private native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); - - @Override - public void setFlexShrink(float flexShrink) { - jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); - } - - private native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); - - @Override - public YogaValue getFlexBasis() { - return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); - } - - private native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); - - @Override - public void setFlexBasis(float flexBasis) { - jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); - } - - private native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); - - @Override - public void setFlexBasisPercent(float percent) { - jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); - } - - private native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); - - @Override - public void setFlexBasisAuto() { - jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); - } - - private native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); - - @Override - public YogaValue getMargin(YogaEdge edge) { - if (!((mEdgeSetFlag & MARGIN) == MARGIN)) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); - } - - private native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); - - @Override - public void setMargin(YogaEdge edge, float margin) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); - } - - private native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); - - @Override - public void setMarginPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); - } - - private native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); - - @Override - public void setMarginAuto(YogaEdge edge) { - mEdgeSetFlag |= MARGIN; - jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); - } - - private native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); - - @Override - public YogaValue getPadding(YogaEdge edge) { - if (!((mEdgeSetFlag & PADDING) == PADDING)) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); - } - - private native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); - - @Override - public void setPadding(YogaEdge edge, float padding) { - mEdgeSetFlag |= PADDING; - jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); - } - - private native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); - - @Override - public void setPaddingPercent(YogaEdge edge, float percent) { - mEdgeSetFlag |= PADDING; - jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); - } - - private native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); - - @Override - public float getBorder(YogaEdge edge) { - if (!((mEdgeSetFlag & BORDER) == BORDER)) { - return YogaConstants.UNDEFINED; - } - return jni_YGNodeStyleGetBorder(mNativePointer, edge.intValue()); - } - - private native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); - - @Override - public void setBorder(YogaEdge edge, float border) { - mEdgeSetFlag |= BORDER; - jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); - } - - private native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); - - @Override - public YogaValue getPosition(YogaEdge edge) { - if (!mHasSetPosition) { - return YogaValue.UNDEFINED; - } - return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); - } - - private native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); - - @Override - public void setPosition(YogaEdge edge, float position) { - mHasSetPosition = true; - jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); - } - - private native void jni_YGNodeStyleSetPositionPercent( - long nativePointer, int edge, float percent); - - @Override - public void setPositionPercent(YogaEdge edge, float percent) { - mHasSetPosition = true; - jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); - } - - private native Object jni_YGNodeStyleGetWidth(long nativePointer); - - @Override - public YogaValue getWidth() { - return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); - } - - private native void jni_YGNodeStyleSetWidth(long nativePointer, float width); - - @Override - public void setWidth(float width) { - jni_YGNodeStyleSetWidth(mNativePointer, width); - } - - private native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); - - @Override - public void setWidthPercent(float percent) { - jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); - } - - private native void jni_YGNodeStyleSetWidthAuto(long nativePointer); - - @Override - public void setWidthAuto() { - jni_YGNodeStyleSetWidthAuto(mNativePointer); - } - - private native Object jni_YGNodeStyleGetHeight(long nativePointer); - - @Override - public YogaValue getHeight() { - return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); - } - - private native void jni_YGNodeStyleSetHeight(long nativePointer, float height); - - @Override - public void setHeight(float height) { - jni_YGNodeStyleSetHeight(mNativePointer, height); - } - - private native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); - - @Override - public void setHeightPercent(float percent) { - jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); - } - - private native void jni_YGNodeStyleSetHeightAuto(long nativePointer); - - @Override - public void setHeightAuto() { - jni_YGNodeStyleSetHeightAuto(mNativePointer); - } - - private native Object jni_YGNodeStyleGetMinWidth(long nativePointer); - - @Override - public YogaValue getMinWidth() { - return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); - } - - private native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); - - @Override - public void setMinWidth(float minWidth) { - jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); - } - - private native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); - - @Override - public void setMinWidthPercent(float percent) { - jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); - } - - private native Object jni_YGNodeStyleGetMinHeight(long nativePointer); - - @Override - public YogaValue getMinHeight() { - return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); - } - - private native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); - - @Override - public void setMinHeight(float minHeight) { - jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); - } - - private native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); - - @Override - public void setMinHeightPercent(float percent) { - jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); - } - - private native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); - - @Override - public YogaValue getMaxWidth() { - return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); - } - - private native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); - - @Override - public void setMaxWidth(float maxWidth) { - jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); - } - - private native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); - - @Override - public void setMaxWidthPercent(float percent) { - jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); - } - - private native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); - - @Override - public YogaValue getMaxHeight() { - return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); - } - - private native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); - - @Override - public void setMaxHeight(float maxheight) { - jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); - } - - private native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); - - @Override - public void setMaxHeightPercent(float percent) { - jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); - } - - private native float jni_YGNodeStyleGetAspectRatio(long nativePointer); - - @Override - public float getAspectRatio() { - return jni_YGNodeStyleGetAspectRatio(mNativePointer); - } - - private native void jni_YGNodeStyleSetAspectRatio(long nativePointer, float aspectRatio); - - @Override - public void setAspectRatio(float aspectRatio) { - jni_YGNodeStyleSetAspectRatio(mNativePointer, aspectRatio); - } - - @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); - } -} diff --git a/java/com/facebook/yoga/YogaNodePropertiesUnsafe.java b/java/com/facebook/yoga/YogaNodePropertiesUnsafe.java deleted file mode 100644 index f8af890b..00000000 --- a/java/com/facebook/yoga/YogaNodePropertiesUnsafe.java +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ -package com.facebook.yoga; - -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.soloader.SoLoader; -import java.lang.reflect.Field; -import sun.misc.Unsafe; - -@DoNotStrip -public class YogaNodePropertiesUnsafe implements YogaNodeProperties { - - private static final int TRUE_BITS = 0x01000001; - private static final int FLOAT_SIZE = 4; - private static final int AUTO = YogaUnit.AUTO.intValue(); - private static final int POINT = YogaUnit.POINT.intValue(); - private static final int PERCENT = YogaUnit.PERCENT.intValue(); - private static final int UNDEFINED = YogaUnit.UNDEFINED.intValue(); - private static final int RTL = YogaDirection.RTL.intValue(); - private static final Unsafe UNSAFE; - - private final long mNativePointer; - private final long mStyleNativePointer; - private final long mLayoutNativePointer; - private boolean mHasBorderSet = false; - private boolean mHasNewLayout = true; - private boolean mIsFreed = false; - - static { - SoLoader.loadLibrary("yoga"); - Field instanceField = null; - try { - instanceField = Unsafe.class.getDeclaredField("theUnsafe"); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - instanceField.setAccessible(true); - try { - UNSAFE = (Unsafe) instanceField.get(null); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - private static native long jni_YGNodeNewNoProps(YogaNode node); - private static native long jni_YGNodeNewNoPropsWithConfig(YogaNode node, long configPointer); - private static native long jni_YGNodeStylePointer(long nativePointer); - private static native long jni_YGNodeLayoutPointer(long nativePointer); - - public YogaNodePropertiesUnsafe(YogaNode node) { - this(jni_YGNodeNewNoProps(node)); - } - - public YogaNodePropertiesUnsafe(YogaNode node, YogaConfig config) { - this(jni_YGNodeNewNoPropsWithConfig(node, config.mNativePointer)); - } - - public YogaNodePropertiesUnsafe(long nativePointer) { - mNativePointer = nativePointer; - mStyleNativePointer = jni_YGNodeStylePointer(nativePointer); - mLayoutNativePointer = jni_YGNodeLayoutPointer(nativePointer); - } - - private static native long jni_YGNodeCloneNoProps(long nativePointer, YogaNode newNode); - - @Override - public YogaNodeProperties clone(YogaNode node) { - long clonedNativePointer = jni_YGNodeCloneNoProps(getNativePointer(), node); - YogaNodePropertiesUnsafe clone = - new YogaNodePropertiesUnsafe(clonedNativePointer); - clone.mHasBorderSet = mHasBorderSet; - clone.mHasNewLayout = mHasNewLayout; - return clone; - } - - @Override - public long getNativePointer() { - return mNativePointer; - } - - @Override - public void onAfterCalculateLayout(boolean hasNewLayout) { - mHasNewLayout = hasNewLayout; - } - - private static native void jni_YGNodeReset(long nativePointer); - - @Override - public void reset() { - mHasNewLayout = true; - jni_YGNodeReset(getNativePointer()); - } - - @Override - public boolean hasNewLayout() { - return mHasNewLayout; - } - - private static native boolean jni_YGNodeIsDirty(long nativePointer); - - @Override - public boolean isDirty() { - return jni_YGNodeIsDirty(mNativePointer); - } - - @Override - public void markLayoutSeen() { - mHasNewLayout = false; - } - - @Override - public YogaDirection getStyleDirection() { - return YogaDirection.fromInt(getStyleInt(YogaNodeMemoryLayout.styleDirection)); - } - - @Override - public void setDirection(YogaDirection direction) { - putStyleInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); - } - - @Override - public YogaFlexDirection getFlexDirection() { - return YogaFlexDirection.fromInt(getStyleInt(YogaNodeMemoryLayout.styleFlexDirection)); - } - - @Override - public void setFlexDirection(YogaFlexDirection flexDirection) { - putStyleInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); - } - - @Override - public YogaJustify getJustifyContent() { - return YogaJustify.fromInt(getStyleInt(YogaNodeMemoryLayout.styleJustifyContent)); - } - - @Override - public void setJustifyContent(YogaJustify justifyContent) { - putStyleInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); - } - - @Override - public YogaAlign getAlignItems() { - return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignItems)); - } - - @Override - public void setAlignItems(YogaAlign alignItems) { - putStyleInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); - } - - @Override - public YogaAlign getAlignSelf() { - return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignSelf)); - } - - @Override - public void setAlignSelf(YogaAlign alignSelf) { - putStyleInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); - } - - @Override - public YogaAlign getAlignContent() { - return YogaAlign.fromInt(getStyleInt(YogaNodeMemoryLayout.styleAlignContent)); - } - - @Override - public void setAlignContent(YogaAlign alignContent) { - putStyleInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); - } - - @Override - public YogaPositionType getPositionType() { - return YogaPositionType.fromInt(getStyleInt(YogaNodeMemoryLayout.stylePositionType)); - } - - @Override - public void setPositionType(YogaPositionType positionType) { - putStyleInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); - } - - @Override - public void setWrap(YogaWrap flexWrap) { - putStyleInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); - } - - @Override - public YogaOverflow getOverflow() { - return YogaOverflow.fromInt(getStyleInt(YogaNodeMemoryLayout.styleOverflow)); - } - - @Override - public void setOverflow(YogaOverflow overflow) { - putStyleInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); - } - - @Override - public YogaDisplay getDisplay() { - return YogaDisplay.fromInt(getStyleInt(YogaNodeMemoryLayout.styleDisplay)); - } - - @Override - public void setDisplay(YogaDisplay display) { - putStyleInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); - } - - @Override - public void setFlex(float flex) { - putStyleOptional(YogaNodeMemoryLayout.styleFlex, flex); - } - - @Override - public float getFlexGrow() { - return getStyleFloat(YogaNodeMemoryLayout.styleFlexGrow); - } - - @Override - public void setFlexGrow(float flexGrow) { - putStyleOptional(YogaNodeMemoryLayout.styleFlexGrow, flexGrow); - } - - @Override - public float getFlexShrink() { - return getStyleFloat(YogaNodeMemoryLayout.styleFlexShrink); - } - - @Override - public void setFlexShrink(float flexShrink) { - putStyleOptional(YogaNodeMemoryLayout.styleFlexShrink, flexShrink); - } - - @Override - public YogaValue getFlexBasis() { - return getStyleValue(YogaNodeMemoryLayout.styleFlexBasis); - } - - @Override - public void setFlexBasis(float flexBasis) { - putStylePoints(YogaNodeMemoryLayout.styleFlexBasis, flexBasis); - } - - @Override - public void setFlexBasisPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleFlexBasis, percent); - } - - @Override - public void setFlexBasisAuto() { - putStyleAuto(YogaNodeMemoryLayout.styleFlexBasis); - } - - @Override - public YogaValue getMargin(YogaEdge edge) { - return getStyleValue(YogaNodeMemoryLayout.styleMarginOffset(edge)); - } - - @Override - public void setMargin(YogaEdge edge, float margin) { - putStylePoints(YogaNodeMemoryLayout.styleMarginOffset(edge), margin); - } - - @Override - public void setMarginPercent(YogaEdge edge, float percent) { - putStylePercent(YogaNodeMemoryLayout.styleMarginOffset(edge), percent); - } - - @Override - public void setMarginAuto(YogaEdge edge) { - putStyleAuto(YogaNodeMemoryLayout.styleMarginOffset(edge)); - } - - @Override - public YogaValue getPadding(YogaEdge edge) { - return getStyleValue(YogaNodeMemoryLayout.stylePaddingOffset(edge)); - } - - @Override - public void setPadding(YogaEdge edge, float padding) { - putStylePoints(YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); - } - - @Override - public void setPaddingPercent(YogaEdge edge, float percent) { - putStylePercent(YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); - } - - @Override - public float getBorder(YogaEdge edge) { - return mHasBorderSet - ? getStyleFloat(YogaNodeMemoryLayout.styleBorderOffset(edge)) - : YogaConstants.UNDEFINED; - } - - @Override - public void setBorder(YogaEdge edge, float border) { - mHasBorderSet = true; - putStylePoints(YogaNodeMemoryLayout.styleBorderOffset(edge), border); - } - - @Override - public YogaValue getPosition(YogaEdge edge) { - return getStyleValue(YogaNodeMemoryLayout.stylePositionOffset(edge)); - } - - @Override - public void setPosition(YogaEdge edge, float position) { - putStylePoints(YogaNodeMemoryLayout.stylePositionOffset(edge), position); - } - - @Override - public void setPositionPercent(YogaEdge edge, float percent) { - putStylePercent(YogaNodeMemoryLayout.stylePositionOffset(edge), percent); - } - - @Override - public YogaValue getWidth() { - return getStyleValue(YogaNodeMemoryLayout.styleWidth); - } - - @Override - public void setWidth(float width) { - putStylePoints(YogaNodeMemoryLayout.styleWidth, width); - } - - @Override - public void setWidthPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleWidth, percent); - } - - @Override - public void setWidthAuto() { - putStyleAuto(YogaNodeMemoryLayout.styleWidth); - } - - @Override - public YogaValue getHeight() { - return getStyleValue(YogaNodeMemoryLayout.styleHeight); - } - - @Override - public void setHeight(float height) { - putStylePoints(YogaNodeMemoryLayout.styleHeight, height); - } - - @Override - public void setHeightPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleHeight, percent); - } - - @Override - public void setHeightAuto() { - putStyleAuto(YogaNodeMemoryLayout.styleHeight); - } - - @Override - public YogaValue getMinWidth() { - return getStyleValue(YogaNodeMemoryLayout.styleMinWidth); - } - - @Override - public void setMinWidth(float minWidth) { - putStylePoints(YogaNodeMemoryLayout.styleMinWidth, minWidth); - } - - @Override - public void setMinWidthPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleMinWidth, percent); - } - - @Override - public YogaValue getMinHeight() { - return getStyleValue(YogaNodeMemoryLayout.styleMinHeight); - } - - @Override - public void setMinHeight(float minHeight) { - putStylePoints(YogaNodeMemoryLayout.styleMinHeight, minHeight); - } - - @Override - public void setMinHeightPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleMinHeight, percent); - } - - @Override - public YogaValue getMaxWidth() { - return getStyleValue(YogaNodeMemoryLayout.styleMaxWidth); - } - - @Override - public void setMaxWidth(float maxWidth) { - putStylePoints(YogaNodeMemoryLayout.styleMaxWidth, maxWidth); - } - - @Override - public void setMaxWidthPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleMaxWidth, percent); - } - - @Override - public YogaValue getMaxHeight() { - return getStyleValue(YogaNodeMemoryLayout.styleMaxHeight); - } - - @Override - public void setMaxHeight(float maxHeight) { - putStylePoints(YogaNodeMemoryLayout.styleMaxHeight, maxHeight); - } - - @Override - public void setMaxHeightPercent(float percent) { - putStylePercent(YogaNodeMemoryLayout.styleMaxHeight, percent); - } - - @Override - public float getAspectRatio() { - return getStyleOptional(YogaNodeMemoryLayout.styleAspectRatio); - } - - @Override - public void setAspectRatio(float aspectRatio) { - putStyleOptional(YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); - } - - @Override - public float getLayoutX() { - return getLayoutFloat(YogaNodeMemoryLayout.layoutX); - } - - @Override - public float getLayoutY() { - return getLayoutFloat(YogaNodeMemoryLayout.layoutY); - } - - @Override - public float getLayoutWidth() { - return getLayoutFloat(YogaNodeMemoryLayout.layoutWidth); - } - - @Override - public float getLayoutHeight() { - return getLayoutFloat(YogaNodeMemoryLayout.layoutHeight); - } - - @Override - public boolean getDoesLegacyStretchFlagAffectsLayout() { - return getBool(mLayoutNativePointer + YogaNodeMemoryLayout.layoutDoesLegacyStretchFlagAffectsLayout); - } - - @Override - public float getLayoutMargin(YogaEdge edge) { - return getLayoutFloat(YogaNodeMemoryLayout.layoutMarginOffset(layoutEdge(edge))); - } - - @Override - public float getLayoutPadding(YogaEdge edge) { - return getLayoutFloat(YogaNodeMemoryLayout.layoutPaddingOffset(layoutEdge(edge))); - } - - @Override - public float getLayoutBorder(YogaEdge edge) { - return getLayoutFloat(YogaNodeMemoryLayout.layoutBorderOffset(layoutEdge(edge))); - } - - @Override - public YogaDirection getLayoutDirection() { - return YogaDirection.fromInt(getLayoutDirectionInt()); - } - - private static native void jni_YGNodeFree(long nativePointer); - - @Override - public void freeNatives() { - if (!mIsFreed) { - mIsFreed = true; - jni_YGNodeFree(mNativePointer); - } - } - - private int getLayoutDirectionInt() { - return UNSAFE.getInt(null, mLayoutNativePointer + YogaNodeMemoryLayout.layoutDirection); - } - - private YogaEdge layoutEdge(YogaEdge edge) { - int layoutDirection = getLayoutDirectionInt(); - switch (edge) { - case LEFT: - return layoutDirection == RTL ? YogaEdge.END : YogaEdge.START; - case RIGHT: - return layoutDirection == RTL ? YogaEdge.START : YogaEdge.END; - case TOP: - case BOTTOM: - case START: - case END: - return edge; - default: - throw new IllegalArgumentException("Cannot get layout properties of multi-edge shorthands"); - } - } - - private int getStyleInt(int offset) { - return UNSAFE.getInt(null, mStyleNativePointer + offset); - } - - private void putStyleInt(int offset, int value) { - UNSAFE.putInt(null, mStyleNativePointer + offset, value); - } - - private float getStyleFloat(int offset) { - return getFloat(mStyleNativePointer + offset); - } - - private void putStyleFloat(int offset, float value) { - putFloat(mStyleNativePointer + offset, value); - } - - private void putStylePoints(int offset, float value) { - putStyleValue(offset, value, POINT); - } - - private void putStylePercent(int offset, float value) { - putStyleValue(offset, value, PERCENT); - } - - private void putStyleAuto(int offset) { - putStyleValue(offset, 0, AUTO); - } - - private void putStyleValue(int offset, float value, int unit) { - if (YogaConstants.isUndefined(value)) { - value = YogaConstants.UNDEFINED; - unit = UNDEFINED; - } - putStyleFloat(offset, value); - putStyleInt(offset + FLOAT_SIZE, unit); - } - - private YogaValue getStyleValue(int offset) { - float value = getStyleFloat(offset); - int unit = getStyleInt(offset + FLOAT_SIZE); - return new YogaValue(value, YogaUnit.fromInt(unit)); - } - - private void putStyleOptional(int offset, float value) { - int isUndefinedBits = YogaConstants.isUndefined(value) ? TRUE_BITS : 0; - putStyleFloat(offset, value); - putStyleInt(offset + FLOAT_SIZE, isUndefinedBits); - } - - private float getStyleOptional(int offset) { - boolean isUndefined = getBool(mStyleNativePointer + offset + FLOAT_SIZE); - return isUndefined - ? YogaConstants.UNDEFINED - : getStyleFloat(offset); - } - - private float getLayoutFloat(int offset) { - return getFloat(mLayoutNativePointer + offset); - } - - private static float getFloat(long offset) { - int intBits = UNSAFE.getInt(null, offset); - return Float.intBitsToFloat(intBits); - } - - private static void putFloat(long offset, float value) { - int intBits = Float.floatToRawIntBits(value); - UNSAFE.putInt(null, offset, intBits); - } - - private static boolean getBool(long offset) { - // assumes little endian - return (UNSAFE.getInt(null, offset) & 0xFF) != 0; - } - -} diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 482c14ae..6233cc23 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -6,7 +6,6 @@ * */ #include -#include #include #include #include @@ -22,23 +21,6 @@ struct JYogaConfig : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaConfig;"; }; -struct JYogaNodePropertiesJNI : public JavaClass { - static constexpr auto kJavaDescriptor = - "Lcom/facebook/yoga/YogaNodePropertiesJNI;"; -}; - -struct JYogaNodePropertiesByteBuffer - : public JavaClass { - static constexpr auto kJavaDescriptor = - "Lcom/facebook/yoga/YogaNodePropertiesByteBuffer"; -}; - -struct JYogaNodePropertiesHybrid - : public JavaClass { - static constexpr auto kJavaDescriptor = - "Lcom/facebook/yoga/YogaNodePropertiesHybrid"; -}; - struct YGConfigContext { global_ref* logger; global_ref* config; @@ -51,34 +33,16 @@ struct YGConfigContext { } }; -struct JNINodeContext { - weak_ref node; - weak_ref props; -}; - static inline weak_ref* YGNodeJobject(YGNodeRef node) { - return &reinterpret_cast(node->getContext())->node; -} - -static inline weak_ref* YGNodePropsJObject( - YGNodeRef node) { - return &reinterpret_cast(node->getContext())->props; -} - -static inline void setNodeContext( - YGNodeRef node, - alias_ref javaNode, - alias_ref javaNodeProps) { - node->setContext( - new JNINodeContext{make_weak(javaNode), make_weak(javaNodeProps)}); + return reinterpret_cast*>(node->getContext()); } static void YGTransferLayoutDirection( YGNodeRef node, - alias_ref javaProps) { + alias_ref javaNode) { static auto layoutDirectionField = - javaProps->getClass()->getField("mLayoutDirection"); - javaProps->setFieldValue( + javaNode->getClass()->getField("mLayoutDirection"); + javaNode->setFieldValue( layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); } @@ -86,7 +50,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { if (!root->getHasNewLayout()) { return; } - auto obj = YGNodePropsJObject(root)->lockLocal(); + auto obj = YGNodeJobject(root)->lockLocal(); if (!obj) { YGLog( root, @@ -259,9 +223,7 @@ static YGSize YGJNIMeasureFunc( findClassStatic("com/facebook/yoga/YogaNode") ->getMethod("measure"); - if (auto jProps = YGNodePropsJObject(node)->lockLocal()) { - YGTransferLayoutDirection(node, jProps); - } + YGTransferLayoutDirection(node, obj); const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); @@ -325,36 +287,22 @@ static int YGJNILogFunc( return result; } -jlong jni_YGNodeNew( - alias_ref javaProps, - alias_ref javaNode) { +jlong jni_YGNodeNew(alias_ref thiz) { const YGNodeRef node = YGNodeNew(); - setNodeContext(node, javaNode, javaProps); + node->setContext(new weak_ref(make_weak(thiz))); + // YGNodeSetContext(node, new weak_ref(make_weak(thiz))); node->setPrintFunc(YGPrint); + // YGNodeSetPrintFunc(node, YGPrint); return reinterpret_cast(node); } -jlong jni_YGNodeNewWithConfig( - alias_ref javaProps, - alias_ref javaNode, - jlong configPointer) { +jlong jni_YGNodeNewWithConfig(alias_ref thiz, jlong configPointer) { const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer)); - setNodeContext(node, javaNode, javaProps); + node->setContext(new weak_ref(make_weak(thiz))); node->setPrintFunc(YGPrint); return reinterpret_cast(node); } -jlong jni_YGNodeNewNoProps(alias_ref, alias_ref javaNode) { - return jni_YGNodeNew(nullptr, javaNode); -} - -jlong jni_YGNodeNewNoPropsWithConfig( - alias_ref, - alias_ref javaNode, - jlong configPointer) { - return jni_YGNodeNewWithConfig(nullptr, javaNode, configPointer); -} - void jni_YGNodeSetOwner( alias_ref thiz, jlong nativePointer, @@ -366,28 +314,21 @@ void jni_YGNodeSetOwner( } jlong jni_YGNodeClone( - alias_ref, + alias_ref thiz, jlong nativePointer, - alias_ref clonedJavaObject, - alias_ref clonedJavaProps) { + alias_ref clonedJavaObject) { const YGNodeRef clonedYogaNode = YGNodeClone(_jlong2YGNodeRef(nativePointer)); - setNodeContext(clonedYogaNode, clonedJavaObject, clonedJavaProps); + clonedYogaNode->setContext( + new weak_ref(make_weak(clonedJavaObject))); return reinterpret_cast(clonedYogaNode); } -jlong jni_YGNodeCloneNoProps( - alias_ref cls, - jlong nativePointer, - alias_ref clonedJavaObject) { - return jni_YGNodeClone(cls, nativePointer, clonedJavaObject, nullptr); -} - -void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { +void jni_YGNodeFree(alias_ref, jlong nativePointer) { if (nativePointer == 0) { return; } const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - delete reinterpret_cast(node->getContext()); + delete YGNodeJobject(node); YGNodeFree(node); } @@ -438,7 +379,7 @@ void jni_YGNodeRemoveChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } -jboolean jni_YGNodeCalculateLayout( +void jni_YGNodeCalculateLayout( alias_ref, jlong nativePointer, jfloat width, @@ -449,13 +390,6 @@ jboolean jni_YGNodeCalculateLayout( static_cast(width), static_cast(height), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); - return root->getHasNewLayout(); -} - -static void jni_YGTransferLayoutOutputsRecursive( - alias_ref, - jlong nativePointer) { - const YGNodeRef root = _jlong2YGNodeRef(nativePointer); YGTransferLayoutOutputsRecursive(root); } @@ -729,43 +663,29 @@ void jni_YGConfigSetLogger( jint jni_YGNodeGetInstanceCount(alias_ref clazz) { return YGNodeGetInstanceCount(); } -local_ref jni_getStyleBuffer( - alias_ref, - jlong nativePointer) { - YGStyle* style = &_jlong2YGNodeRef(nativePointer)->getStyle(); - return JByteBuffer::wrapBytes( - reinterpret_cast(style), sizeof(YGStyle)); -} - -local_ref jni_getLayoutBuffer( - alias_ref, - jlong nativePointer) { - YGLayout* layout = &_jlong2YGNodeRef(nativePointer)->getLayout(); - return JByteBuffer::wrapBytes( - reinterpret_cast(layout), sizeof(YGLayout)); -} - -jlong jni_YGNodeStylePointer(alias_ref, jlong nativePointer) { - return reinterpret_cast(&_jlong2YGNodeRef(nativePointer)->getStyle()); -} - -jlong jni_YGNodeLayoutPointer(alias_ref, jlong nativePointer) { - return reinterpret_cast(&_jlong2YGNodeRef(nativePointer)->getLayout()); -} #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( - "com/facebook/yoga/YogaNodePropertiesJNI", + "com/facebook/yoga/YogaNode", { - YGMakeNativeMethod(jni_YGNodeClone), YGMakeNativeMethod(jni_YGNodeNew), YGMakeNativeMethod(jni_YGNodeNewWithConfig), YGMakeNativeMethod(jni_YGNodeFree), YGMakeNativeMethod(jni_YGNodeReset), + YGMakeNativeMethod(jni_YGNodeClearChildren), + YGMakeNativeMethod(jni_YGNodeInsertChild), + YGMakeNativeMethod(jni_YGNodeInsertSharedChild), + YGMakeNativeMethod(jni_YGNodeRemoveChild), + YGMakeNativeMethod(jni_YGNodeCalculateLayout), + YGMakeNativeMethod(jni_YGNodeMarkDirty), + YGMakeNativeMethod(jni_YGNodeMarkDirtyAndPropogateToDescendants), YGMakeNativeMethod(jni_YGNodeIsDirty), + YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc), + YGMakeNativeMethod(jni_YGNodeSetHasBaselineFunc), + YGMakeNativeMethod(jni_YGNodeCopyStyle), YGMakeNativeMethod(jni_YGNodeStyleGetDirection), YGMakeNativeMethod(jni_YGNodeStyleSetDirection), YGMakeNativeMethod(jni_YGNodeStyleGetFlexDirection), @@ -828,23 +748,9 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetAspectRatio), YGMakeNativeMethod(jni_YGNodeStyleSetAspectRatio), - YGMakeNativeMethod(jni_YGTransferLayoutOutputsRecursive), - }); - registerNatives( - "com/facebook/yoga/YogaNode", - { - YGMakeNativeMethod(jni_YGNodeClearChildren), - YGMakeNativeMethod(jni_YGNodeInsertChild), - YGMakeNativeMethod(jni_YGNodeInsertSharedChild), - YGMakeNativeMethod(jni_YGNodeRemoveChild), - YGMakeNativeMethod(jni_YGNodeCalculateLayout), - YGMakeNativeMethod(jni_YGNodeMarkDirty), - YGMakeNativeMethod(jni_YGNodeMarkDirtyAndPropogateToDescendants), - YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc), - YGMakeNativeMethod(jni_YGNodeSetHasBaselineFunc), - YGMakeNativeMethod(jni_YGNodeCopyStyle), YGMakeNativeMethod(jni_YGNodeGetInstanceCount), YGMakeNativeMethod(jni_YGNodePrint), + YGMakeNativeMethod(jni_YGNodeClone), YGMakeNativeMethod(jni_YGNodeSetOwner), }); registerNatives( @@ -861,34 +767,5 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod( jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), }); - registerNatives( - "com/facebook/yoga/YogaNodePropertiesByteBuffer", - { - YGMakeNativeMethod(jni_YGNodeCloneNoProps), - YGMakeNativeMethod(jni_YGNodeFree), - YGMakeNativeMethod(jni_YGNodeNewNoProps), - YGMakeNativeMethod(jni_YGNodeNewNoPropsWithConfig), - YGMakeNativeMethod(jni_YGNodeReset), - YGMakeNativeMethod(jni_YGNodeIsDirty), - YGMakeNativeMethod(jni_getStyleBuffer), - YGMakeNativeMethod(jni_getLayoutBuffer), - }); - registerNatives( - "com/facebook/yoga/YogaNodePropertiesHybrid", - { - YGMakeNativeMethod(jni_getStyleBuffer), - }); - registerNatives( - "com/facebook/yoga/YogaNodePropertiesUnsafe", - { - YGMakeNativeMethod(jni_YGNodeCloneNoProps), - YGMakeNativeMethod(jni_YGNodeFree), - YGMakeNativeMethod(jni_YGNodeNewNoProps), - YGMakeNativeMethod(jni_YGNodeNewNoPropsWithConfig), - YGMakeNativeMethod(jni_YGNodeStylePointer), - YGMakeNativeMethod(jni_YGNodeLayoutPointer), - YGMakeNativeMethod(jni_YGNodeIsDirty), - YGMakeNativeMethod(jni_YGNodeReset), - }); }); } diff --git a/java/stubs/build.gradle b/java/stubs/build.gradle deleted file mode 100644 index f2faa446..00000000 --- a/java/stubs/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -apply plugin: 'java' - -sourceSets { - main { - java { - srcDirs = ['src'] - } - } -} - diff --git a/java/stubs/src/sun/misc/Unsafe.java b/java/stubs/src/sun/misc/Unsafe.java deleted file mode 100644 index 01ff08dc..00000000 --- a/java/stubs/src/sun/misc/Unsafe.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. - * - */ - -package sun.misc; - -/** - * Stub for sun.misc.Unsafe, which is not exposed by the Android SDK. - * - * This only contains the methods and fields we need for Yoga. - */ -public final class Unsafe { - private static final Unsafe theUnsafe = null; - - public final int getInt(Object object, long offset) { - throw new RuntimeException("Stub!"); - } - - public final void putInt(Object object, long offset, int value) { - throw new RuntimeException("Stub!"); - } -} - diff --git a/java/tests/com/facebook/yoga/TestParametrization.java b/java/tests/com/facebook/yoga/TestParametrization.java index 23fe67d1..fdc3ac5d 100644 --- a/java/tests/com/facebook/yoga/TestParametrization.java +++ b/java/tests/com/facebook/yoga/TestParametrization.java @@ -8,74 +8,27 @@ package com.facebook.yoga; import java.util.Arrays; +import java.util.List; public class TestParametrization { public static Iterable nodeFactories() { - return Arrays.asList( - new NodeFactory() { - @Override - public YogaNode create() { - return new YogaNode(); - } + NodeFactory nodeFactory = new NodeFactory() { + @Override + public YogaNode create() { + return new YogaNode(); + } - @Override - public YogaNode create(YogaConfig config) { - return new YogaNode(config); - } + @Override + public YogaNode create(YogaConfig config) { + return new YogaNode(config); + } - @Override - public String toString() { - return "JNI"; - } - }, - new NodeFactory() { - @Override - public YogaNode create() { - return new YogaNode(YogaNode.BYTE_BUFFER); - } - - @Override - public YogaNode create(YogaConfig config) { - return new YogaNode(YogaNode.BYTE_BUFFER, config); - } - - @Override - public String toString() { - return "ByteBuffer"; - } - }, - new NodeFactory() { - @Override - public YogaNode create() { - return new YogaNode(YogaNode.HYBRID); - } - - @Override - public YogaNode create(YogaConfig config) { - return new YogaNode(YogaNode.HYBRID, config); - } - - @Override - public String toString() { - return "Hybrid"; - } - }, - new NodeFactory() { - @Override - public YogaNode create() { - return new YogaNode(YogaNode.UNSAFE); - } - - @Override - public YogaNode create(YogaConfig config) { - return new YogaNode(YogaNode.UNSAFE, config); - } - - @Override - public String toString() { - return "Unsafe"; - } - }); + @Override + public String toString() { + return "JNI"; + } + }; + return Arrays.asList(nodeFactory); } diff --git a/settings.gradle b/settings.gradle index f18ef534..93d836ba 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,5 @@ -include ':yoga', ':yogacore', ':yoga-layout', ':yoga:proguard-annotations', ':yoga:stubs', ':libfb' +include ':yoga', ':yogacore', ':yoga-layout', ':yoga:proguard-annotations', ':libfb' project(':yoga').projectDir = file('java') project(':yoga:proguard-annotations').projectDir = file('java/proguard-annotations') -project(':yoga:stubs').projectDir = file('java/stubs') project(':yoga-layout').projectDir = file('android') project(':libfb').projectDir = file('lib/fb') From b4a889553ce4328e11c7e5a134ef221d18e967e4 Mon Sep 17 00:00:00 2001 From: Amir Livneh Date: Mon, 13 Aug 2018 15:19:36 -0700 Subject: [PATCH 050/189] Fix typo Summary: Fix typo Created from Diffusion's 'Open in Editor' feature. Reviewed By: dshahidehpour Differential Revision: D9295603 fbshipit-source-id: 0a105284592de4962acc672712cca14e157074f4 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 703aa160..74c9d245 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ For testing we rely on [gtest](https://github.com/google/googletest) as a submod For any changes you make you should ensure that all the tests are passing. In case you make any fixes or additions to the library please also add tests for that change to ensure we don't break anything in the future. Tests are located in the `tests` directory. Run the tests by executing `buck test //:yoga`. -Instead of manually writing a test which ensures parity with web implementations of Flexbox you can run `gentest/gentest.rb` to generated a test for you. You can write html which you want to verify in Yoga, in `gentest/fixtures` folder, such as the following. +Instead of manually writing a test which ensures parity with web implementations of Flexbox you can run `gentest/gentest.rb` to generate a test for you. You can write html which you want to verify in Yoga, in `gentest/fixtures` folder, such as the following. ```html

From 45c44d293cdd5746c96d77e2943affa211dcc562 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 15 Aug 2018 06:13:28 -0700 Subject: [PATCH 051/189] Eliminate unnecessary copies of node style objects Summary: @public `YGNode.getStyle()` returns a reference to the enclosed `YGStyle` member. Assigning to a local copies unnecessarily. Having eliminated the copy, we can also safely remove calls to `YGNode.setStyle()`, eliminating another copy. Reviewed By: astreet Differential Revision: D9083336 fbshipit-source-id: df8b603b5cc0b974cf5dd434c71956be4548e583 --- yoga/Yoga.cpp | 81 ++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 59 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index a05ff852..086dda11 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -598,9 +598,7 @@ struct StyleProp { } static void set(YGNodeRef node, T newValue) { if (node->getStyle().*P != newValue) { - YGStyle style = node->getStyle(); - style.*P = newValue; - node->setStyle(style); + node->getStyle().*P = newValue; node->markDirtyAndPropogate(); } } @@ -618,9 +616,7 @@ struct StyleProp { if ((node->getStyle().instanceName.value != value.value && \ value.unit != YGUnitUndefined) || \ node->getStyle().instanceName.unit != value.unit) { \ - YGStyle style = node->getStyle(); \ - style.instanceName = value; \ - node->setStyle(style); \ + node->getStyle().instanceName = value; \ node->markDirtyAndPropogate(); \ } \ } \ @@ -634,10 +630,7 @@ struct StyleProp { if ((node->getStyle().instanceName.value != value.value && \ value.unit != YGUnitUndefined) || \ node->getStyle().instanceName.unit != value.unit) { \ - YGStyle style = node->getStyle(); \ - \ - style.instanceName = value; \ - node->setStyle(style); \ + node->getStyle().instanceName = value; \ node->markDirtyAndPropogate(); \ } \ } @@ -652,9 +645,7 @@ struct StyleProp { if ((node->getStyle().instanceName.value != value.value && \ value.unit != YGUnitUndefined) || \ node->getStyle().instanceName.unit != value.unit) { \ - YGStyle style = node->getStyle(); \ - style.instanceName = value; \ - node->setStyle(style); \ + node->getStyle().instanceName = value; \ node->markDirtyAndPropogate(); \ } \ } \ @@ -663,21 +654,19 @@ struct StyleProp { const YGNodeRef node, const type paramName) { \ if (node->getStyle().instanceName.value != YGFloatSanitize(paramName) || \ node->getStyle().instanceName.unit != YGUnitPercent) { \ - YGStyle style = node->getStyle(); \ + YGStyle& style = node->getStyle(); \ style.instanceName.value = YGFloatSanitize(paramName); \ style.instanceName.unit = \ YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent; \ - node->setStyle(style); \ node->markDirtyAndPropogate(); \ } \ } \ \ void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ if (node->getStyle().instanceName.unit != YGUnitAuto) { \ - YGStyle style = node->getStyle(); \ + YGStyle& style = node->getStyle(); \ style.instanceName.value = 0; \ style.instanceName.unit = YGUnitAuto; \ - node->setStyle(style); \ node->markDirtyAndPropogate(); \ } \ } @@ -710,10 +699,9 @@ struct StyleProp { #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \ void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \ if (node->getStyle().instanceName[edge].unit != YGUnitAuto) { \ - YGStyle style = node->getStyle(); \ + YGStyle& style = node->getStyle(); \ style.instanceName[edge].value = 0; \ style.instanceName[edge].unit = YGUnitAuto; \ - node->setStyle(style); \ node->markDirtyAndPropogate(); \ } \ } @@ -729,9 +717,7 @@ struct StyleProp { if ((node->getStyle().instanceName[edge].value != value.value && \ value.unit != YGUnitUndefined) || \ node->getStyle().instanceName[edge].unit != value.unit) { \ - YGStyle style = node->getStyle(); \ - style.instanceName[edge] = value; \ - node->setStyle(style); \ + node->getStyle().instanceName[edge] = value; \ node->markDirtyAndPropogate(); \ } \ } \ @@ -745,9 +731,7 @@ struct StyleProp { if ((node->getStyle().instanceName[edge].value != value.value && \ value.unit != YGUnitUndefined) || \ node->getStyle().instanceName[edge].unit != value.unit) { \ - YGStyle style = node->getStyle(); \ - style.instanceName[edge] = value; \ - node->setStyle(style); \ + node->getStyle().instanceName[edge] = value; \ node->markDirtyAndPropogate(); \ } \ } \ @@ -875,13 +859,8 @@ YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) { // TODO(T26792433): Change the API to accept YGFloatOptional. void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { if (node->getStyle().flex != flex) { - YGStyle style = node->getStyle(); - if (YGFloatIsUndefined(flex)) { - style.flex = YGFloatOptional(); - } else { - style.flex = YGFloatOptional(flex); - } - node->setStyle(style); + node->getStyle().flex = + YGFloatIsUndefined(flex) ? YGFloatOptional() : YGFloatOptional(flex); node->markDirtyAndPropogate(); } } @@ -895,13 +874,9 @@ float YGNodeStyleGetFlex(const YGNodeRef node) { // TODO(T26792433): Change the API to accept YGFloatOptional. void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) { if (node->getStyle().flexGrow != flexGrow) { - YGStyle style = node->getStyle(); - if (YGFloatIsUndefined(flexGrow)) { - style.flexGrow = YGFloatOptional(); - } else { - style.flexGrow = YGFloatOptional(flexGrow); - } - node->setStyle(style); + node->getStyle().flexGrow = YGFloatIsUndefined(flexGrow) + ? YGFloatOptional() + : YGFloatOptional(flexGrow); node->markDirtyAndPropogate(); } } @@ -909,13 +884,9 @@ void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) { // TODO(T26792433): Change the API to accept YGFloatOptional. void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) { if (node->getStyle().flexShrink != flexShrink) { - YGStyle style = node->getStyle(); - if (YGFloatIsUndefined(flexShrink)) { - style.flexShrink = YGFloatOptional(); - } else { - style.flexShrink = YGFloatOptional(flexShrink); - } - node->setStyle(style); + node->getStyle().flexShrink = YGFloatIsUndefined(flexShrink) + ? YGFloatOptional() + : YGFloatOptional(flexShrink); node->markDirtyAndPropogate(); } } @@ -937,9 +908,7 @@ void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { if ((node->getStyle().flexBasis.value != value.value && value.unit != YGUnitUndefined) || node->getStyle().flexBasis.unit != value.unit) { - YGStyle style = node->getStyle(); - style.flexBasis = value; - node->setStyle(style); + node->getStyle().flexBasis = value; node->markDirtyAndPropogate(); } } @@ -949,21 +918,19 @@ void YGNodeStyleSetFlexBasisPercent( const float flexBasisPercent) { if (node->getStyle().flexBasis.value != flexBasisPercent || node->getStyle().flexBasis.unit != YGUnitPercent) { - YGStyle style = node->getStyle(); + YGStyle& style = node->getStyle(); style.flexBasis.value = YGFloatSanitize(flexBasisPercent); style.flexBasis.unit = YGFloatIsUndefined(flexBasisPercent) ? YGUnitAuto : YGUnitPercent; - node->setStyle(style); node->markDirtyAndPropogate(); } } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { if (node->getStyle().flexBasis.unit != YGUnitAuto) { - YGStyle style = node->getStyle(); + YGStyle& style = node->getStyle(); style.flexBasis.value = 0; style.flexBasis.unit = YGUnitAuto; - node->setStyle(style); node->markDirtyAndPropogate(); } } @@ -985,9 +952,7 @@ void YGNodeStyleSetBorder( if ((node->getStyle().border[edge].value != value.value && value.unit != YGUnitUndefined) || node->getStyle().border[edge].unit != value.unit) { - YGStyle style = node->getStyle(); - style.border[edge] = value; - node->setStyle(style); + node->getStyle().border[edge] = value; node->markDirtyAndPropogate(); } } @@ -1014,9 +979,7 @@ float YGNodeStyleGetAspectRatio(const YGNodeRef node) { // TODO(T26792433): Change the API to accept YGFloatOptional. void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) { if (node->getStyle().aspectRatio != aspectRatio) { - YGStyle style = node->getStyle(); - style.aspectRatio = YGFloatOptional(aspectRatio); - node->setStyle(style); + node->getStyle().aspectRatio = YGFloatOptional(aspectRatio); node->markDirtyAndPropogate(); } } From 8368338c93d907751c0a1fad20480c94ebd0a296 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 15 Aug 2018 06:13:30 -0700 Subject: [PATCH 052/189] Eliminate remaining `YGStyle&` locals Summary: @public Replaces local references to `YGStyle` objects, and assignment to `YGValue` members with direct assignment from temporaries. This should increase readability, and eliminate duplicated checks for *undefined* values. Reviewed By: astreet Differential Revision: D9083531 fbshipit-source-id: 11386be465352f5cb167b8195b7da432d0055d6f --- yoga/Yoga.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 086dda11..86d66956 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -654,19 +654,16 @@ struct StyleProp { const YGNodeRef node, const type paramName) { \ if (node->getStyle().instanceName.value != YGFloatSanitize(paramName) || \ node->getStyle().instanceName.unit != YGUnitPercent) { \ - YGStyle& style = node->getStyle(); \ - style.instanceName.value = YGFloatSanitize(paramName); \ - style.instanceName.unit = \ - YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent; \ + node->getStyle().instanceName = YGFloatIsUndefined(paramName) \ + ? YGValue{0, YGUnitAuto} \ + : YGValue{paramName, YGUnitPercent}; \ node->markDirtyAndPropogate(); \ } \ } \ \ void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ if (node->getStyle().instanceName.unit != YGUnitAuto) { \ - YGStyle& style = node->getStyle(); \ - style.instanceName.value = 0; \ - style.instanceName.unit = YGUnitAuto; \ + node->getStyle().instanceName = {0, YGUnitAuto}; \ node->markDirtyAndPropogate(); \ } \ } @@ -699,9 +696,7 @@ struct StyleProp { #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \ void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \ if (node->getStyle().instanceName[edge].unit != YGUnitAuto) { \ - YGStyle& style = node->getStyle(); \ - style.instanceName[edge].value = 0; \ - style.instanceName[edge].unit = YGUnitAuto; \ + node->getStyle().instanceName[edge] = {0, YGUnitAuto}; \ node->markDirtyAndPropogate(); \ } \ } @@ -918,19 +913,16 @@ void YGNodeStyleSetFlexBasisPercent( const float flexBasisPercent) { if (node->getStyle().flexBasis.value != flexBasisPercent || node->getStyle().flexBasis.unit != YGUnitPercent) { - YGStyle& style = node->getStyle(); - style.flexBasis.value = YGFloatSanitize(flexBasisPercent); - style.flexBasis.unit = - YGFloatIsUndefined(flexBasisPercent) ? YGUnitAuto : YGUnitPercent; + node->getStyle().flexBasis = YGFloatIsUndefined(flexBasisPercent) + ? YGValue{0, YGUnitAuto} + : YGValue{flexBasisPercent, YGUnitPercent}; node->markDirtyAndPropogate(); } } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { if (node->getStyle().flexBasis.unit != YGUnitAuto) { - YGStyle& style = node->getStyle(); - style.flexBasis.value = 0; - style.flexBasis.unit = YGUnitAuto; + node->getStyle().flexBasis = {0, YGUnitAuto}; node->markDirtyAndPropogate(); } } @@ -2402,7 +2394,7 @@ static void YGJustifyMainAxis( const float& availableInnerCrossDim, const float& availableInnerWidth, const bool& performLayout) { - const YGStyle style = node->getStyle(); + const YGStyle& style = node->getStyle(); // If we are using "at most" rules in the main axis. Calculate the remaining // space when constraint by the min size defined for the main axis. @@ -2488,7 +2480,7 @@ static void YGJustifyMainAxis( i < collectedFlexItemsValues.endOfLineIndex; i++) { const YGNodeRef child = node->getChild(i); - const YGStyle childStyle = child->getStyle(); + const YGStyle& childStyle = child->getStyle(); const YGLayout childLayout = child->getLayout(); if (childStyle.display == YGDisplayNone) { continue; From b872751d68f36b31e80933ea528f46e191b935d7 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Wed, 15 Aug 2018 14:21:55 -0700 Subject: [PATCH 053/189] Solve width bug when the size is less than min Summary: Removed the faulty calculation of `remainingFreeSpace` from the code. `remainingFreeSpace` already had the correct value that special condition was not required. Also added a test case for this issue Reviewed By: IanChilds Differential Revision: D9286928 fbshipit-source-id: 915269602cda2cc4515e6eab8184b2ea98d3e6d4 --- gentest/fixtures/YGJustifyContentTest.html | 15 ++ tests/YGJustifyContentTest.cpp | 171 ++++++++++++++++++++- tests/YGPaddingTest.cpp | 10 +- yoga/Yoga.cpp | 17 +- 4 files changed, 190 insertions(+), 23 deletions(-) diff --git a/gentest/fixtures/YGJustifyContentTest.html b/gentest/fixtures/YGJustifyContentTest.html index 0dee8c3a..2f832df7 100644 --- a/gentest/fixtures/YGJustifyContentTest.html +++ b/gentest/fixtures/YGJustifyContentTest.html @@ -86,3 +86,18 @@
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
diff --git a/tests/YGJustifyContentTest.cpp b/tests/YGJustifyContentTest.cpp index e5d42168..9a022889 100644 --- a/tests/YGJustifyContentTest.cpp +++ b/tests/YGJustifyContentTest.cpp @@ -1,11 +1,12 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - -// @Generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html +// @Generated by gentest/gentest.rb from +// gentest/fixtures/YGJustifyContentTest.html #include #include @@ -735,6 +736,164 @@ TEST(YogaTest, justify_content_row_min_width_and_margin) { YGConfigFree(config); } +TEST( + YogaTest, + justify_content_min_width_with_padding_child_width_greater_than_parent) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetWidth(root, 1000); + YGNodeStyleSetHeight(root, 1584); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); + YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); + YGNodeStyleSetMinWidth(root_child0_child0, 400); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); + YGNodeStyleSetWidth(root_child0_child0_child0, 300); + YGNodeStyleSetHeight(root_child0_child0_child0, 100); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + justify_content_min_width_with_padding_child_width_lower_than_parent) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetWidth(root, 1080); + YGNodeStyleSetHeight(root, 1584); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); + YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); + YGNodeStyleSetMinWidth(root_child0_child0, 400); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); + YGNodeStyleSetWidth(root_child0_child0_child0, 199); + YGNodeStyleSetHeight(root_child0_child0_child0, 100); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(680, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + // + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, justify_content_row_max_width_and_margin) { const YGConfigRef config = YGConfigNew(); diff --git a/tests/YGPaddingTest.cpp b/tests/YGPaddingTest.cpp index f0d37527..1873151c 100644 --- a/tests/YGPaddingTest.cpp +++ b/tests/YGPaddingTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html #include diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 86d66956..36117082 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2396,20 +2396,13 @@ static void YGJustifyMainAxis( const bool& performLayout) { const YGStyle& style = node->getStyle(); - // If we are using "at most" rules in the main axis. Calculate the remaining - // space when constraint by the min size defined for the main axis. + // If we are using "at most" rules in the main axis, make sure that + // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && collectedFlexItemsValues.remainingFreeSpace > 0) { - if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined && - !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) - .isUndefined()) { - collectedFlexItemsValues.remainingFreeSpace = YGFloatMax( - 0, - YGUnwrapFloatOptional(YGResolveValue( - style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - - (availableInnerMainDim - - collectedFlexItemsValues.remainingFreeSpace)); - } else { + if (style.minDimensions[dim[mainAxis]].unit == YGUnitUndefined || + YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) + .isUndefined()) { collectedFlexItemsValues.remainingFreeSpace = 0; } } From abc9fdb37c4b96c38cc8675c348d58e1fb93cecf Mon Sep 17 00:00:00 2001 From: Roman Kushnarenko Date: Thu, 16 Aug 2018 03:12:17 -0700 Subject: [PATCH 054/189] Revert D9286928: [yoga] Solve width bug when the size is less than min Differential Revision: D9286928 Original commit changeset: 915269602cda fbshipit-source-id: a4c23bf335b82fbbf3928a524a61374a6cf6ffb1 --- gentest/fixtures/YGJustifyContentTest.html | 15 -- tests/YGJustifyContentTest.cpp | 171 +-------------------- tests/YGPaddingTest.cpp | 10 +- yoga/Yoga.cpp | 17 +- 4 files changed, 23 insertions(+), 190 deletions(-) diff --git a/gentest/fixtures/YGJustifyContentTest.html b/gentest/fixtures/YGJustifyContentTest.html index 2f832df7..0dee8c3a 100644 --- a/gentest/fixtures/YGJustifyContentTest.html +++ b/gentest/fixtures/YGJustifyContentTest.html @@ -86,18 +86,3 @@
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
diff --git a/tests/YGJustifyContentTest.cpp b/tests/YGJustifyContentTest.cpp index 9a022889..e5d42168 100644 --- a/tests/YGJustifyContentTest.cpp +++ b/tests/YGJustifyContentTest.cpp @@ -1,12 +1,11 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * Copyright (c) 2014-present, Facebook, Inc. * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ -// @Generated by gentest/gentest.rb from -// gentest/fixtures/YGJustifyContentTest.html + +// @Generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html #include #include @@ -736,164 +735,6 @@ TEST(YogaTest, justify_content_row_min_width_and_margin) { YGConfigFree(config); } -TEST( - YogaTest, - justify_content_min_width_with_padding_child_width_greater_than_parent) { - const YGConfigRef config = YGConfigNew(); - - const YGNodeRef root = YGNodeNewWithConfig(config); - YGNodeStyleSetAlignContent(root, YGAlignStretch); - YGNodeStyleSetWidth(root, 1000); - YGNodeStyleSetHeight(root, 1584); - - const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); - YGNodeInsertChild(root, root_child0, 0); - - const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); - YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); - YGNodeStyleSetMinWidth(root_child0_child0, 400); - YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); - YGNodeInsertChild(root_child0, root_child0_child0, 0); - - const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); - YGNodeStyleSetWidth(root_child0_child0_child0, 300); - YGNodeStyleSetHeight(root_child0_child0_child0, 100); - YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - - YGNodeFreeRecursive(root); - - YGConfigFree(config); -} - -TEST( - YogaTest, - justify_content_min_width_with_padding_child_width_lower_than_parent) { - const YGConfigRef config = YGConfigNew(); - - const YGNodeRef root = YGNodeNewWithConfig(config); - YGNodeStyleSetAlignContent(root, YGAlignStretch); - YGNodeStyleSetWidth(root, 1080); - YGNodeStyleSetHeight(root, 1584); - - const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); - YGNodeInsertChild(root, root_child0, 0); - - const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); - YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); - YGNodeStyleSetMinWidth(root_child0_child0, 400); - YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); - YGNodeInsertChild(root_child0, root_child0_child0, 0); - - const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); - YGNodeStyleSetWidth(root_child0_child0_child0, 199); - YGNodeStyleSetHeight(root_child0_child0_child0, 100); - YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(680, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - // - YGNodeFreeRecursive(root); - - YGConfigFree(config); -} - TEST(YogaTest, justify_content_row_max_width_and_margin) { const YGConfigRef config = YGConfigNew(); diff --git a/tests/YGPaddingTest.cpp b/tests/YGPaddingTest.cpp index 1873151c..f0d37527 100644 --- a/tests/YGPaddingTest.cpp +++ b/tests/YGPaddingTest.cpp @@ -1,10 +1,10 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * Copyright (c) 2014-present, Facebook, Inc. * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ + // @Generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html #include diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 36117082..86d66956 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2396,13 +2396,20 @@ static void YGJustifyMainAxis( const bool& performLayout) { const YGStyle& style = node->getStyle(); - // If we are using "at most" rules in the main axis, make sure that - // remainingFreeSpace is 0 when min main dimension is not given + // If we are using "at most" rules in the main axis. Calculate the remaining + // space when constraint by the min size defined for the main axis. if (measureModeMainDim == YGMeasureModeAtMost && collectedFlexItemsValues.remainingFreeSpace > 0) { - if (style.minDimensions[dim[mainAxis]].unit == YGUnitUndefined || - YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) - .isUndefined()) { + if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined && + !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) + .isUndefined()) { + collectedFlexItemsValues.remainingFreeSpace = YGFloatMax( + 0, + YGUnwrapFloatOptional(YGResolveValue( + style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - + (availableInnerMainDim - + collectedFlexItemsValues.remainingFreeSpace)); + } else { collectedFlexItemsValues.remainingFreeSpace = 0; } } From 8309cfc9764f7ba7e1fed4cec4596d8c7d740a07 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Thu, 16 Aug 2018 06:22:10 -0700 Subject: [PATCH 055/189] Fix parent height calculation in case of baseline alignment Summary: Prior to this diff, if parents height was not set then the height of parent was deduced as max of childrens height(considering line ht, padding, margin etc. ), but it didn't consider the baseline scenario where the previous logic will fail as then the parents height will be determined by the space taken by children above and below the reference baseline. I added a test case for the same. Look at the diff D9088051 which shows the screenshot of the bug. It is solved to https://pxl.cl/gvVk Reviewed By: dsyang Differential Revision: D9219678 fbshipit-source-id: f4a0b9f1452c33e78bd8c6cf39f6fcf538a04074 --- tests/YGAlignBaselineTest.cpp | 96 +++++++++++++++++++++++++++++++++++ tests/YGAlignItemsTest.cpp | 10 ++-- yoga/Yoga.cpp | 86 +++++++++++++++++-------------- 3 files changed, 149 insertions(+), 43 deletions(-) create mode 100644 tests/YGAlignBaselineTest.cpp diff --git a/tests/YGAlignBaselineTest.cpp b/tests/YGAlignBaselineTest.cpp new file mode 100644 index 00000000..477ecb48 --- /dev/null +++ b/tests/YGAlignBaselineTest.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ + +#include +#include + +static float +_baselineFunc(YGNodeRef node, const float width, const float height) { + return height / 2; +} + +TEST(YogaTest, align_baseline_with_no_parent_ht) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 150); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 50); + YGNodeStyleSetHeight(root_child1, 40); + YGNodeSetBaselineFunc(root_child1, _baselineFunc); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, align_baseline_with_no_baseline_func_and_no_parent_ht) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 150); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 80); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 50); + YGNodeStyleSetHeight(root_child1, 50); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/tests/YGAlignItemsTest.cpp b/tests/YGAlignItemsTest.cpp index fd5e424f..29f43645 100644 --- a/tests/YGAlignItemsTest.cpp +++ b/tests/YGAlignItemsTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignItemsTest.html #include diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 86d66956..e17766bc 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -3152,47 +3152,46 @@ static void YGNodelayoutImpl( } // STEP 8: MULTI-LINE CONTENT ALIGNMENT - if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node)) && - !YGFloatIsUndefined(availableInnerCrossDim)) { - const float remainingAlignContentDim = - availableInnerCrossDim - totalLineCrossDim; - + // currentLead stores the size of the cross dim + float currentLead = leadingPaddingAndBorderCross; + if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node))) { float crossDimLead = 0; - float currentLead = leadingPaddingAndBorderCross; - - switch (node->getStyle().alignContent) { - case YGAlignFlexEnd: - currentLead += remainingAlignContentDim; - break; - case YGAlignCenter: - currentLead += remainingAlignContentDim / 2; - break; - case YGAlignStretch: - if (availableInnerCrossDim > totalLineCrossDim) { - crossDimLead = remainingAlignContentDim / lineCount; - } - break; - case YGAlignSpaceAround: - if (availableInnerCrossDim > totalLineCrossDim) { - currentLead += remainingAlignContentDim / (2 * lineCount); - if (lineCount > 1) { + if (!YGFloatIsUndefined(availableInnerCrossDim)) { + const float remainingAlignContentDim = + availableInnerCrossDim - totalLineCrossDim; + switch (node->getStyle().alignContent) { + case YGAlignFlexEnd: + currentLead += remainingAlignContentDim; + break; + case YGAlignCenter: + currentLead += remainingAlignContentDim / 2; + break; + case YGAlignStretch: + if (availableInnerCrossDim > totalLineCrossDim) { crossDimLead = remainingAlignContentDim / lineCount; } - } else { - currentLead += remainingAlignContentDim / 2; - } - break; - case YGAlignSpaceBetween: - if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) { - crossDimLead = remainingAlignContentDim / (lineCount - 1); - } - break; - case YGAlignAuto: - case YGAlignFlexStart: - case YGAlignBaseline: - break; + break; + case YGAlignSpaceAround: + if (availableInnerCrossDim > totalLineCrossDim) { + currentLead += remainingAlignContentDim / (2 * lineCount); + if (lineCount > 1) { + crossDimLead = remainingAlignContentDim / lineCount; + } + } else { + currentLead += remainingAlignContentDim / 2; + } + break; + case YGAlignSpaceBetween: + if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) { + crossDimLead = remainingAlignContentDim / (lineCount - 1); + } + break; + case YGAlignAuto: + case YGAlignFlexStart: + case YGAlignBaseline: + break; + } } - uint32_t endIndex = 0; for (uint32_t i = 0; i < lineCount; i++) { const uint32_t startIndex = endIndex; @@ -3394,7 +3393,6 @@ static void YGNodelayoutImpl( measureModeCrossDim == YGMeasureModeAtMost)) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. - node->setLayoutMeasuredDimension( YGNodeBoundAxis( node, @@ -3420,6 +3418,18 @@ static void YGNodelayoutImpl( dim[crossAxis]); } + if (performLayout && + node->getStyle().dimensions[dim[crossAxis]].unit == YGUnitAuto && + node->getStyle().alignItems == YGAlignBaseline) { + node->setLayoutMeasuredDimension( + YGNodeBoundAxis( + node, + crossAxis, + currentLead + paddingAndBorderAxisRow, + crossAxisownerSize, + ownerWidth), + dim[crossAxis]); + } // As we only wrapped in normal direction yet, we need to reverse the // positions on wrap-reverse. if (performLayout && node->getStyle().flexWrap == YGWrapWrapReverse) { From 6132a597725522b752bb576e9feb18cff0720632 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 17 Aug 2018 03:56:35 -0700 Subject: [PATCH 056/189] Type alias for dimensions Summary: Aliases `std::array` as `YGStyle::Dimensions` for increased readability. This prepares a follow up, where the alias is used in `Yoga.cpp`. Reviewed By: astreet Differential Revision: D8874566 fbshipit-source-id: a7a7a1b02bff547d7d6b800c522c4785a62ad611 --- yoga/YGStyle.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 3f4bbd34..83c24968 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -11,6 +11,8 @@ #include "Yoga.h" struct YGStyle { + using Dimensions = std::array; + YGDirection direction; YGFlexDirection flexDirection; YGJustify justifyContent; @@ -29,9 +31,9 @@ struct YGStyle { std::array position; std::array padding; std::array border; - std::array dimensions; - std::array minDimensions; - std::array maxDimensions; + Dimensions dimensions; + Dimensions minDimensions; + Dimensions maxDimensions; // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio; From 48a8f883badde79ee7682deadbbd32caa4572365 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 17 Aug 2018 03:56:37 -0700 Subject: [PATCH 057/189] Replace getter in `YG_NODE_STYLE_PROPERTY_UNIT_IMPL` macro with template code Reviewed By: astreet Differential Revision: D8874734 fbshipit-source-id: ba94b4d0fd31e8344c7836b66a269d5f1f69e225 --- yoga/Yoga.cpp | 55 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index e17766bc..6d3cfa70 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -604,19 +604,31 @@ struct StyleProp { } }; +template +struct DimensionProp { + template + static WIN_STRUCT(YGValue) get(YGNodeRef node) { + YGValue value = (node->getStyle().*P)[idx]; + if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { + value.value = YGUndefined; + } + return WIN_STRUCT_REF(value); + } +}; + } // namespace #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ - type, name, paramName, instanceName) \ + type, name, paramName, instanceName, dimension) \ void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ YGValue value = { \ YGFloatSanitize(paramName), \ YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \ }; \ - if ((node->getStyle().instanceName.value != value.value && \ + if ((node->getStyle().instanceName[dimension].value != value.value && \ value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName.unit != value.unit) { \ - node->getStyle().instanceName = value; \ + node->getStyle().instanceName[dimension].unit != value.unit) { \ + node->getStyle().instanceName[dimension] = value; \ node->markDirtyAndPropogate(); \ } \ } \ @@ -627,10 +639,10 @@ struct StyleProp { YGFloatSanitize(paramName), \ YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \ }; \ - if ((node->getStyle().instanceName.value != value.value && \ + if ((node->getStyle().instanceName[dimension].value != value.value && \ value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName.unit != value.unit) { \ - node->getStyle().instanceName = value; \ + node->getStyle().instanceName[dimension].unit != value.unit) { \ \ + node->getStyle().instanceName[dimension] = value; \ node->markDirtyAndPropogate(); \ } \ } @@ -668,16 +680,13 @@ struct StyleProp { } \ } -#define YG_NODE_STYLE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName) \ - YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ - float, name, paramName, instanceName) \ - \ - type YGNodeStyleGet##name(const YGNodeRef node) { \ - YGValue value = node->getStyle().instanceName; \ - if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \ - value.value = YGUndefined; \ - } \ - return value; \ +#define YG_NODE_STYLE_PROPERTY_UNIT_IMPL( \ + type, name, paramName, instanceName, dimension) \ + YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ + float, name, paramName, instanceName, dimension) \ + \ + type YGNodeStyleGet##name(const YGNodeRef node) { \ + return DimensionProp<&YGStyle::instanceName>::get(node); \ } #define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( \ @@ -990,22 +999,26 @@ YG_NODE_STYLE_PROPERTY_UNIT_IMPL( YGValue, MinWidth, minWidth, - minDimensions[YGDimensionWidth]); + minDimensions, + YGDimensionWidth); YG_NODE_STYLE_PROPERTY_UNIT_IMPL( YGValue, MinHeight, minHeight, - minDimensions[YGDimensionHeight]); + minDimensions, + YGDimensionHeight); YG_NODE_STYLE_PROPERTY_UNIT_IMPL( YGValue, MaxWidth, maxWidth, - maxDimensions[YGDimensionWidth]); + maxDimensions, + YGDimensionWidth); YG_NODE_STYLE_PROPERTY_UNIT_IMPL( YGValue, MaxHeight, maxHeight, - maxDimensions[YGDimensionHeight]); + maxDimensions, + YGDimensionHeight); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]); From 7f71cac3b0a56321bce9676b29e3b436ae256f6d Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 17 Aug 2018 03:56:39 -0700 Subject: [PATCH 058/189] Replace point setter in `YG_NODE_STYLE_PROPERTY_UNIT_IMPL` macro with template code Reviewed By: astreet Differential Revision: D8874735 fbshipit-source-id: 77fa1ceb2eaff6a0e415ef939e55aa22bc3d6099 --- yoga/Yoga.cpp | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6d3cfa70..03185fb3 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -604,6 +604,16 @@ struct StyleProp { } }; +struct Value { + template + static YGValue create(float value) { + return { + YGFloatSanitize(value), + YGFloatIsUndefined(value) ? YGUnitUndefined : U, + }; + } +}; + template struct DimensionProp { template @@ -614,6 +624,17 @@ struct DimensionProp { } return WIN_STRUCT_REF(value); } + + template + static void set(YGNodeRef node, float newValue) { + YGValue value = Value::create(newValue); + if (((node->getStyle().*P)[idx].value != value.value && + value.unit != YGUnitUndefined) || + (node->getStyle().*P)[idx].unit != value.unit) { + (node->getStyle().*P)[idx] = value; + node->markDirtyAndPropogate(); + } + } }; } // namespace @@ -621,16 +642,8 @@ struct DimensionProp { #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ type, name, paramName, instanceName, dimension) \ void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \ - }; \ - if ((node->getStyle().instanceName[dimension].value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[dimension].unit != value.unit) { \ - node->getStyle().instanceName[dimension] = value; \ - node->markDirtyAndPropogate(); \ - } \ + DimensionProp<&YGStyle::instanceName>::set( \ + node, paramName); \ } \ \ void YGNodeStyleSet##name##Percent( \ @@ -641,8 +654,8 @@ struct DimensionProp { }; \ if ((node->getStyle().instanceName[dimension].value != value.value && \ value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[dimension].unit != value.unit) { \ \ - node->getStyle().instanceName[dimension] = value; \ + node->getStyle().instanceName[dimension].unit != value.unit) { \ + node->getStyle().instanceName[dimension] = value; \ node->markDirtyAndPropogate(); \ } \ } From 85031baaf263cf518fbac085f425a43073dbad94 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 17 Aug 2018 03:56:43 -0700 Subject: [PATCH 059/189] Replace percent setter in `YG_NODE_STYLE_PROPERTY_UNIT_IMPL` macro with template code Reviewed By: astreet Differential Revision: D8874732 fbshipit-source-id: 46fdf851f19f16def0c7e2ab4c5f17a349dc7aee --- yoga/Yoga.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 03185fb3..7a115a90 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -648,16 +648,8 @@ struct DimensionProp { \ void YGNodeStyleSet##name##Percent( \ const YGNodeRef node, const type paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \ - }; \ - if ((node->getStyle().instanceName[dimension].value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[dimension].unit != value.unit) { \ - node->getStyle().instanceName[dimension] = value; \ - node->markDirtyAndPropogate(); \ - } \ + DimensionProp<&YGStyle::instanceName>::set( \ + node, paramName); \ } #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ From 1d09227374b9d081bb763d9ee052e39c7d5b5bc0 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 17 Aug 2018 03:56:48 -0700 Subject: [PATCH 060/189] Inline `YG_NODE_STYLE_PROPERTY_UNIT_IMPL` macro Reviewed By: astreet Differential Revision: D8874733 fbshipit-source-id: 75c24b508f287f405fad09605f64d2bfb3ffa0a5 --- yoga/Yoga.cpp | 99 +++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 7a115a90..f35b70b5 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -639,19 +639,6 @@ struct DimensionProp { } // namespace -#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ - type, name, paramName, instanceName, dimension) \ - void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ - DimensionProp<&YGStyle::instanceName>::set( \ - node, paramName); \ - } \ - \ - void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const type paramName) { \ - DimensionProp<&YGStyle::instanceName>::set( \ - node, paramName); \ - } - #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ type, name, paramName, instanceName) \ void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ @@ -685,15 +672,6 @@ struct DimensionProp { } \ } -#define YG_NODE_STYLE_PROPERTY_UNIT_IMPL( \ - type, name, paramName, instanceName, dimension) \ - YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ - float, name, paramName, instanceName, dimension) \ - \ - type YGNodeStyleGet##name(const YGNodeRef node) { \ - return DimensionProp<&YGStyle::instanceName>::get(node); \ - } - #define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( \ type, name, paramName, instanceName) \ YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ @@ -1000,30 +978,59 @@ YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( Height, height, dimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL( - YGValue, - MinWidth, - minWidth, - minDimensions, - YGDimensionWidth); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL( - YGValue, - MinHeight, - minHeight, - minDimensions, - YGDimensionHeight); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL( - YGValue, - MaxWidth, - maxWidth, - maxDimensions, - YGDimensionWidth); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL( - YGValue, - MaxHeight, - maxHeight, - maxDimensions, - YGDimensionHeight); + +void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { + DimensionProp<&YGStyle::minDimensions>::set( + node, minWidth); +} +void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { + DimensionProp<&YGStyle::minDimensions>::set( + node, minWidth); +} +YGValue YGNodeStyleGetMinWidth(const YGNodeRef node) { + return DimensionProp<&YGStyle::minDimensions>::get(node); +}; + +void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { + DimensionProp<&YGStyle::minDimensions>::set( + node, minHeight); +} +void YGNodeStyleSetMinHeightPercent( + const YGNodeRef node, + const float minHeight) { + DimensionProp<&YGStyle::minDimensions>::set( + node, minHeight); +} +YGValue YGNodeStyleGetMinHeight(const YGNodeRef node) { + return DimensionProp<&YGStyle::minDimensions>::get(node); +}; + +void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { + DimensionProp<&YGStyle::maxDimensions>::set( + node, maxWidth); +} +void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { + DimensionProp<&YGStyle::maxDimensions>::set( + node, maxWidth); +} +YGValue YGNodeStyleGetMaxWidth(const YGNodeRef node) { + return DimensionProp<&YGStyle::maxDimensions>::get(node); +}; + +void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { + DimensionProp<&YGStyle::maxDimensions>::set( + node, maxHeight); +} +void YGNodeStyleSetMaxHeightPercent( + const YGNodeRef node, + const float maxHeight) { + DimensionProp<&YGStyle::maxDimensions>::set( + node, maxHeight); +} +YGValue YGNodeStyleGetMaxHeight(const YGNodeRef node) { + return DimensionProp<&YGStyle::maxDimensions>::get(node); +}; + YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]); From 1080cf22e3f520875108ffedd1295a801ea6dd5c Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 20 Aug 2018 06:14:50 -0700 Subject: [PATCH 061/189] Solve width bug when the size is less than min Summary: This diff updates the logic which reassigns `remainingFreeSpace` when the node's calculated dimension falls below min width of the node. So we will have to update the `remainingFreeSpace` as there is more available space since the calculated nodes width is less than the min width. I have also added comments at relevant places in the code so that it is clearer. This diff solves the issue raised in litho support grp. The details can be found here T32199608. This diff also makes sure that it doesn't break fblite, as the earlier version broke it, details of which can be found here T32881750. Reviewed By: IanChilds Differential Revision: D9359026 fbshipit-source-id: 4168e385e962c168a9de9370220c75f14a6726a7 --- gentest/fixtures/YGJustifyContentTest.html | 15 ++ tests/YGJustifyContentTest.cpp | 171 ++++++++++++++++++++- tests/YGPaddingTest.cpp | 10 +- yoga/Yoga.cpp | 31 ++-- 4 files changed, 205 insertions(+), 22 deletions(-) diff --git a/gentest/fixtures/YGJustifyContentTest.html b/gentest/fixtures/YGJustifyContentTest.html index 0dee8c3a..2f832df7 100644 --- a/gentest/fixtures/YGJustifyContentTest.html +++ b/gentest/fixtures/YGJustifyContentTest.html @@ -86,3 +86,18 @@
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
diff --git a/tests/YGJustifyContentTest.cpp b/tests/YGJustifyContentTest.cpp index e5d42168..9a022889 100644 --- a/tests/YGJustifyContentTest.cpp +++ b/tests/YGJustifyContentTest.cpp @@ -1,11 +1,12 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - -// @Generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html +// @Generated by gentest/gentest.rb from +// gentest/fixtures/YGJustifyContentTest.html #include #include @@ -735,6 +736,164 @@ TEST(YogaTest, justify_content_row_min_width_and_margin) { YGConfigFree(config); } +TEST( + YogaTest, + justify_content_min_width_with_padding_child_width_greater_than_parent) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetWidth(root, 1000); + YGNodeStyleSetHeight(root, 1584); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); + YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); + YGNodeStyleSetMinWidth(root_child0_child0, 400); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); + YGNodeStyleSetWidth(root_child0_child0_child0, 300); + YGNodeStyleSetHeight(root_child0_child0_child0, 100); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + justify_content_min_width_with_padding_child_width_lower_than_parent) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetWidth(root, 1080); + YGNodeStyleSetHeight(root, 1584); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); + YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); + YGNodeStyleSetMinWidth(root_child0_child0, 400); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); + YGNodeStyleSetWidth(root_child0_child0_child0, 199); + YGNodeStyleSetHeight(root_child0_child0_child0, 100); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(680, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + // + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, justify_content_row_max_width_and_margin) { const YGConfigRef config = YGConfigNew(); diff --git a/tests/YGPaddingTest.cpp b/tests/YGPaddingTest.cpp index f0d37527..1873151c 100644 --- a/tests/YGPaddingTest.cpp +++ b/tests/YGPaddingTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html #include diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index f35b70b5..621564f4 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2420,20 +2420,32 @@ static void YGJustifyMainAxis( const float& availableInnerWidth, const bool& performLayout) { const YGStyle& style = node->getStyle(); - - // If we are using "at most" rules in the main axis. Calculate the remaining - // space when constraint by the min size defined for the main axis. + const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( + node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); + const float trailingPaddingAndBorderMain = YGUnwrapFloatOptional( + node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)); + // If we are using "at most" rules in the main axis, make sure that + // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && collectedFlexItemsValues.remainingFreeSpace > 0) { if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined && !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) .isUndefined()) { - collectedFlexItemsValues.remainingFreeSpace = YGFloatMax( - 0, + // This condition makes sure that if the size of main dimension(after + // considering child nodes main dim, leading and trailing padding etc) + // falls below min dimension, then the remainingFreeSpace is reassigned + // considering the min dimension + + // `minAvailableMainDim` denotes minimum available space in which child + // can be laid out, it will exclude space consumed by padding and border. + const float minAvailableMainDim = YGUnwrapFloatOptional(YGResolveValue( style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - - (availableInnerMainDim - - collectedFlexItemsValues.remainingFreeSpace)); + leadingPaddingAndBorderMain - trailingPaddingAndBorderMain; + const float occupiedSpaceByChildNodes = + availableInnerMainDim - collectedFlexItemsValues.remainingFreeSpace; + collectedFlexItemsValues.remainingFreeSpace = + YGFloatMax(0, minAvailableMainDim - occupiedSpaceByChildNodes); } else { collectedFlexItemsValues.remainingFreeSpace = 0; } @@ -2495,8 +2507,6 @@ static void YGJustifyMainAxis( } } - const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); collectedFlexItemsValues.mainDim = leadingPaddingAndBorderMain + leadingMainDim; collectedFlexItemsValues.crossDim = 0; @@ -2579,8 +2589,7 @@ static void YGJustifyMainAxis( } } } - collectedFlexItemsValues.mainDim += YGUnwrapFloatOptional( - node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)); + collectedFlexItemsValues.mainDim += trailingPaddingAndBorderMain; } // From 7a45fb39bff870f35967d5e0ae69212587f35020 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Tue, 21 Aug 2018 17:23:25 -0700 Subject: [PATCH 062/189] Solve the bug related to baseline height Summary: This diff fixes the height calculation logic for the nodes with baseline. Before height calculation for baseline was done at wrong place. The task was created due to the regression caused by D9219678. Reviewed By: IanChilds Differential Revision: D9421551 fbshipit-source-id: 3fbb738314130b346c4186ec45d00c9ea63bc9f4 --- tests/YGAlignBaselineTest.cpp | 70 +++++++++++++++++++++++++++++++++++ yoga/Yoga.cpp | 52 ++++++++++++++++---------- 2 files changed, 103 insertions(+), 19 deletions(-) diff --git a/tests/YGAlignBaselineTest.cpp b/tests/YGAlignBaselineTest.cpp index 477ecb48..e5981ed4 100644 --- a/tests/YGAlignBaselineTest.cpp +++ b/tests/YGAlignBaselineTest.cpp @@ -14,6 +14,76 @@ _baselineFunc(YGNodeRef node, const float width, const float height) { return height / 2; } +static YGSize _measure1( + YGNodeRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode) { + return YGSize{ + .width = 42, + .height = 50, + }; +} + +static YGSize _measure2( + YGNodeRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode) { + return YGSize{ + .width = 279, + .height = 126, + }; +} + +// Test case for bug in T32999822 +TEST(YogaTest, align_baseline_parent_ht_not_specified) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 340); + YGNodeStyleSetMaxHeight(root, 170); + YGNodeStyleSetMinHeight(root, 0); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 0); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeSetMeasureFunc(root_child0, _measure1); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 0); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeSetMeasureFunc(root_child1, _measure2); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(340, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(126, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(42, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + ASSERT_FLOAT_EQ(76, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(42, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(279, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(126, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, align_baseline_with_no_parent_ht) { YGConfigRef config = YGConfigNew(); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 621564f4..c6d38bb4 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2511,6 +2511,9 @@ static void YGJustifyMainAxis( leadingPaddingAndBorderMain + leadingMainDim; collectedFlexItemsValues.crossDim = 0; + float maxAscentForCurrentLine = 0; + float maxDescentForCurrentLine = 0; + bool isNodeBaselineLayout = YGIsBaselineLayout(node); for (uint32_t i = startOfLineIndex; i < collectedFlexItemsValues.endOfLineIndex; i++) { @@ -2575,11 +2578,30 @@ static void YGJustifyMainAxis( collectedFlexItemsValues.mainDim += betweenMainDim + YGNodeDimWithMargin(child, mainAxis, availableInnerWidth); - // The cross dimension is the max of the elements dimension since - // there can only be one element in that cross dimension. - collectedFlexItemsValues.crossDim = YGFloatMax( - collectedFlexItemsValues.crossDim, - YGNodeDimWithMargin(child, crossAxis, availableInnerWidth)); + if (isNodeBaselineLayout) { + // If the child is baseline aligned then the cross dimension is + // calculated by adding maxAscent and maxDescent from the baseline. + const float ascent = YGBaseline(child) + + YGUnwrapFloatOptional(child->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth)); + const float descent = + child->getLayout().measuredDimensions[YGDimensionHeight] + + YGUnwrapFloatOptional(child->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth)) - + ascent; + + maxAscentForCurrentLine = + YGFloatMax(maxAscentForCurrentLine, ascent); + maxDescentForCurrentLine = + YGFloatMax(maxDescentForCurrentLine, descent); + } else { + // The cross dimension is the max of the elements dimension since + // there can only be one element in that cross dimension in the case + // when the items are not baseline aligned + collectedFlexItemsValues.crossDim = YGFloatMax( + collectedFlexItemsValues.crossDim, + YGNodeDimWithMargin(child, crossAxis, availableInnerWidth)); + } } } else if (performLayout) { child->setLayoutPosition( @@ -2590,6 +2612,11 @@ static void YGJustifyMainAxis( } } collectedFlexItemsValues.mainDim += trailingPaddingAndBorderMain; + + if (isNodeBaselineLayout) { + collectedFlexItemsValues.crossDim = + maxAscentForCurrentLine + maxDescentForCurrentLine; + } } // @@ -3187,9 +3214,9 @@ static void YGNodelayoutImpl( // STEP 8: MULTI-LINE CONTENT ALIGNMENT // currentLead stores the size of the cross dim - float currentLead = leadingPaddingAndBorderCross; if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node))) { float crossDimLead = 0; + float currentLead = leadingPaddingAndBorderCross; if (!YGFloatIsUndefined(availableInnerCrossDim)) { const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; @@ -3372,7 +3399,6 @@ static void YGNodelayoutImpl( } } } - currentLead += lineHeight; } } @@ -3452,18 +3478,6 @@ static void YGNodelayoutImpl( dim[crossAxis]); } - if (performLayout && - node->getStyle().dimensions[dim[crossAxis]].unit == YGUnitAuto && - node->getStyle().alignItems == YGAlignBaseline) { - node->setLayoutMeasuredDimension( - YGNodeBoundAxis( - node, - crossAxis, - currentLead + paddingAndBorderAxisRow, - crossAxisownerSize, - ownerWidth), - dim[crossAxis]); - } // As we only wrapped in normal direction yet, we need to reverse the // positions on wrap-reverse. if (performLayout && node->getStyle().flexWrap == YGWrapWrapReverse) { From 2b52c73d70100e95d2afd959447dcc3e5f0e4f07 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Tue, 28 Aug 2018 21:54:41 -0700 Subject: [PATCH 063/189] Move yoga_defs.bzl Reviewed By: mzlee Differential Revision: D9546736 fbshipit-source-id: ff0c19a33cc72a330bac1e266ad0bb6d7c440e60 --- BUCK | 2 +- YogaKit/BUCK | 2 +- android/BUCK | 2 +- android/sample/BUCK | 2 +- android/sample/java/com/facebook/samples/yoga/BUCK | 2 +- android/src/main/java/com/facebook/yoga/android/BUCK | 2 +- benchmark/BUCK | 2 +- csharp/BUCK | 2 +- java/BUCK | 2 +- .../src/main/java/com/facebook/proguard/annotations/BUCK | 2 +- lib/android-support/BUCK | 2 +- lib/appcompat/BUCK | 2 +- lib/fb/BUCK | 2 +- lib/fb/src/main/java/com/facebook/jni/BUCK | 2 +- lib/gtest/BUCK | 2 +- lib/infer-annotations/BUCK | 2 +- lib/jni/BUCK | 2 +- lib/jsr-305/BUCK | 2 +- lib/junit/BUCK | 2 +- lib/soloader/BUCK | 2 +- yoga_defs.bzl => tools/build_defs/oss/yoga_defs.bzl | 0 21 files changed, 20 insertions(+), 20 deletions(-) rename yoga_defs.bzl => tools/build_defs/oss/yoga_defs.bzl (100%) diff --git a/BUCK b/BUCK index 4b809f69..699e7a61 100644 --- a/BUCK +++ b/BUCK @@ -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("//:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "subdir_glob", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep") +load("//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "GTEST_TARGET", "LIBRARY_COMPILER_FLAGS", "subdir_glob", "yoga_cxx_library", "yoga_cxx_test", "yoga_dep") GMOCK_OVERRIDE_FLAGS = [ # gmock does not mark mocked methods as override, ignore the warnings in tests diff --git a/YogaKit/BUCK b/YogaKit/BUCK index 9675d049..f4ea3567 100644 --- a/YogaKit/BUCK +++ b/YogaKit/BUCK @@ -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("//:yoga_defs.bzl", "subdir_glob", "yoga_apple_library", "yoga_apple_test", "yoga_dep") +load("//tools/build_defs/oss:yoga_defs.bzl", "subdir_glob", "yoga_apple_library", "yoga_apple_test", "yoga_dep") COMPILER_FLAGS = [ "-fobjc-arc", diff --git a/android/BUCK b/android/BUCK index af64135f..35f91a0d 100644 --- a/android/BUCK +++ b/android/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "INFER_ANNOTATIONS_TARGET", "JAVA_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource") +load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_RES_TARGET", "INFER_ANNOTATIONS_TARGET", "JAVA_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "yoga_android_aar", "yoga_android_resource") yoga_android_aar( name = "android", diff --git a/android/sample/BUCK b/android/sample/BUCK index 966c700d..0612aca9 100644 --- a/android/sample/BUCK +++ b/android/sample/BUCK @@ -4,7 +4,7 @@ # This source code is licensed under the license found in the # LICENSE-examples file in the root directory of this source tree. -load("//:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource") +load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource") yoga_android_binary( name = "sample", diff --git a/android/sample/java/com/facebook/samples/yoga/BUCK b/android/sample/java/com/facebook/samples/yoga/BUCK index 4c216b1e..5d3b601f 100644 --- a/android/sample/java/com/facebook/samples/yoga/BUCK +++ b/android/sample/java/com/facebook/samples/yoga/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the license found in the # LICENSE-examples file in the root directory of this source tree. -load("//:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "ANDROID_SUPPORT_TARGET", "APPCOMPAT_TARGET", "SOLOADER_TARGET", "yoga_android_library") +load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "ANDROID_SUPPORT_TARGET", "APPCOMPAT_TARGET", "SOLOADER_TARGET", "yoga_android_library") yoga_android_library( name = "yoga", diff --git a/android/src/main/java/com/facebook/yoga/android/BUCK b/android/src/main/java/com/facebook/yoga/android/BUCK index 01a8d47d..8731dc3c 100644 --- a/android/src/main/java/com/facebook/yoga/android/BUCK +++ b/android/src/main/java/com/facebook/yoga/android/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "ANDROID_RES_TARGET", "INFER_ANNOTATIONS_TARGET", "JAVA_TARGET", "JSR_305_TARGET", "SOLOADER_TARGET", "yoga_android_library") +load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "INFER_ANNOTATIONS_TARGET", "JAVA_TARGET", "JSR_305_TARGET", "SOLOADER_TARGET", "yoga_android_library") yoga_android_library( name = "android", diff --git a/benchmark/BUCK b/benchmark/BUCK index 82864373..2071746f 100644 --- a/benchmark/BUCK +++ b/benchmark/BUCK @@ -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("//:yoga_defs.bzl", "subdir_glob", "yoga_cxx_binary", "yoga_dep") +load("//tools/build_defs/oss:yoga_defs.bzl", "subdir_glob", "yoga_cxx_binary", "yoga_dep") yoga_cxx_binary( name = "benchmark", diff --git a/csharp/BUCK b/csharp/BUCK index e679803a..21e3b23f 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -4,7 +4,7 @@ # LICENSE file in the root directory of this source tree. load( - "//:yoga_defs.bzl", + "//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "is_apple_platform", "yoga_cxx_library", diff --git a/java/BUCK b/java/BUCK index 4ddabcef..dab188ce 100644 --- a/java/BUCK +++ b/java/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//: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_library", "yoga_dep", "yoga_java_binary", "yoga_java_library", "yoga_java_test") yoga_cxx_library( name = "jni", diff --git a/java/proguard-annotations/src/main/java/com/facebook/proguard/annotations/BUCK b/java/proguard-annotations/src/main/java/com/facebook/proguard/annotations/BUCK index 73456365..16761a05 100644 --- a/java/proguard-annotations/src/main/java/com/facebook/proguard/annotations/BUCK +++ b/java/proguard-annotations/src/main/java/com/facebook/proguard/annotations/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library") yoga_java_library( name = "annotations", diff --git a/lib/android-support/BUCK b/lib/android-support/BUCK index d104d464..59bc7cfa 100644 --- a/lib/android-support/BUCK +++ b/lib/android-support/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_prebuilt_jar") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_prebuilt_jar") yoga_prebuilt_jar( name = "android-support", diff --git a/lib/appcompat/BUCK b/lib/appcompat/BUCK index eeda3b37..c5508740 100644 --- a/lib/appcompat/BUCK +++ b/lib/appcompat/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") android_prebuilt_aar( name = "appcompat", diff --git a/lib/fb/BUCK b/lib/fb/BUCK index cc2502ec..6eac7750 100644 --- a/lib/fb/BUCK +++ b/lib/fb/BUCK @@ -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("//: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", "FBJNI_JAVA_TARGET", "JNI_TARGET", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library", "yoga_prebuilt_cxx_library") yoga_prebuilt_cxx_library( name = "ndklog", diff --git a/lib/fb/src/main/java/com/facebook/jni/BUCK b/lib/fb/src/main/java/com/facebook/jni/BUCK index 0bb5297d..b69c0c07 100644 --- a/lib/fb/src/main/java/com/facebook/jni/BUCK +++ b/lib/fb/src/main/java/com/facebook/jni/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "JSR_305_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_java_library") +load("//tools/build_defs/oss:yoga_defs.bzl", "JSR_305_TARGET", "PROGRUARD_ANNOTATIONS_TARGET", "SOLOADER_TARGET", "yoga_java_library") yoga_java_library( name = "jni", diff --git a/lib/gtest/BUCK b/lib/gtest/BUCK index e489c69c..e59462a5 100644 --- a/lib/gtest/BUCK +++ b/lib/gtest/BUCK @@ -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("//:yoga_defs.bzl", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "subdir_glob", "yoga_cxx_library") COMPILER_FLAGS = [ "-std=c++11", diff --git a/lib/infer-annotations/BUCK b/lib/infer-annotations/BUCK index 6c89bc6e..8dbd2a13 100644 --- a/lib/infer-annotations/BUCK +++ b/lib/infer-annotations/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") yoga_prebuilt_jar( name = "infer-annotations-jar", diff --git a/lib/jni/BUCK b/lib/jni/BUCK index 9ce8bd05..9ec57971 100644 --- a/lib/jni/BUCK +++ b/lib/jni/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "yoga_cxx_library") +load("//tools/build_defs/oss:yoga_defs.bzl", "yoga_cxx_library") yoga_cxx_library( name = "jni", diff --git a/lib/jsr-305/BUCK b/lib/jsr-305/BUCK index 34343c25..dadd5e0b 100644 --- a/lib/jsr-305/BUCK +++ b/lib/jsr-305/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") yoga_prebuilt_jar( name = "jsr305-jar", diff --git a/lib/junit/BUCK b/lib/junit/BUCK index 7cc0079c..64f8f1d3 100644 --- a/lib/junit/BUCK +++ b/lib/junit/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS", "yoga_java_library", "yoga_prebuilt_jar") yoga_prebuilt_jar( name = "junit-jar", diff --git a/lib/soloader/BUCK b/lib/soloader/BUCK index 7ab9627f..c21b5475 100644 --- a/lib/soloader/BUCK +++ b/lib/soloader/BUCK @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "YOGA_ROOTS") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") android_prebuilt_aar( name = "soloader", diff --git a/yoga_defs.bzl b/tools/build_defs/oss/yoga_defs.bzl similarity index 100% rename from yoga_defs.bzl rename to tools/build_defs/oss/yoga_defs.bzl From f7df575746d852a0f6ce1d62ec284138ed9daa9a Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Thu, 30 Aug 2018 04:40:46 -0700 Subject: [PATCH 064/189] Expose logging capablities in Yoga header Summary: Exposes a bool in the config which will help log the yoga hierarchy. Also added a test case Reviewed By: IanChilds Differential Revision: D9560577 fbshipit-source-id: ef4998107ed51ea374853bab7cbe09e3232caa0c --- tests/YGLoggerTest.cpp | 50 +++++++++++++++++++++++++++++++++++++----- yoga/YGConfig.cpp | 17 ++++++++------ yoga/YGConfig.h | 11 +++++----- yoga/Yoga.cpp | 9 +++++--- yoga/Yoga.h | 1 + 5 files changed, 68 insertions(+), 20 deletions(-) diff --git a/tests/YGLoggerTest.cpp b/tests/YGLoggerTest.cpp index 1b84ee6b..fd620cc9 100644 --- a/tests/YGLoggerTest.cpp +++ b/tests/YGLoggerTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include #include #include @@ -23,6 +23,46 @@ int _unmanagedLogger(const YGConfigRef config, } } +TEST(YogaTest, config_print_tree_enabled) { + writeBuffer[0] = '\0'; + const YGConfigRef config = YGConfigNew(); + YGConfigSetPrintTreeFlag(config, true); + YGConfigSetLogger(config, _unmanagedLogger); + const YGNodeRef root = YGNodeNewWithConfig(config); + const YGNodeRef child0 = YGNodeNewWithConfig(config); + const YGNodeRef child1 = YGNodeNewWithConfig(config); + YGNodeInsertChild(root, child0, 0); + YGNodeInsertChild(root, child1, 1); + YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR); + YGConfigSetLogger(config, NULL); + YGNodeFreeRecursive(root); + + const char* expected = + "
\n " + "
\n
\n
"; + ASSERT_STREQ(expected, writeBuffer); +} + +TEST(YogaTest, config_print_tree_disabled) { + writeBuffer[0] = '\0'; + const YGConfigRef config = YGConfigNew(); + YGConfigSetPrintTreeFlag(config, false); + YGConfigSetLogger(config, _unmanagedLogger); + const YGNodeRef root = YGNodeNewWithConfig(config); + const YGNodeRef child0 = YGNodeNewWithConfig(config); + const YGNodeRef child1 = YGNodeNewWithConfig(config); + YGNodeInsertChild(root, child0, 0); + YGNodeInsertChild(root, child1, 1); + YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR); + YGConfigSetLogger(config, NULL); + YGNodeFreeRecursive(root); + + const char* expected = ""; + ASSERT_STREQ(expected, writeBuffer); +} + TEST(YogaTest, logger_default_node_should_print_no_style_info) { writeBuffer[0] = '\0'; const YGConfigRef config = YGConfigNew(); diff --git a/yoga/YGConfig.cpp b/yoga/YGConfig.cpp index 5cee5278..a52f93c2 100644 --- a/yoga/YGConfig.cpp +++ b/yoga/YGConfig.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGConfig.h" const std::array @@ -15,5 +15,8 @@ YGConfig::YGConfig(YGLogger logger) useWebDefaults(false), useLegacyStretchBehaviour(false), shouldDiffLayoutWithoutLegacyStretchBehaviour(false), - pointScaleFactor(1.0f), logger(logger), cloneNodeCallback(nullptr), - context(nullptr) {} + pointScaleFactor(1.0f), + logger(logger), + cloneNodeCallback(nullptr), + context(nullptr), + printTree(false) {} diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index 0f655d1b..98d7a217 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 "Yoga-internal.h" #include "Yoga.h" @@ -18,6 +18,7 @@ struct YGConfig { YGLogger logger; YGCloneNodeFunc cloneNodeCallback; void* context; + bool printTree; YGConfig(YGLogger logger); }; diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index c6d38bb4..a4bd3f1a 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -198,6 +198,10 @@ bool YGNodeGetHasNewLayout(YGNodeRef node) { return node->getHasNewLayout(); } +void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled) { + config->printTree = enabled; +} + void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout) { node->setHasNewLayout(hasNewLayout); } @@ -3535,7 +3539,6 @@ static void YGNodelayoutImpl( } uint32_t gDepth = 0; -bool gPrintTree = false; bool gPrintChanges = false; bool gPrintSkips = false; @@ -4111,7 +4114,7 @@ void YGNodeCalculateLayout( node->getLayout().direction, ownerWidth, ownerHeight, ownerWidth); YGRoundToPixelGrid(node, node->getConfig()->pointScaleFactor, 0.0f, 0.0f); - if (gPrintTree) { + if (node->getConfig()->printTree) { YGNodePrint( node, (YGPrintOptions)( @@ -4163,7 +4166,7 @@ void YGNodeCalculateLayout( node->setLayoutDoesLegacyFlagAffectsLayout( !originalNode->isLayoutTreeEqualToNode(*node)); - if (gPrintTree) { + if (originalNode->getConfig()->printTree) { YGNodePrint( originalNode, (YGPrintOptions)( diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 5bcbe2ab..bd537a3c 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -155,6 +155,7 @@ WIN_EXPORT void YGNodeCopyStyle( void* YGNodeGetContext(YGNodeRef node); void YGNodeSetContext(YGNodeRef node, void* context); +void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled); YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node); void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc); YGBaselineFunc YGNodeGetBaselineFunc(YGNodeRef node); From d6ba8326d1904151f6b533d94ea40cd6961e3e52 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Thu, 30 Aug 2018 04:40:48 -0700 Subject: [PATCH 065/189] Expose printTree property of YGConfig to jni Summary: Exposes printTree property of YGConfig to jni Reviewed By: IanChilds Differential Revision: D9561097 fbshipit-source-id: 1bf86a63ad5e9baa107e36d429209b9061e6676d --- java/com/facebook/yoga/YogaConfig.java | 5 +++++ java/jni/YGJNI.cpp | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index 128f5328..01dbf70d 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -54,6 +54,11 @@ public class YogaConfig { jni_YGConfigSetUseWebDefaults(mNativePointer, useWebDefaults); } + private native void jni_YGConfigSetPrintTreeFlag(long nativePointer, boolean enable); + public void setPrintTreeFlag(boolean enable) { + jni_YGConfigSetPrintTreeFlag(mNativePointer, enable); + } + private native void jni_YGConfigSetPointScaleFactor(long nativePointer, float pixelsInPoint); public void setPointScaleFactor(float pixelsInPoint) { jni_YGConfigSetPointScaleFactor(mNativePointer, pixelsInPoint); diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 6233cc23..8234e38d 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -598,6 +598,14 @@ void jni_YGConfigSetUseWebDefaults( YGConfigSetUseWebDefaults(config, useWebDefaults); } +void jni_YGConfigSetPrintTreeFlag( + alias_ref, + jlong nativePointer, + jboolean enable) { + const YGConfigRef config = _jlong2YGConfigRef(nativePointer); + YGConfigSetPrintTreeFlag(config, enable); +} + void jni_YGConfigSetPointScaleFactor( alias_ref, jlong nativePointer, @@ -760,6 +768,7 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod(jni_YGConfigFree), YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), + YGMakeNativeMethod(jni_YGConfigSetPrintTreeFlag), YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), YGMakeNativeMethod(jni_YGConfigSetLogger), From 238d7ba98ffa9fcecbd7ae1b448688cb396e0b15 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Fri, 31 Aug 2018 17:49:38 -0700 Subject: [PATCH 066/189] Remove unused loads from build files. Summary: Unused loads hurt readability and take time to process. Reviewed By: hramos Differential Revision: D9494120 fbshipit-source-id: 455b56efadab1cb976344cffcb427772bfda2f71 --- csharp/BUCK | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/BUCK b/csharp/BUCK index 21e3b23f..610c1617 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -6,10 +6,9 @@ load( "//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", - "is_apple_platform", + "yoga_apple_binary", "yoga_cxx_library", "yoga_dep", - "yoga_apple_binary", ) COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"] From e224a29d1cbfd4d662392a7c69e0939d9278c3cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Tue, 11 Sep 2018 15:27:47 -0700 Subject: [PATCH 067/189] Update copyright headers to yearless format Summary: This change drops the year from the copyright headers and the LICENSE file. Reviewed By: yungsters Differential Revision: D9727774 fbshipit-source-id: df4fc1e4390733fe774b1a160dd41b4a3d83302a --- BUCK | 2 +- CMakeLists.txt | 2 +- LICENSE | 2 +- YogaKit/BUCK | 2 +- YogaKit/Source/UIView+Yoga.h | 2 +- YogaKit/Source/UIView+Yoga.m | 2 +- YogaKit/Source/YGLayout+Private.h | 2 +- YogaKit/Source/YGLayout.h | 2 +- YogaKit/Source/YGLayout.m | 2 +- YogaKit/Source/YGLayoutExtensions.swift | 2 +- YogaKit/Tests/YogaKitTests.m | 2 +- android/BUCK | 2 +- android/sample/java/com/facebook/samples/yoga/BUCK | 2 +- android/src/main/AndroidManifest.xml | 2 +- android/src/main/java/com/facebook/yoga/android/BUCK | 2 +- .../java/com/facebook/yoga/android/VirtualYogaLayout.java | 2 +- .../src/main/java/com/facebook/yoga/android/YogaLayout.java | 2 +- .../java/com/facebook/yoga/android/YogaViewLayoutFactory.java | 2 +- android/src/main/res/values/attrs.xml | 2 +- benchmark/BUCK | 2 +- benchmark/YGBenchmark.c | 2 +- csharp/Android/Facebook.Yoga.Android.Tests/MainActivity.cs | 2 +- csharp/BUCK | 2 +- csharp/Facebook.Yoga/BaselineFunction.cs | 2 +- csharp/Facebook.Yoga/Logger.cs | 2 +- csharp/Facebook.Yoga/MeasureFunction.cs | 2 +- csharp/Facebook.Yoga/MeasureOutput.cs | 2 +- csharp/Facebook.Yoga/Native.cs | 2 +- csharp/Facebook.Yoga/YGConfigHandle.cs | 2 +- csharp/Facebook.Yoga/YGNodeHandle.cs | 2 +- csharp/Facebook.Yoga/YogaAlign.cs | 2 +- csharp/Facebook.Yoga/YogaBaselineFunc.cs | 2 +- csharp/Facebook.Yoga/YogaConfig.cs | 2 +- csharp/Facebook.Yoga/YogaConstants.cs | 2 +- csharp/Facebook.Yoga/YogaDimension.cs | 2 +- csharp/Facebook.Yoga/YogaDirection.cs | 2 +- csharp/Facebook.Yoga/YogaDisplay.cs | 2 +- csharp/Facebook.Yoga/YogaEdge.cs | 2 +- csharp/Facebook.Yoga/YogaExperimentalFeature.cs | 2 +- csharp/Facebook.Yoga/YogaFlexDirection.cs | 2 +- csharp/Facebook.Yoga/YogaJustify.cs | 2 +- csharp/Facebook.Yoga/YogaLogLevel.cs | 2 +- csharp/Facebook.Yoga/YogaLogger.cs | 2 +- csharp/Facebook.Yoga/YogaMeasureFunc.cs | 2 +- csharp/Facebook.Yoga/YogaMeasureMode.cs | 2 +- csharp/Facebook.Yoga/YogaNode.Spacing.cs | 2 +- csharp/Facebook.Yoga/YogaNode.cs | 2 +- csharp/Facebook.Yoga/YogaNodeType.cs | 2 +- csharp/Facebook.Yoga/YogaOverflow.cs | 2 +- csharp/Facebook.Yoga/YogaPositionType.cs | 2 +- csharp/Facebook.Yoga/YogaPrintOptions.cs | 2 +- csharp/Facebook.Yoga/YogaSize.cs | 2 +- csharp/Facebook.Yoga/YogaUnit.cs | 2 +- csharp/Facebook.Yoga/YogaValue.cs | 2 +- csharp/Facebook.Yoga/YogaValueExtensions.cs | 2 +- csharp/Facebook.Yoga/YogaWrap.cs | 2 +- csharp/Mac/ApiDefinition.cs | 2 +- csharp/Mac/Facebook.Yoga.Mac.Tests/Main.cs | 2 +- csharp/Unity/pack.sh | 2 +- .../Facebook.Yoga.Desktop.Tests/Properties/AssemblyInfo.cs | 2 +- csharp/Windows/Facebook.Yoga/Properties/AssemblyInfo.cs | 2 +- csharp/Yoga/YGInterop.cpp | 2 +- csharp/Yoga/YGInterop.h | 2 +- csharp/Yoga/dllmain.cpp | 2 +- csharp/Yoga/stdafx.cpp | 2 +- csharp/Yoga/stdafx.h | 2 +- csharp/Yoga/targetver.h | 2 +- csharp/iOS/Facebook.Yoga.iOS.Tests/Main.cs | 2 +- csharp/iOS/Facebook.Yoga.iOS.Tests/UnitTestAppDelegate.cs | 2 +- csharp/iOS/Facebook.Yoga.iOS/ApiDefinition.cs | 2 +- csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGAlignContentTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGAlignItemsTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGAlignSelfTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGAndroidNewsFeed.cs | 2 +- csharp/tests/Facebook.Yoga/YGBorderTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGDimensionTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGDisplayTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGFlexDirectionTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGFlexTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGFlexWrapTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGMarginTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGPaddingTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGPercentageTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGRoundingTest.cs | 2 +- csharp/tests/Facebook.Yoga/YGSizeOverflowTest.cs | 2 +- csharp/tests/Facebook.Yoga/YogaConfigTest.cs | 2 +- csharp/tests/Facebook.Yoga/YogaNodeSpacingTest.cs | 2 +- csharp/tests/Facebook.Yoga/YogaNodeTest.cs | 2 +- enums.py | 4 ++-- .../components/lib/yoga/src/main/cpp/yoga/Yoga-internal.h | 2 +- gentest/gentest-cpp.js | 2 +- gentest/gentest-cs.js | 2 +- gentest/gentest-java.js | 2 +- gentest/gentest-javascript.js | 2 +- gentest/gentest.js | 2 +- java/BUCK | 2 +- java/CMakeLists.txt | 2 +- java/com/facebook/yoga/YogaAlign.java | 2 +- java/com/facebook/yoga/YogaBaselineFunction.java | 2 +- java/com/facebook/yoga/YogaConfig.java | 2 +- java/com/facebook/yoga/YogaConstants.java | 2 +- java/com/facebook/yoga/YogaDimension.java | 2 +- java/com/facebook/yoga/YogaDirection.java | 2 +- java/com/facebook/yoga/YogaDisplay.java | 2 +- java/com/facebook/yoga/YogaEdge.java | 2 +- java/com/facebook/yoga/YogaExperimentalFeature.java | 2 +- java/com/facebook/yoga/YogaFlexDirection.java | 2 +- java/com/facebook/yoga/YogaJustify.java | 2 +- java/com/facebook/yoga/YogaLogLevel.java | 2 +- java/com/facebook/yoga/YogaLogger.java | 2 +- java/com/facebook/yoga/YogaMeasureFunction.java | 2 +- java/com/facebook/yoga/YogaMeasureMode.java | 2 +- java/com/facebook/yoga/YogaMeasureOutput.java | 2 +- java/com/facebook/yoga/YogaNode.java | 2 +- java/com/facebook/yoga/YogaNodeCloneFunction.java | 2 +- java/com/facebook/yoga/YogaNodeType.java | 2 +- java/com/facebook/yoga/YogaOverflow.java | 2 +- java/com/facebook/yoga/YogaPositionType.java | 2 +- java/com/facebook/yoga/YogaPrintOptions.java | 2 +- java/com/facebook/yoga/YogaUnit.java | 2 +- java/com/facebook/yoga/YogaValue.java | 2 +- java/com/facebook/yoga/YogaWrap.java | 2 +- java/jni/YGJNI.cpp | 2 +- .../src/main/java/com/facebook/proguard/annotations/BUCK | 2 +- .../java/com/facebook/proguard/annotations/DoNotStrip.java | 2 +- java/res/values/strings.xml | 2 +- java/tests/com/facebook/yoga/TestParametrization.java | 2 +- java/tests/com/facebook/yoga/YGAbsolutePositionTest.java | 2 +- java/tests/com/facebook/yoga/YGAlignContentTest.java | 2 +- java/tests/com/facebook/yoga/YGAlignItemsTest.java | 2 +- java/tests/com/facebook/yoga/YGAlignSelfTest.java | 2 +- java/tests/com/facebook/yoga/YGAndroidNewsFeed.java | 2 +- java/tests/com/facebook/yoga/YGBorderTest.java | 2 +- java/tests/com/facebook/yoga/YGDimensionTest.java | 2 +- java/tests/com/facebook/yoga/YGDisplayTest.java | 2 +- java/tests/com/facebook/yoga/YGFlexDirectionTest.java | 2 +- java/tests/com/facebook/yoga/YGFlexTest.java | 2 +- java/tests/com/facebook/yoga/YGFlexWrapTest.java | 2 +- java/tests/com/facebook/yoga/YGJustifyContentTest.java | 2 +- java/tests/com/facebook/yoga/YGMarginTest.java | 2 +- java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java | 2 +- java/tests/com/facebook/yoga/YGPaddingTest.java | 2 +- java/tests/com/facebook/yoga/YGPercentageTest.java | 2 +- java/tests/com/facebook/yoga/YGRoundingTest.java | 2 +- java/tests/com/facebook/yoga/YGSizeOverflowTest.java | 2 +- java/tests/com/facebook/yoga/YogaLoggerTest.java | 2 +- java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java | 2 +- java/tests/com/facebook/yoga/YogaNodeTest.java | 2 +- java/tests/com/facebook/yoga/YogaValueTest.java | 2 +- javascript/sources/Config.cc | 2 +- javascript/sources/Config.hh | 2 +- javascript/sources/Layout.hh | 2 +- javascript/sources/Node.cc | 2 +- javascript/sources/Node.hh | 2 +- javascript/sources/Size.hh | 2 +- javascript/sources/YGEnums.js | 2 +- javascript/sources/entry-browser.js | 2 +- javascript/sources/entry-common.js | 2 +- javascript/sources/entry-node.js | 2 +- javascript/sources/global.cc | 2 +- javascript/sources/global.hh | 2 +- javascript/sources/nbind.cc | 2 +- javascript/tests/Benchmarks/YGBenchmark.js | 2 +- javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js | 2 +- javascript/tests/Facebook.Yoga/YGAlignContentTest.js | 2 +- javascript/tests/Facebook.Yoga/YGAlignItemsTest.js | 2 +- javascript/tests/Facebook.Yoga/YGAlignSelfTest.js | 2 +- javascript/tests/Facebook.Yoga/YGAndroidNewsFeed.js | 2 +- javascript/tests/Facebook.Yoga/YGBorderTest.js | 2 +- javascript/tests/Facebook.Yoga/YGComputedBorderTest.js | 2 +- javascript/tests/Facebook.Yoga/YGComputedMarginTest.js | 2 +- javascript/tests/Facebook.Yoga/YGComputedPaddingTest.js | 2 +- javascript/tests/Facebook.Yoga/YGDimensionTest.js | 2 +- javascript/tests/Facebook.Yoga/YGDisplayTest.js | 2 +- javascript/tests/Facebook.Yoga/YGFlexDirectionTest.js | 2 +- javascript/tests/Facebook.Yoga/YGFlexTest.js | 2 +- javascript/tests/Facebook.Yoga/YGFlexWrapTest.js | 2 +- javascript/tests/Facebook.Yoga/YGJustifyContentTest.js | 2 +- javascript/tests/Facebook.Yoga/YGMarginTest.js | 2 +- javascript/tests/Facebook.Yoga/YGMeasureCacheTest.js | 2 +- javascript/tests/Facebook.Yoga/YGMeasureTest.js | 2 +- javascript/tests/Facebook.Yoga/YGMinMaxDimensionTest.js | 2 +- javascript/tests/Facebook.Yoga/YGPaddingTest.js | 2 +- javascript/tests/Facebook.Yoga/YGPercentageTest.js | 2 +- javascript/tests/Facebook.Yoga/YGRoundingTest.js | 2 +- javascript/tests/Facebook.Yoga/YGSizeOverflowTest.js | 2 +- javascript/tests/run-bench.js | 2 +- javascript/tests/tools.js | 2 +- lib/android-support/BUCK | 2 +- lib/appcompat/BUCK | 2 +- lib/fb/BUCK | 2 +- lib/fb/src/main/AndroidManifest.xml | 2 +- lib/fb/src/main/cpp/CMakeLists.txt | 2 +- lib/fb/src/main/cpp/assert.cpp | 2 +- lib/fb/src/main/cpp/include/fb/ALog.h | 2 +- lib/fb/src/main/cpp/include/fb/Countable.h | 2 +- lib/fb/src/main/cpp/include/fb/Environment.h | 2 +- lib/fb/src/main/cpp/include/fb/ProgramLocation.h | 2 +- lib/fb/src/main/cpp/include/fb/RefPtr.h | 2 +- lib/fb/src/main/cpp/include/fb/StaticInitialized.h | 2 +- lib/fb/src/main/cpp/include/fb/ThreadLocal.h | 2 +- lib/fb/src/main/cpp/include/fb/assert.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Boxed.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/ByteBuffer.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Common.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Context.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Exceptions.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/File.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Iterator-inl.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Iterator.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/JThread.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Meta-forward.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Meta.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/NativeRunnable.h | 2 +- .../src/main/cpp/include/fb/fbjni/ReferenceAllocators-inl.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/References-forward.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/References.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/Registration.h | 2 +- lib/fb/src/main/cpp/include/fb/fbjni/TypeTraits.h | 2 +- lib/fb/src/main/cpp/include/fb/noncopyable.h | 2 +- lib/fb/src/main/cpp/include/fb/nonmovable.h | 2 +- lib/fb/src/main/cpp/include/fb/visibility.h | 2 +- lib/fb/src/main/cpp/include/jni/Countable.h | 2 +- lib/fb/src/main/cpp/include/jni/GlobalReference.h | 2 +- lib/fb/src/main/cpp/include/jni/LocalReference.h | 2 +- lib/fb/src/main/cpp/include/jni/LocalString.h | 2 +- lib/fb/src/main/cpp/include/jni/Registration.h | 2 +- lib/fb/src/main/cpp/include/jni/WeakReference.h | 2 +- lib/fb/src/main/cpp/include/jni/jni_helpers.h | 2 +- lib/fb/src/main/cpp/jni/ByteBuffer.cpp | 2 +- lib/fb/src/main/cpp/jni/Countable.cpp | 2 +- lib/fb/src/main/cpp/jni/Environment.cpp | 2 +- lib/fb/src/main/cpp/jni/Exceptions.cpp | 2 +- lib/fb/src/main/cpp/jni/Hybrid.cpp | 2 +- lib/fb/src/main/cpp/jni/LocalString.cpp | 2 +- lib/fb/src/main/cpp/jni/OnLoad.cpp | 2 +- lib/fb/src/main/cpp/jni/References.cpp | 2 +- lib/fb/src/main/cpp/jni/WeakReference.cpp | 2 +- lib/fb/src/main/cpp/jni/fbjni.cpp | 2 +- lib/fb/src/main/cpp/jni/jni_helpers.cpp | 2 +- lib/fb/src/main/cpp/log.cpp | 2 +- lib/fb/src/main/cpp/onload.cpp | 2 +- lib/fb/src/main/java/com/facebook/jni/BUCK | 2 +- lib/fb/src/main/java/com/facebook/jni/CppException.java | 2 +- .../main/java/com/facebook/jni/CppSystemErrorException.java | 2 +- lib/fb/src/main/java/com/facebook/jni/IteratorHelper.java | 2 +- lib/fb/src/main/java/com/facebook/jni/MapIteratorHelper.java | 2 +- lib/fb/src/main/java/com/facebook/jni/NativeRunnable.java | 2 +- .../src/main/java/com/facebook/jni/UnknownCppException.java | 2 +- lib/gtest/BUCK | 2 +- lib/infer-annotations/BUCK | 2 +- lib/jni/BUCK | 2 +- lib/jni/jni.h | 2 +- lib/jsr-305/BUCK | 2 +- lib/junit/BUCK | 2 +- lib/soloader/BUCK | 2 +- tests/YGAbsolutePositionTest.cpp | 2 +- tests/YGAlignBaselineTest.cpp | 2 +- tests/YGAlignContentTest.cpp | 2 +- tests/YGAlignItemsTest.cpp | 2 +- tests/YGAlignSelfTest.cpp | 2 +- tests/YGAndroidNewsFeed.cpp | 2 +- tests/YGAspectRatioTest.cpp | 2 +- tests/YGBaselineFuncTest.cpp | 2 +- tests/YGBorderTest.cpp | 2 +- tests/YGComputedMarginTest.cpp | 2 +- tests/YGComputedPaddingTest.cpp | 2 +- tests/YGDefaultValuesTest.cpp | 2 +- tests/YGDimensionTest.cpp | 2 +- tests/YGDirtiedTest.cpp | 2 +- tests/YGDirtyMarkingTest.cpp | 2 +- tests/YGDisplayTest.cpp | 2 +- tests/YGEdgeTest.cpp | 2 +- tests/YGFlexDirectionTest.cpp | 2 +- tests/YGFlexTest.cpp | 2 +- tests/YGFlexWrapTest.cpp | 2 +- tests/YGInfiniteHeightTest.cpp | 2 +- tests/YGJustifyContentTest.cpp | 2 +- tests/YGLayoutDiffingTest.cpp | 2 +- tests/YGLoggerTest.cpp | 2 +- tests/YGMarginTest.cpp | 2 +- tests/YGMeasureCacheTest.cpp | 2 +- tests/YGMeasureModeTest.cpp | 2 +- tests/YGMeasureTest.cpp | 2 +- tests/YGMinMaxDimensionTest.cpp | 2 +- tests/YGNodeChildTest.cpp | 2 +- tests/YGPaddingTest.cpp | 2 +- tests/YGPercentageTest.cpp | 2 +- tests/YGPersistenceTest.cpp | 2 +- tests/YGRelayoutTest.cpp | 2 +- tests/YGRoundingFunctionTest.cpp | 2 +- tests/YGRoundingMeasureFuncTest.cpp | 2 +- tests/YGRoundingTest.cpp | 2 +- tests/YGSizeOverflowTest.cpp | 2 +- tests/YGStyleTest.cpp | 2 +- tests/YGTraversalTest.cpp | 2 +- tests/YGTreeMutationTest.cpp | 2 +- tests/YGZeroOutLayoutRecursivlyTest.cpp | 2 +- website/gatsby-config.js | 2 +- website/gatsby-node.js | 2 +- website/src/components/DocsSidebar.css | 2 +- website/src/components/DocsSidebar.js | 2 +- website/src/components/FacebookOSSLogo.js | 2 +- website/src/components/Footer.css | 2 +- website/src/components/Footer.js | 2 +- website/src/components/Padded.css | 2 +- website/src/components/Padded.js | 2 +- website/src/components/Page.css | 2 +- website/src/components/Page.js | 2 +- website/src/components/Playground/CodeGenerators.js | 2 +- website/src/components/Playground/CodeJavaScript.js | 2 +- website/src/components/Playground/CodeLitho.js | 2 +- website/src/components/Playground/CodeReactNative.js | 2 +- website/src/components/Playground/EditValue.js | 2 +- website/src/components/Playground/Editor.css | 2 +- website/src/components/Playground/Editor.js | 2 +- website/src/components/Playground/InfoText.css | 2 +- website/src/components/Playground/InfoText.js | 2 +- website/src/components/Playground/LayoutRecord.js | 2 +- website/src/components/Playground/PositionGuide.css | 2 +- website/src/components/Playground/PositionGuide.js | 2 +- website/src/components/Playground/PositionRecord.js | 2 +- website/src/components/Playground/Sidebar.css | 2 +- website/src/components/Playground/Sidebar.js | 2 +- website/src/components/Playground/URLShortener.js | 2 +- website/src/components/Playground/YogaEnumSelect.css | 2 +- website/src/components/Playground/YogaEnumSelect.js | 2 +- website/src/components/Playground/YogaNode.css | 2 +- website/src/components/Playground/YogaNode.js | 2 +- website/src/components/Playground/YogaPositionEditor.css | 2 +- website/src/components/Playground/YogaPositionEditor.js | 2 +- website/src/components/Playground/index.css | 2 +- website/src/components/Playground/index.js | 2 +- website/src/components/Toolbar.css | 2 +- website/src/components/Toolbar.js | 2 +- website/src/pages/404.js | 2 +- website/src/pages/docs/index.css | 2 +- website/src/pages/docs/index.js | 2 +- website/src/pages/index.css | 2 +- website/src/pages/index.js | 2 +- website/src/pages/playground/index.js | 2 +- website/src/templates/index.css | 2 +- website/src/templates/withPlayground.js | 2 +- website/src/templates/withoutPlayground.js | 2 +- yoga/Utils.cpp | 2 +- yoga/Utils.h | 2 +- yoga/YGConfig.cpp | 2 +- yoga/YGConfig.h | 2 +- yoga/YGEnums.cpp | 2 +- yoga/YGEnums.h | 2 +- yoga/YGFloatOptional.cpp | 2 +- yoga/YGFloatOptional.h | 2 +- yoga/YGLayout.cpp | 2 +- yoga/YGLayout.h | 2 +- yoga/YGMacros.h | 2 +- yoga/YGNode.cpp | 2 +- yoga/YGNode.h | 2 +- yoga/YGNodePrint.cpp | 2 +- yoga/YGNodePrint.h | 2 +- yoga/YGStyle.cpp | 2 +- yoga/YGStyle.h | 2 +- yoga/Yoga-internal.h | 2 +- yoga/Yoga.cpp | 2 +- yoga/Yoga.h | 2 +- yogacore/src/main/AndroidManifest.xml | 2 +- 376 files changed, 377 insertions(+), 377 deletions(-) diff --git a/BUCK b/BUCK index 699e7a61..aeeac450 100644 --- a/BUCK +++ b/BUCK @@ -1,4 +1,4 @@ -# Copyright (c) 2014-present, Facebook, Inc. +# 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. diff --git a/CMakeLists.txt b/CMakeLists.txt index 64bd1606..5a89aced 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2014-present, Facebook, Inc. +# 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. diff --git a/LICENSE b/LICENSE index cde61b6c..b96dcb04 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014-present, Facebook, Inc. +Copyright (c) Facebook, Inc. and its affiliates. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/YogaKit/BUCK b/YogaKit/BUCK index f4ea3567..c3d534e8 100644 --- a/YogaKit/BUCK +++ b/YogaKit/BUCK @@ -1,4 +1,4 @@ -# Copyright (c) 2014-present, Facebook, Inc. +# 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. diff --git a/YogaKit/Source/UIView+Yoga.h b/YogaKit/Source/UIView+Yoga.h index 5a5ae00a..68675188 100644 --- a/YogaKit/Source/UIView+Yoga.h +++ b/YogaKit/Source/UIView+Yoga.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/YogaKit/Source/UIView+Yoga.m b/YogaKit/Source/UIView+Yoga.m index eb360a8c..963362d5 100644 --- a/YogaKit/Source/UIView+Yoga.m +++ b/YogaKit/Source/UIView+Yoga.m @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/YogaKit/Source/YGLayout+Private.h b/YogaKit/Source/YGLayout+Private.h index d810fa87..e680222d 100644 --- a/YogaKit/Source/YGLayout+Private.h +++ b/YogaKit/Source/YGLayout+Private.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/YogaKit/Source/YGLayout.h b/YogaKit/Source/YGLayout.h index 3bfb1b89..37aa2345 100644 --- a/YogaKit/Source/YGLayout.h +++ b/YogaKit/Source/YGLayout.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/YogaKit/Source/YGLayout.m b/YogaKit/Source/YGLayout.m index ad0ef7f2..836b34a5 100644 --- a/YogaKit/Source/YGLayout.m +++ b/YogaKit/Source/YGLayout.m @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/YogaKit/Source/YGLayoutExtensions.swift b/YogaKit/Source/YGLayoutExtensions.swift index dc91c1d2..fa414449 100644 --- a/YogaKit/Source/YGLayoutExtensions.swift +++ b/YogaKit/Source/YGLayoutExtensions.swift @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/YogaKit/Tests/YogaKitTests.m b/YogaKit/Tests/YogaKitTests.m index 8e07462a..945d4d24 100644 --- a/YogaKit/Tests/YogaKitTests.m +++ b/YogaKit/Tests/YogaKitTests.m @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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. diff --git a/android/BUCK b/android/BUCK index 35f91a0d..f72dde8b 100644 --- a/android/BUCK +++ b/android/BUCK @@ -1,4 +1,4 @@ -# Copyright (c) 2014-present, Facebook, Inc. +# 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. diff --git a/android/sample/java/com/facebook/samples/yoga/BUCK b/android/sample/java/com/facebook/samples/yoga/BUCK index 5d3b601f..31609016 100644 --- a/android/sample/java/com/facebook/samples/yoga/BUCK +++ b/android/sample/java/com/facebook/samples/yoga/BUCK @@ -1,4 +1,4 @@ -# Copyright (c) 2014-present, Facebook, Inc. +# Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the license found in the # LICENSE-examples file in the root directory of this source tree. diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index b5ae6f2f..dd2d58c6 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + diff --git a/YogaKit/YogaKitSample/YogaKitSample.xcworkspace/contents.xcworkspacedata b/YogaKit/YogaKitSample/YogaKitSample.xcworkspace/contents.xcworkspacedata index c64c0fa8..ad8697b8 100644 --- a/YogaKit/YogaKitSample/YogaKitSample.xcworkspace/contents.xcworkspacedata +++ b/YogaKit/YogaKitSample/YogaKitSample.xcworkspace/contents.xcworkspacedata @@ -1,3 +1,10 @@ + + diff --git a/android/build.gradle b/android/build.gradle index 042459a2..7dc4904b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,3 +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. + */ + apply plugin: 'com.jfrog.bintray' apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' diff --git a/android/gradle.properties b/android/gradle.properties index e03c3c0c..76b74e27 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +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. +# + GROUP=com.facebook.yoga.android POM_NAME=YogaLayout POM_DESCRIPTION=YogaLayout diff --git a/build.gradle b/build.gradle index 7cbb3cf7..d2202c63 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +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. + */ + // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { diff --git a/csharp/Mac/run-tests.sh b/csharp/Mac/run-tests.sh index 88b899e6..fe69016a 100755 --- a/csharp/Mac/run-tests.sh +++ b/csharp/Mac/run-tests.sh @@ -1,2 +1,10 @@ #!/bin/sh -./csharp/Mac/Facebook.Yoga.Mac.Tests/bin/Release/Facebook.Yoga.Mac.Tests.app/Contents/MacOS/Facebook.Yoga.Mac.Tests \ No newline at end of file + +# +# 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. +# + +./csharp/Mac/Facebook.Yoga.Mac.Tests/bin/Release/Facebook.Yoga.Mac.Tests.app/Contents/MacOS/Facebook.Yoga.Mac.Tests diff --git a/csharp/build-native.sh b/csharp/build-native.sh index c614744e..eaada621 100755 --- a/csharp/build-native.sh +++ b/csharp/build-native.sh @@ -1,4 +1,12 @@ #!/bin/sh + +# +# 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. +# + cd `dirname "$0"` echo $ANDROID_SDK BUCK_RELEASE=2018.02.16.01 @@ -22,4 +30,3 @@ $BUCK build \ //csharp:yoganet-macosx \ //csharp:yoganet#android-armv7,shared \ //csharp:yoganet#android-x86,shared - diff --git a/gradle.properties b/gradle.properties index 5ee043c0..a514ea0a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +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. +# + # Project-wide Gradle settings. org.gradle.jvmargs=-Xmx1536M diff --git a/java/build.gradle b/java/build.gradle index 85e94961..772886e0 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -1,3 +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. + */ + apply plugin: 'com.jfrog.bintray' apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' diff --git a/java/gradle.properties b/java/gradle.properties index 1679cf1d..eb063444 100644 --- a/java/gradle.properties +++ b/java/gradle.properties @@ -1,3 +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. +# + GROUP=com.facebook.yoga POM_NAME=Yoga POM_DESCRIPTION=Java bindings to libyoga diff --git a/java/proguard-annotations/build.gradle b/java/proguard-annotations/build.gradle index bbfeb03c..3f252b3f 100644 --- a/java/proguard-annotations/build.gradle +++ b/java/proguard-annotations/build.gradle @@ -1 +1,8 @@ +/** + * 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. + */ + apply plugin: 'java' diff --git a/javascript/sources/Value.hh b/javascript/sources/Value.hh index bfcc2b81..a44cbbbe 100644 --- a/javascript/sources/Value.hh +++ b/javascript/sources/Value.hh @@ -1,3 +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. + */ + #pragma once #include diff --git a/lib/fb/build.gradle b/lib/fb/build.gradle index 2b01b4c2..eb806477 100644 --- a/lib/fb/build.gradle +++ b/lib/fb/build.gradle @@ -1,3 +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. + */ + apply plugin: 'com.android.library' android { diff --git a/lib/fb/src/main/java/com/facebook/jni/fbjni.pro b/lib/fb/src/main/java/com/facebook/jni/fbjni.pro index 5b5b6454..3b3c2b61 100644 --- a/lib/fb/src/main/java/com/facebook/jni/fbjni.pro +++ b/lib/fb/src/main/java/com/facebook/jni/fbjni.pro @@ -1,3 +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. +# + # For common use cases for the hybrid pattern, keep symbols which may # be referenced only from C++. diff --git a/scripts/android-setup.sh b/scripts/android-setup.sh index abc102a1..33b6e7a8 100644 --- a/scripts/android-setup.sh +++ b/scripts/android-setup.sh @@ -1,3 +1,12 @@ +#!/bin/bash + +# +# 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. +# + set -e function download() { diff --git a/scripts/deploy_jcenter.sh b/scripts/deploy_jcenter.sh index 897331a1..34c633df 100755 --- a/scripts/deploy_jcenter.sh +++ b/scripts/deploy_jcenter.sh @@ -1,4 +1,12 @@ #!/bin/bash + +# +# 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. +# + set -e ROOTDIR="$(dirname $0)/.." echo -e "\033[1;34m** We can deploy two libraries\n** (1) Java bindings to Yoga\n** (2) Android YogaLayout\n** Which do you want to ship today? \033[0m" diff --git a/scripts/publish-snapshot.sh b/scripts/publish-snapshot.sh index 145322b7..02c45457 100755 --- a/scripts/publish-snapshot.sh +++ b/scripts/publish-snapshot.sh @@ -1,6 +1,12 @@ #!/usr/bin/env bash # # Deploy a SNAPSHOT JAR after every successful CI run To Sonatype. + +# +# 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. # set -e diff --git a/settings.gradle b/settings.gradle index 93d836ba..1c136f10 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +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 ':yoga', ':yogacore', ':yoga-layout', ':yoga:proguard-annotations', ':libfb' project(':yoga').projectDir = file('java') project(':yoga:proguard-annotations').projectDir = file('java/proguard-annotations') diff --git a/tools/build_defs/oss/yoga_defs.bzl b/tools/build_defs/oss/yoga_defs.bzl index 5d717a86..6b3ac1d5 100644 --- a/tools/build_defs/oss/yoga_defs.bzl +++ b/tools/build_defs/oss/yoga_defs.bzl @@ -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. +# """Provides macros for working with yoga library.""" YOGA_ROOTS = ["//..."] diff --git a/website/src/components/Playground/CodeComponentKit.js b/website/src/components/Playground/CodeComponentKit.js index 9dd71a2f..74cc2db2 100644 --- a/website/src/components/Playground/CodeComponentKit.js +++ b/website/src/components/Playground/CodeComponentKit.js @@ -1,3 +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. + */ + // @flow import yoga from 'yoga-layout/dist/entry-browser'; import LayoutRecord from './LayoutRecord'; diff --git a/website/src/components/Playground/CodeGenerators.css b/website/src/components/Playground/CodeGenerators.css index 483e7ab3..261986d2 100644 --- a/website/src/components/Playground/CodeGenerators.css +++ b/website/src/components/Playground/CodeGenerators.css @@ -1,3 +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. + */ + .CodeGeneratorsTitle { display: flex; justify-content: space-between; diff --git a/website/src/components/Playground/URLShortener.css b/website/src/components/Playground/URLShortener.css index e319fb2b..fe3da49c 100644 --- a/website/src/components/Playground/URLShortener.css +++ b/website/src/components/Playground/URLShortener.css @@ -1,2 +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. + */ + .URLShortener { } diff --git a/website/src/pages/playground/index.css b/website/src/pages/playground/index.css index b4f3e843..0ed0ad24 100644 --- a/website/src/pages/playground/index.css +++ b/website/src/pages/playground/index.css @@ -1,3 +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. + */ + .playground-page { display: flex; flex: 1; diff --git a/yogacore/build.gradle b/yogacore/build.gradle index c31d7294..122383b3 100644 --- a/yogacore/build.gradle +++ b/yogacore/build.gradle @@ -1,3 +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. + */ + apply plugin: 'com.android.library' android { From fad2ee1a640069fa50a74a7ee65cc69302929912 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Thu, 25 Oct 2018 08:02:04 -0700 Subject: [PATCH 085/189] Replaced default constructors with member assignments Reviewed By: davidaurelio Differential Revision: D10466125 fbshipit-source-id: ed92d1e054a8b5b9a6c8c09035173b11da45c368 --- yoga/YGConfig.cpp | 14 +-------- yoga/YGConfig.h | 16 +++++------ yoga/YGFloatOptional.h | 6 ++-- yoga/YGLayout.cpp | 22 --------------- yoga/YGLayout.h | 41 ++++++++++++++------------- yoga/YGStyle.cpp | 45 ----------------------------- yoga/YGStyle.h | 64 +++++++++++++++++++++++++++--------------- 7 files changed, 75 insertions(+), 133 deletions(-) diff --git a/yoga/YGConfig.cpp b/yoga/YGConfig.cpp index 646f8d92..e0edd3f7 100644 --- a/yoga/YGConfig.cpp +++ b/yoga/YGConfig.cpp @@ -7,16 +7,4 @@ */ #include "YGConfig.h" -const std::array - kYGDefaultExperimentalFeatures = {{false}}; - -YGConfig::YGConfig(YGLogger logger) - : experimentalFeatures(kYGDefaultExperimentalFeatures), - useWebDefaults(false), - useLegacyStretchBehaviour(false), - shouldDiffLayoutWithoutLegacyStretchBehaviour(false), - pointScaleFactor(1.0f), - logger(logger), - cloneNodeCallback(nullptr), - context(nullptr), - printTree(false) {} +YGConfig::YGConfig(YGLogger logger) : logger(logger) {} diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index 3718133a..941e0dcd 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -10,15 +10,15 @@ #include "Yoga.h" struct YGConfig { - std::array experimentalFeatures; - bool useWebDefaults; - bool useLegacyStretchBehaviour; - bool shouldDiffLayoutWithoutLegacyStretchBehaviour; - float pointScaleFactor; + std::array experimentalFeatures = {}; + bool useWebDefaults = false; + bool useLegacyStretchBehaviour = false; + bool shouldDiffLayoutWithoutLegacyStretchBehaviour = false; + float pointScaleFactor = 1.0f; YGLogger logger; - YGCloneNodeFunc cloneNodeCallback; - void* context; - bool printTree; + YGCloneNodeFunc cloneNodeCallback = nullptr; + void* context = nullptr; + bool printTree = false; YGConfig(YGLogger logger); }; diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 00acc313..2578b9dd 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -9,12 +9,12 @@ struct YGFloatOptional { private: - float value_; - bool isUndefined_; + float value_ = 0; + bool isUndefined_ = true; public: explicit YGFloatOptional(float value); - explicit YGFloatOptional() : value_(0), isUndefined_(true) {} + YGFloatOptional() = default; // Program will terminate if the value of an undefined is accessed. Please // make sure to check if the optional is defined before calling this function. diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index fea7015f..0f362f88 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -10,28 +10,6 @@ using namespace facebook; -const std::array kYGDefaultDimensionValues = { - {YGUndefined, YGUndefined}}; - -YGLayout::YGLayout() - : position(), - dimensions(kYGDefaultDimensionValues), - margin(), - border(), - padding(), - direction(YGDirectionInherit), - computedFlexBasisGeneration(0), - computedFlexBasis(YGFloatOptional()), - hadOverflow(false), - generationCount(0), - lastOwnerDirection((YGDirection)-1), - nextCachedMeasurementsIndex(0), - cachedMeasurements(), - measuredDimensions(kYGDefaultDimensionValues), - cachedLayout(YGCachedMeasurement()), - didUseLegacyFlag(false), - doesLegacyStretchFlagAffectsLayout(false) {} - bool YGLayout::operator==(YGLayout layout) const { bool isEqual = YGFloatArrayEqual(position, layout.position) && YGFloatArrayEqual(dimensions, layout.dimensions) && diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 22f2a1eb..812ed6bd 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -9,33 +9,36 @@ #include "YGFloatOptional.h" #include "Yoga-internal.h" -struct YGLayout { - std::array position; - std::array dimensions; - std::array margin; - std::array border; - std::array padding; - YGDirection direction; +constexpr std::array kYGDefaultDimensionValues = { + {YGUndefined, YGUndefined}}; - uint32_t computedFlexBasisGeneration; - YGFloatOptional computedFlexBasis; - bool hadOverflow; +struct YGLayout { + std::array position = {}; + std::array dimensions = kYGDefaultDimensionValues; + std::array margin = {}; + std::array border = {}; + std::array padding = {}; + YGDirection direction = YGDirectionInherit; + + uint32_t computedFlexBasisGeneration = 0; + YGFloatOptional computedFlexBasis = {}; + bool hadOverflow = false; // Instead of recomputing the entire layout every single time, we // cache some information to break early when nothing changed - uint32_t generationCount; - YGDirection lastOwnerDirection; + uint32_t generationCount = 0; + YGDirection lastOwnerDirection = (YGDirection)-1; - uint32_t nextCachedMeasurementsIndex; + uint32_t nextCachedMeasurementsIndex = 0; std::array - cachedMeasurements; - std::array measuredDimensions; + cachedMeasurements = {}; + std::array measuredDimensions = kYGDefaultDimensionValues; - YGCachedMeasurement cachedLayout; - bool didUseLegacyFlag; - bool doesLegacyStretchFlagAffectsLayout; + YGCachedMeasurement cachedLayout = YGCachedMeasurement(); + bool didUseLegacyFlag = false; + bool doesLegacyStretchFlagAffectsLayout = false; - YGLayout(); + YGLayout() = default; bool operator==(YGLayout layout) const; bool operator!=(YGLayout layout) const { diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 44fd9e50..46a65b28 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -7,51 +7,6 @@ */ #include "YGStyle.h" -const YGValue kYGValueUndefined = {0, YGUnitUndefined}; - -const YGValue kYGValueAuto = {0, YGUnitAuto}; - -const std::array kYGDefaultEdgeValuesUnit = { - {kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined}}; - -const std::array kYGDefaultDimensionValuesAutoUnit = { - {kYGValueAuto, kYGValueAuto}}; - -const std::array kYGDefaultDimensionValuesUnit = { - {kYGValueUndefined, kYGValueUndefined}}; - -YGStyle::YGStyle() - : direction(YGDirectionInherit), - flexDirection(YGFlexDirectionColumn), - justifyContent(YGJustifyFlexStart), - alignContent(YGAlignFlexStart), - alignItems(YGAlignStretch), - alignSelf(YGAlignAuto), - positionType(YGPositionTypeRelative), - flexWrap(YGWrapNoWrap), - overflow(YGOverflowVisible), - display(YGDisplayFlex), - flex(YGFloatOptional()), - flexGrow(YGFloatOptional()), - flexShrink(YGFloatOptional()), - flexBasis(kYGValueAuto), - margin(kYGDefaultEdgeValuesUnit), - position(kYGDefaultEdgeValuesUnit), - padding(kYGDefaultEdgeValuesUnit), - border(kYGDefaultEdgeValuesUnit), - dimensions(kYGDefaultDimensionValuesAutoUnit), - minDimensions(kYGDefaultDimensionValuesUnit), - maxDimensions(kYGDefaultDimensionValuesUnit), - aspectRatio(YGFloatOptional()) {} - // Yoga specific properties, not compatible with flexbox specification bool YGStyle::operator==(const YGStyle& style) { bool areNonFloatValuesEqual = direction == style.direction && diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index efd52fff..04a74545 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -10,34 +10,52 @@ #include "Yoga-internal.h" #include "Yoga.h" +constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; + +constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; + +constexpr std::array kYGDefaultEdgeValuesUnit = { + {kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined}}; + +constexpr std::array kYGDefaultDimensionValuesUnit = { + {kYGValueUndefined, kYGValueUndefined}}; + struct YGStyle { using Dimensions = std::array; - YGDirection direction; - YGFlexDirection flexDirection; - YGJustify justifyContent; - YGAlign alignContent; - YGAlign alignItems; - YGAlign alignSelf; - YGPositionType positionType; - YGWrap flexWrap; - YGOverflow overflow; - YGDisplay display; - YGFloatOptional flex; - YGFloatOptional flexGrow; - YGFloatOptional flexShrink; - YGValue flexBasis; - std::array margin; - std::array position; - std::array padding; - std::array border; - Dimensions dimensions; - Dimensions minDimensions; - Dimensions maxDimensions; + YGDirection direction = YGDirectionInherit; + YGFlexDirection flexDirection = YGFlexDirectionColumn; + YGJustify justifyContent = YGJustifyFlexStart; + YGAlign alignContent = YGAlignFlexStart; + YGAlign alignItems = YGAlignStretch; + YGAlign alignSelf = YGAlignAuto; + YGPositionType positionType = YGPositionTypeRelative; + YGWrap flexWrap = YGWrapNoWrap; + YGOverflow overflow = YGOverflowVisible; + YGDisplay display = YGDisplayFlex; + YGFloatOptional flex = {}; + YGFloatOptional flexGrow = {}; + YGFloatOptional flexShrink = {}; + YGValue flexBasis = kYGValueAuto; + std::array margin = kYGDefaultEdgeValuesUnit; + std::array position = kYGDefaultEdgeValuesUnit; + std::array padding = kYGDefaultEdgeValuesUnit; + std::array border = kYGDefaultEdgeValuesUnit; + Dimensions dimensions = {{kYGValueAuto, kYGValueAuto}}; + Dimensions minDimensions = kYGDefaultDimensionValuesUnit; + Dimensions maxDimensions = kYGDefaultDimensionValuesUnit; // Yoga specific properties, not compatible with flexbox specification - YGFloatOptional aspectRatio; + YGFloatOptional aspectRatio = {}; - YGStyle(); + YGStyle() = default; bool operator==(const YGStyle& style); bool operator!=(YGStyle style) { From eb2aeb3adbb2062842b70cd073b3a2980dba3cec Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Mon, 29 Oct 2018 03:07:44 -0700 Subject: [PATCH 086/189] corrected copyright header in gentest.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public We have changed Yoga’s license to a yearless format, but this was not reflected in the test generation script. This commit changes the corresponding template/. Reviewed By: davidaurelio Differential Revision: D10852787 fbshipit-source-id: 0b79e253be6174a218f9dc8de942fc2496a425c8 --- gentest/gentest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gentest/gentest.js b/gentest/gentest.js index 6a63ba05..6d3f5a46 100755 --- a/gentest/gentest.js +++ b/gentest/gentest.js @@ -42,7 +42,7 @@ function assert(condition, message) { function printTest(e, LTRContainer, RTLContainer, genericContainer) { e.push([ '/**', - ' * Copyright (c) 2014-present, Facebook, Inc.', + ' * 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.', From 1e4d0abc66840c6827c0a8248c99a34fc253e9fd Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Mon, 29 Oct 2018 04:28:50 -0700 Subject: [PATCH 087/189] using TestParametrization.NodeFactory in gentest-java.js to generate java tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public Our tests were manually parametrized, without adding the necessary code to the test case generation script. This commit makes the necessary changes so that test generation won’t overwrite the parametrization. Reviewed By: davidaurelio Differential Revision: D10853163 fbshipit-source-id: b5e41755df16a6a296cf2061fbb89c3f27f8574d --- gentest/gentest-java.js | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/gentest/gentest-java.js b/gentest/gentest-java.js index 6b6d34c4..033417e2 100644 --- a/gentest/gentest-java.js +++ b/gentest/gentest-java.js @@ -42,13 +42,29 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, { this.push([ 'package com.facebook.yoga;', '', - 'import org.junit.Test;', - '', 'import static org.junit.Assert.assertEquals;', '', + 'import org.junit.Test;', + 'import org.junit.runner.RunWith;', + 'import org.junit.runners.Parameterized;', + '', + '@RunWith(Parameterized.class)', 'public class YogaTest {', ]); this.pushIndent(); + this.push([ + '@Parameterized.Parameters(name = "{0}")', + 'public static Iterable nodeFactories() {', + ]); + this.pushIndent(); + this.push('return TestParametrization.nodeFactories();'); + this.popIndent(); + this.push('}'); + this.push([ + '', + '@Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory;', + '', + ]); }}, emitTestPrologue:{value:function(name, experiments) { @@ -64,7 +80,7 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, { }}, emitTestTreePrologue:{value:function(nodeName) { - this.push('final YogaNode ' + nodeName + ' = new YogaNode(config);'); + this.push('final YogaNode ' + nodeName + ' = createNode(config);'); }}, emitTestEpilogue:{value:function(experiments) { @@ -76,6 +92,11 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, { }}, emitEpilogue:{value:function(lines) { + this.push('private YogaNode createNode(YogaConfig config) {'); + this.pushIndent(); + this.push('return mNodeFactory.create(config);'); + this.popIndent(); + this.push('}'); this.popIndent(); this.push([ '}', From b7890fa2a8f45d771d79a1ee069b17fd1b7cc006 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Wed, 31 Oct 2018 10:13:02 -0700 Subject: [PATCH 088/189] adding missing generated test cases in csharp, java, js Summary: @public gentest.rb script generates tests in different languages cpp, java, csharp, js from html files. Some tests were missing from csharp, java and js test files. This diff adds those in all the test files Reviewed By: priteshrnandgaonkar Differential Revision: D10853971 fbshipit-source-id: 11d7cee5889dd1f5a7440f6802fca78cea17aa4d --- .../Facebook.Yoga/YGJustifyContentTest.cs | 154 +++++++++ gentest/fixtures/YGJustifyContentTest.html | 4 +- .../facebook/yoga/YGJustifyContentTest.java | 153 ++++++++- .../Facebook.Yoga/YGJustifyContentTest.js | 160 +++++++++ tests/YGJustifyContentTest.cpp | 325 +++++++++--------- 5 files changed, 630 insertions(+), 166 deletions(-) diff --git a/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs b/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs index d0b30d1f..58c9d678 100644 --- a/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs +++ b/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs @@ -1003,5 +1003,159 @@ namespace Facebook.Yoga Assert.AreEqual(10f, root_child2.LayoutHeight); } + [Test] + public void Test_justify_content_min_width_with_padding_child_width_greater_than_parent() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.AlignContent = YogaAlign.Stretch; + root.Width = 1000; + root.Height = 1584; + + YogaNode root_child0 = new YogaNode(config); + root_child0.FlexDirection = YogaFlexDirection.Row; + root_child0.AlignContent = YogaAlign.Stretch; + root.Insert(0, root_child0); + + YogaNode root_child0_child0 = new YogaNode(config); + root_child0_child0.FlexDirection = YogaFlexDirection.Row; + root_child0_child0.JustifyContent = YogaJustify.Center; + root_child0_child0.AlignContent = YogaAlign.Stretch; + root_child0_child0.PaddingLeft = 100; + root_child0_child0.PaddingRight = 100; + root_child0_child0.MinWidth = 400; + root_child0.Insert(0, root_child0_child0); + + YogaNode root_child0_child0_child0 = new YogaNode(config); + root_child0_child0_child0.FlexDirection = YogaFlexDirection.Row; + root_child0_child0_child0.AlignContent = YogaAlign.Stretch; + root_child0_child0_child0.Width = 300; + root_child0_child0_child0.Height = 100; + root_child0_child0.Insert(0, root_child0_child0_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(1000f, root.LayoutWidth); + Assert.AreEqual(1584f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(1000f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(500f, root_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(100f, root_child0_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0_child0.LayoutY); + Assert.AreEqual(300f, root_child0_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(1000f, root.LayoutWidth); + Assert.AreEqual(1584f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(1000f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(500f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(500f, root_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(100f, root_child0_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0_child0.LayoutY); + Assert.AreEqual(300f, root_child0_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0_child0.LayoutHeight); + } + + [Test] + public void Test_justify_content_min_width_with_padding_child_width_lower_than_parent() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.AlignContent = YogaAlign.Stretch; + root.Width = 1080; + root.Height = 1584; + + YogaNode root_child0 = new YogaNode(config); + root_child0.FlexDirection = YogaFlexDirection.Row; + root_child0.AlignContent = YogaAlign.Stretch; + root.Insert(0, root_child0); + + YogaNode root_child0_child0 = new YogaNode(config); + root_child0_child0.FlexDirection = YogaFlexDirection.Row; + root_child0_child0.JustifyContent = YogaJustify.Center; + root_child0_child0.AlignContent = YogaAlign.Stretch; + root_child0_child0.PaddingLeft = 100; + root_child0_child0.PaddingRight = 100; + root_child0_child0.MinWidth = 400; + root_child0.Insert(0, root_child0_child0); + + YogaNode root_child0_child0_child0 = new YogaNode(config); + root_child0_child0_child0.FlexDirection = YogaFlexDirection.Row; + root_child0_child0_child0.AlignContent = YogaAlign.Stretch; + root_child0_child0_child0.Width = 199; + root_child0_child0_child0.Height = 100; + root_child0_child0.Insert(0, root_child0_child0_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(1080f, root.LayoutWidth); + Assert.AreEqual(1584f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(1080f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(400f, root_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(101f, root_child0_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0_child0.LayoutY); + Assert.AreEqual(199f, root_child0_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(1080f, root.LayoutWidth); + Assert.AreEqual(1584f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(1080f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(680f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(400f, root_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(101f, root_child0_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0_child0.LayoutY); + Assert.AreEqual(199f, root_child0_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0_child0.LayoutHeight); + } + } } diff --git a/gentest/fixtures/YGJustifyContentTest.html b/gentest/fixtures/YGJustifyContentTest.html index 2f832df7..8f7f383a 100644 --- a/gentest/fixtures/YGJustifyContentTest.html +++ b/gentest/fixtures/YGJustifyContentTest.html @@ -86,7 +86,7 @@
-
+
@@ -94,7 +94,7 @@
-
+
diff --git a/java/tests/com/facebook/yoga/YGJustifyContentTest.java b/java/tests/com/facebook/yoga/YGJustifyContentTest.java index de39f64c..1f7442c8 100644 --- a/java/tests/com/facebook/yoga/YGJustifyContentTest.java +++ b/java/tests/com/facebook/yoga/YGJustifyContentTest.java @@ -4,7 +4,6 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html package com.facebook.yoga; @@ -996,6 +995,158 @@ public class YGJustifyContentTest { assertEquals(10f, root_child2.getLayoutHeight(), 0.0f); } + @Test + public void test_justify_content_min_width_with_padding_child_width_greater_than_parent() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = createNode(config); + root.setAlignContent(YogaAlign.STRETCH); + root.setWidth(1000f); + root.setHeight(1584f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setAlignContent(YogaAlign.STRETCH); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0_child0.setJustifyContent(YogaJustify.CENTER); + root_child0_child0.setAlignContent(YogaAlign.STRETCH); + root_child0_child0.setPadding(YogaEdge.LEFT, 100); + root_child0_child0.setPadding(YogaEdge.RIGHT, 100); + root_child0_child0.setMinWidth(400f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child0_child0 = createNode(config); + root_child0_child0_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); + root_child0_child0_child0.setWidth(300f); + root_child0_child0_child0.setHeight(100f); + root_child0_child0.addChildAt(root_child0_child0_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(1000f, root.getLayoutWidth(), 0.0f); + assertEquals(1584f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(1000f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(500f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(100f, root_child0_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f); + assertEquals(300f, root_child0_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(1000f, root.getLayoutWidth(), 0.0f); + assertEquals(1584f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(1000f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(500f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(500f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(100f, root_child0_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f); + assertEquals(300f, root_child0_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0_child0.getLayoutHeight(), 0.0f); + } + + @Test + public void test_justify_content_min_width_with_padding_child_width_lower_than_parent() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = createNode(config); + root.setAlignContent(YogaAlign.STRETCH); + root.setWidth(1080f); + root.setHeight(1584f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setAlignContent(YogaAlign.STRETCH); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0_child0.setJustifyContent(YogaJustify.CENTER); + root_child0_child0.setAlignContent(YogaAlign.STRETCH); + root_child0_child0.setPadding(YogaEdge.LEFT, 100); + root_child0_child0.setPadding(YogaEdge.RIGHT, 100); + root_child0_child0.setMinWidth(400f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child0_child0 = createNode(config); + root_child0_child0_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0_child0_child0.setAlignContent(YogaAlign.STRETCH); + root_child0_child0_child0.setWidth(199f); + root_child0_child0_child0.setHeight(100f); + root_child0_child0.addChildAt(root_child0_child0_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(1080f, root.getLayoutWidth(), 0.0f); + assertEquals(1584f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(1080f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(400f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(101f, root_child0_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f); + assertEquals(199f, root_child0_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(1080f, root.getLayoutWidth(), 0.0f); + assertEquals(1584f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(1080f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(680f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(400f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(101f, root_child0_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0_child0.getLayoutY(), 0.0f); + assertEquals(199f, root_child0_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0_child0.getLayoutHeight(), 0.0f); + } + private YogaNode createNode(YogaConfig config) { return mNodeFactory.create(config); } diff --git a/javascript/tests/Facebook.Yoga/YGJustifyContentTest.js b/javascript/tests/Facebook.Yoga/YGJustifyContentTest.js index 5c7cc30d..b563767b 100644 --- a/javascript/tests/Facebook.Yoga/YGJustifyContentTest.js +++ b/javascript/tests/Facebook.Yoga/YGJustifyContentTest.js @@ -1045,3 +1045,163 @@ it("justify_content_row_space_evenly", function () { config.free(); } }); +it("justify_content_min_width_with_padding_child_width_greater_than_parent", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setAlignContent(Yoga.ALIGN_STRETCH); + root.setWidth(1000); + root.setHeight(1584); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child0.setAlignContent(Yoga.ALIGN_STRETCH); + root.insertChild(root_child0, 0); + + var root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child0_child0.setJustifyContent(Yoga.JUSTIFY_CENTER); + root_child0_child0.setAlignContent(Yoga.ALIGN_STRETCH); + root_child0_child0.setPadding(Yoga.EDGE_LEFT, 100); + root_child0_child0.setPadding(Yoga.EDGE_RIGHT, 100); + root_child0_child0.setMinWidth(400); + root_child0.insertChild(root_child0_child0, 0); + + var root_child0_child0_child0 = Yoga.Node.create(config); + root_child0_child0_child0.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child0_child0_child0.setAlignContent(Yoga.ALIGN_STRETCH); + root_child0_child0_child0.setWidth(300); + root_child0_child0_child0.setHeight(100); + root_child0_child0.insertChild(root_child0_child0_child0, 0); + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(1000 === root.getComputedWidth(), "1000 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(1584 === root.getComputedHeight(), "1584 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(1000 === root_child0.getComputedWidth(), "1000 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(0 === root_child0_child0.getComputedLeft(), "0 === root_child0_child0.getComputedLeft() (" + root_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0.getComputedTop(), "0 === root_child0_child0.getComputedTop() (" + root_child0_child0.getComputedTop() + ")"); + console.assert(500 === root_child0_child0.getComputedWidth(), "500 === root_child0_child0.getComputedWidth() (" + root_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0.getComputedHeight(), "100 === root_child0_child0.getComputedHeight() (" + root_child0_child0.getComputedHeight() + ")"); + + console.assert(100 === root_child0_child0_child0.getComputedLeft(), "100 === root_child0_child0_child0.getComputedLeft() (" + root_child0_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0_child0.getComputedTop(), "0 === root_child0_child0_child0.getComputedTop() (" + root_child0_child0_child0.getComputedTop() + ")"); + console.assert(300 === root_child0_child0_child0.getComputedWidth(), "300 === root_child0_child0_child0.getComputedWidth() (" + root_child0_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0_child0.getComputedHeight(), "100 === root_child0_child0_child0.getComputedHeight() (" + root_child0_child0_child0.getComputedHeight() + ")"); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(1000 === root.getComputedWidth(), "1000 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(1584 === root.getComputedHeight(), "1584 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(1000 === root_child0.getComputedWidth(), "1000 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(500 === root_child0_child0.getComputedLeft(), "500 === root_child0_child0.getComputedLeft() (" + root_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0.getComputedTop(), "0 === root_child0_child0.getComputedTop() (" + root_child0_child0.getComputedTop() + ")"); + console.assert(500 === root_child0_child0.getComputedWidth(), "500 === root_child0_child0.getComputedWidth() (" + root_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0.getComputedHeight(), "100 === root_child0_child0.getComputedHeight() (" + root_child0_child0.getComputedHeight() + ")"); + + console.assert(100 === root_child0_child0_child0.getComputedLeft(), "100 === root_child0_child0_child0.getComputedLeft() (" + root_child0_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0_child0.getComputedTop(), "0 === root_child0_child0_child0.getComputedTop() (" + root_child0_child0_child0.getComputedTop() + ")"); + console.assert(300 === root_child0_child0_child0.getComputedWidth(), "300 === root_child0_child0_child0.getComputedWidth() (" + root_child0_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0_child0.getComputedHeight(), "100 === root_child0_child0_child0.getComputedHeight() (" + root_child0_child0_child0.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); +it("justify_content_min_width_with_padding_child_width_lower_than_parent", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setAlignContent(Yoga.ALIGN_STRETCH); + root.setWidth(1080); + root.setHeight(1584); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child0.setAlignContent(Yoga.ALIGN_STRETCH); + root.insertChild(root_child0, 0); + + var root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child0_child0.setJustifyContent(Yoga.JUSTIFY_CENTER); + root_child0_child0.setAlignContent(Yoga.ALIGN_STRETCH); + root_child0_child0.setPadding(Yoga.EDGE_LEFT, 100); + root_child0_child0.setPadding(Yoga.EDGE_RIGHT, 100); + root_child0_child0.setMinWidth(400); + root_child0.insertChild(root_child0_child0, 0); + + var root_child0_child0_child0 = Yoga.Node.create(config); + root_child0_child0_child0.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child0_child0_child0.setAlignContent(Yoga.ALIGN_STRETCH); + root_child0_child0_child0.setWidth(199); + root_child0_child0_child0.setHeight(100); + root_child0_child0.insertChild(root_child0_child0_child0, 0); + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(1080 === root.getComputedWidth(), "1080 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(1584 === root.getComputedHeight(), "1584 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(1080 === root_child0.getComputedWidth(), "1080 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(0 === root_child0_child0.getComputedLeft(), "0 === root_child0_child0.getComputedLeft() (" + root_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0.getComputedTop(), "0 === root_child0_child0.getComputedTop() (" + root_child0_child0.getComputedTop() + ")"); + console.assert(400 === root_child0_child0.getComputedWidth(), "400 === root_child0_child0.getComputedWidth() (" + root_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0.getComputedHeight(), "100 === root_child0_child0.getComputedHeight() (" + root_child0_child0.getComputedHeight() + ")"); + + console.assert(101 === root_child0_child0_child0.getComputedLeft(), "101 === root_child0_child0_child0.getComputedLeft() (" + root_child0_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0_child0.getComputedTop(), "0 === root_child0_child0_child0.getComputedTop() (" + root_child0_child0_child0.getComputedTop() + ")"); + console.assert(199 === root_child0_child0_child0.getComputedWidth(), "199 === root_child0_child0_child0.getComputedWidth() (" + root_child0_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0_child0.getComputedHeight(), "100 === root_child0_child0_child0.getComputedHeight() (" + root_child0_child0_child0.getComputedHeight() + ")"); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(1080 === root.getComputedWidth(), "1080 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(1584 === root.getComputedHeight(), "1584 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(1080 === root_child0.getComputedWidth(), "1080 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(680 === root_child0_child0.getComputedLeft(), "680 === root_child0_child0.getComputedLeft() (" + root_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0.getComputedTop(), "0 === root_child0_child0.getComputedTop() (" + root_child0_child0.getComputedTop() + ")"); + console.assert(400 === root_child0_child0.getComputedWidth(), "400 === root_child0_child0.getComputedWidth() (" + root_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0.getComputedHeight(), "100 === root_child0_child0.getComputedHeight() (" + root_child0_child0.getComputedHeight() + ")"); + + console.assert(101 === root_child0_child0_child0.getComputedLeft(), "101 === root_child0_child0_child0.getComputedLeft() (" + root_child0_child0_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0_child0_child0.getComputedTop(), "0 === root_child0_child0_child0.getComputedTop() (" + root_child0_child0_child0.getComputedTop() + ")"); + console.assert(199 === root_child0_child0_child0.getComputedWidth(), "199 === root_child0_child0_child0.getComputedWidth() (" + root_child0_child0_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0_child0_child0.getComputedHeight(), "100 === root_child0_child0_child0.getComputedHeight() (" + root_child0_child0_child0.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); diff --git a/tests/YGJustifyContentTest.cpp b/tests/YGJustifyContentTest.cpp index a644d278..7ed1c72b 100644 --- a/tests/YGJustifyContentTest.cpp +++ b/tests/YGJustifyContentTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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. */ // @Generated by gentest/gentest.rb from // gentest/fixtures/YGJustifyContentTest.html @@ -736,164 +735,6 @@ TEST(YogaTest, justify_content_row_min_width_and_margin) { YGConfigFree(config); } -TEST( - YogaTest, - justify_content_min_width_with_padding_child_width_greater_than_parent) { - const YGConfigRef config = YGConfigNew(); - - const YGNodeRef root = YGNodeNewWithConfig(config); - YGNodeStyleSetAlignContent(root, YGAlignStretch); - YGNodeStyleSetWidth(root, 1000); - YGNodeStyleSetHeight(root, 1584); - - const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); - YGNodeInsertChild(root, root_child0, 0); - - const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); - YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); - YGNodeStyleSetMinWidth(root_child0_child0, 400); - YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); - YGNodeInsertChild(root_child0, root_child0_child0, 0); - - const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); - YGNodeStyleSetWidth(root_child0_child0_child0, 300); - YGNodeStyleSetHeight(root_child0_child0_child0, 100); - YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - - YGNodeFreeRecursive(root); - - YGConfigFree(config); -} - -TEST( - YogaTest, - justify_content_min_width_with_padding_child_width_lower_than_parent) { - const YGConfigRef config = YGConfigNew(); - - const YGNodeRef root = YGNodeNewWithConfig(config); - YGNodeStyleSetAlignContent(root, YGAlignStretch); - YGNodeStyleSetWidth(root, 1080); - YGNodeStyleSetHeight(root, 1584); - - const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); - YGNodeInsertChild(root, root_child0, 0); - - const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); - YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); - YGNodeStyleSetMinWidth(root_child0_child0, 400); - YGNodeStyleSetPadding(root_child0_child0, YGEdgeHorizontal, 100); - YGNodeInsertChild(root_child0, root_child0_child0, 0); - - const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); - YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); - YGNodeStyleSetWidth(root_child0_child0_child0, 199); - YGNodeStyleSetHeight(root_child0_child0_child0, 100); - YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); - - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); - ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - ASSERT_FLOAT_EQ(680, YGNodeLayoutGetLeft(root_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); - ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); - - ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); - // - YGNodeFreeRecursive(root); - - YGConfigFree(config); -} - TEST(YogaTest, justify_content_row_max_width_and_margin) { const YGConfigRef config = YGConfigNew(); @@ -1156,3 +997,161 @@ TEST(YogaTest, justify_content_row_space_evenly) { YGConfigFree(config); } + +TEST( + YogaTest, + justify_content_min_width_with_padding_child_width_greater_than_parent) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetWidth(root, 1000); + YGNodeStyleSetHeight(root, 1584); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); + YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeLeft, 100); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeRight, 100); + YGNodeStyleSetMinWidth(root_child0_child0, 400); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); + YGNodeStyleSetWidth(root_child0_child0_child0, 300); + YGNodeStyleSetHeight(root_child0_child0_child0, 100); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1000, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + justify_content_min_width_with_padding_child_width_lower_than_parent) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetWidth(root, 1080); + YGNodeStyleSetHeight(root, 1584); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0, YGAlignStretch); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter); + YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeLeft, 100); + YGNodeStyleSetPadding(root_child0_child0, YGEdgeRight, 100); + YGNodeStyleSetMinWidth(root_child0_child0, 400); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0_child0, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch); + YGNodeStyleSetWidth(root_child0_child0_child0, 199); + YGNodeStyleSetHeight(root_child0_child0_child0, 100); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(1584, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(680, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(101, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(199, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} From d02f4a94de589d91dc719e51ff6c8c5b302df184 Mon Sep 17 00:00:00 2001 From: Scott Rice Date: Wed, 31 Oct 2018 12:03:17 -0700 Subject: [PATCH 089/189] Use fb_native_wrapper for all targets Differential Revision: D12868694 fbshipit-source-id: 0dfc7d05cc0ee6b15a2534f17260e340038a1041 --- android/sample/BUCK | 3 ++- csharp/BUCK | 5 +++-- lib/appcompat/BUCK | 3 ++- lib/soloader/BUCK | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/android/sample/BUCK b/android/sample/BUCK index 0612aca9..0989fcd6 100644 --- a/android/sample/BUCK +++ b/android/sample/BUCK @@ -4,6 +4,7 @@ # This source code is licensed under the license found in the # LICENSE-examples file in the root directory of this source tree. +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource") yoga_android_binary( @@ -28,7 +29,7 @@ yoga_android_resource( ], ) -keystore( +fb_native.keystore( name = "debug_keystore", properties = "debug.keystore.properties", store = "debug.keystore", diff --git a/csharp/BUCK b/csharp/BUCK index 5f93cbe2..685b227f 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -3,6 +3,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:fb_native_wrapper.bzl", "fb_native") load( "//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", @@ -13,14 +14,14 @@ load( COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"] -csharp_library( +fb_native.csharp_library( name = "yogalibnet46", srcs = glob(["**/*.cs"]), dll_name = "Facebook.Yoga.dll", framework_ver = "net46", ) -csharp_library( +fb_native.csharp_library( name = "yogalibnet45", srcs = glob(["**/*.cs"]), dll_name = "Facebook.Yoga.dll", diff --git a/lib/appcompat/BUCK b/lib/appcompat/BUCK index c1d38451..b3262494 100644 --- a/lib/appcompat/BUCK +++ b/lib/appcompat/BUCK @@ -3,9 +3,10 @@ # 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:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") -android_prebuilt_aar( +fb_native.android_prebuilt_aar( name = "appcompat", aar = "appcompat-v7-24.2.1.aar", visibility = YOGA_ROOTS, diff --git a/lib/soloader/BUCK b/lib/soloader/BUCK index c96f46ed..04e2f5ff 100644 --- a/lib/soloader/BUCK +++ b/lib/soloader/BUCK @@ -3,9 +3,10 @@ # 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:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") -android_prebuilt_aar( +fb_native.android_prebuilt_aar( name = "soloader", aar = "soloader-0.5.1.aar", visibility = YOGA_ROOTS, From a2ef8978cddc9c36f679161fa8b68bac99353af8 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Wed, 31 Oct 2018 13:08:37 -0700 Subject: [PATCH 090/189] flex_shrink_flex_grow_row and flex_shrink_flex_grow_child_flex_shrink_other_child tests were directly added in YGFlexTest.cpp, Added these in YGFlexTest.html so that they can generated accordingly in all different langauges via gentest ruby script Summary: @public `flex_shrink_flex_grow_row` and `flex_shrink_flex_grow_child_flex_shrink_other_child` tests were present in YGFlexTest.cpp. When running ruby script to generate tests, these were getting removed since they were not added in YGFlexTest.html using which tests are generated. This diff adds tests in YGFlexTest.html and contains corresponding generated test cases for different languages. Reviewed By: priteshrnandgaonkar Differential Revision: D12838701 fbshipit-source-id: 5e92716d94fa392230db2c0ec3b8c131a089c55a --- csharp/tests/Facebook.Yoga/YGFlexTest.cs | 117 ++++++++++++++++++ gentest/fixtures/YGFlexTest.html | 10 ++ java/tests/com/facebook/yoga/YGFlexTest.java | 116 ++++++++++++++++- javascript/tests/Facebook.Yoga/YGFlexTest.js | 123 +++++++++++++++++++ tests/YGFlexTest.cpp | 39 +++++- 5 files changed, 401 insertions(+), 4 deletions(-) diff --git a/csharp/tests/Facebook.Yoga/YGFlexTest.cs b/csharp/tests/Facebook.Yoga/YGFlexTest.cs index e43278d6..9beb5123 100644 --- a/csharp/tests/Facebook.Yoga/YGFlexTest.cs +++ b/csharp/tests/Facebook.Yoga/YGFlexTest.cs @@ -69,6 +69,123 @@ namespace Facebook.Yoga Assert.AreEqual(25f, root_child1.LayoutHeight); } + [Test] + public void Test_flex_shrink_flex_grow_row() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 500; + root.Height = 500; + + YogaNode root_child0 = new YogaNode(config); + root_child0.FlexShrink = 1; + root_child0.Width = 500; + root_child0.Height = 100; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(config); + root_child1.FlexShrink = 1; + root_child1.Width = 500; + root_child1.Height = 100; + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(500f, root.LayoutWidth); + Assert.AreEqual(500f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(250f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(250f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(250f, root_child1.LayoutWidth); + Assert.AreEqual(100f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(500f, root.LayoutWidth); + Assert.AreEqual(500f, root.LayoutHeight); + + Assert.AreEqual(250f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(250f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(250f, root_child1.LayoutWidth); + Assert.AreEqual(100f, root_child1.LayoutHeight); + } + + [Test] + public void Test_flex_shrink_flex_grow_child_flex_shrink_other_child() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 500; + root.Height = 500; + + YogaNode root_child0 = new YogaNode(config); + root_child0.FlexShrink = 1; + root_child0.Width = 500; + root_child0.Height = 100; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(config); + root_child1.FlexGrow = 1; + root_child1.FlexShrink = 1; + root_child1.Width = 500; + root_child1.Height = 100; + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(500f, root.LayoutWidth); + Assert.AreEqual(500f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(250f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(250f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(250f, root_child1.LayoutWidth); + Assert.AreEqual(100f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(500f, root.LayoutWidth); + Assert.AreEqual(500f, root.LayoutHeight); + + Assert.AreEqual(250f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(250f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(250f, root_child1.LayoutWidth); + Assert.AreEqual(100f, root_child1.LayoutHeight); + } + [Test] public void Test_flex_basis_flex_grow_row() { diff --git a/gentest/fixtures/YGFlexTest.html b/gentest/fixtures/YGFlexTest.html index 5d8ae13c..9985c3cb 100644 --- a/gentest/fixtures/YGFlexTest.html +++ b/gentest/fixtures/YGFlexTest.html @@ -3,6 +3,16 @@
+
+
+
+
+ +
+
+
+
+
diff --git a/java/tests/com/facebook/yoga/YGFlexTest.java b/java/tests/com/facebook/yoga/YGFlexTest.java index 3fd419ef..5ebc8abf 100644 --- a/java/tests/com/facebook/yoga/YGFlexTest.java +++ b/java/tests/com/facebook/yoga/YGFlexTest.java @@ -4,7 +4,6 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html package com.facebook.yoga; @@ -77,6 +76,121 @@ public class YGFlexTest { assertEquals(25f, root_child1.getLayoutHeight(), 0.0f); } + @Test + public void test_flex_shrink_flex_grow_row() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(500f); + root.setHeight(500f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexShrink(1f); + root_child0.setWidth(500f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setFlexShrink(1f); + root_child1.setWidth(500f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(500f, root.getLayoutWidth(), 0.0f); + assertEquals(500f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(250f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(250f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(250f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(500f, root.getLayoutWidth(), 0.0f); + assertEquals(500f, root.getLayoutHeight(), 0.0f); + + assertEquals(250f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(250f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(250f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_flex_shrink_flex_grow_child_flex_shrink_other_child() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(500f); + root.setHeight(500f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexShrink(1f); + root_child0.setWidth(500f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setFlexGrow(1f); + root_child1.setFlexShrink(1f); + root_child1.setWidth(500f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(500f, root.getLayoutWidth(), 0.0f); + assertEquals(500f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(250f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(250f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(250f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(500f, root.getLayoutWidth(), 0.0f); + assertEquals(500f, root.getLayoutHeight(), 0.0f); + + assertEquals(250f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(250f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(250f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + } + @Test public void test_flex_basis_flex_grow_row() { YogaConfig config = new YogaConfig(); diff --git a/javascript/tests/Facebook.Yoga/YGFlexTest.js b/javascript/tests/Facebook.Yoga/YGFlexTest.js index 3053af01..c16f09cd 100644 --- a/javascript/tests/Facebook.Yoga/YGFlexTest.js +++ b/javascript/tests/Facebook.Yoga/YGFlexTest.js @@ -66,6 +66,129 @@ it("flex_basis_flex_grow_column", function () { config.free(); } }); +it("flex_shrink_flex_grow_row", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root.setWidth(500); + root.setHeight(500); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexShrink(1); + root_child0.setWidth(500); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(config); + root_child1.setFlexShrink(1); + root_child1.setWidth(500); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(500 === root.getComputedWidth(), "500 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(500 === root.getComputedHeight(), "500 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(250 === root_child0.getComputedWidth(), "250 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(250 === root_child1.getComputedLeft(), "250 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), "0 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(250 === root_child1.getComputedWidth(), "250 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(100 === root_child1.getComputedHeight(), "100 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(500 === root.getComputedWidth(), "500 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(500 === root.getComputedHeight(), "500 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(250 === root_child0.getComputedLeft(), "250 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(250 === root_child0.getComputedWidth(), "250 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(0 === root_child1.getComputedLeft(), "0 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), "0 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(250 === root_child1.getComputedWidth(), "250 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(100 === root_child1.getComputedHeight(), "100 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); +it("flex_shrink_flex_grow_child_flex_shrink_other_child", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root.setWidth(500); + root.setHeight(500); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexShrink(1); + root_child0.setWidth(500); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(config); + root_child1.setFlexGrow(1); + root_child1.setFlexShrink(1); + root_child1.setWidth(500); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(500 === root.getComputedWidth(), "500 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(500 === root.getComputedHeight(), "500 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(250 === root_child0.getComputedWidth(), "250 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(250 === root_child1.getComputedLeft(), "250 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), "0 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(250 === root_child1.getComputedWidth(), "250 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(100 === root_child1.getComputedHeight(), "100 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(500 === root.getComputedWidth(), "500 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(500 === root.getComputedHeight(), "500 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(250 === root_child0.getComputedLeft(), "250 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(250 === root_child0.getComputedWidth(), "250 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(100 === root_child0.getComputedHeight(), "100 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(0 === root_child1.getComputedLeft(), "0 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), "0 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(250 === root_child1.getComputedWidth(), "250 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(100 === root_child1.getComputedHeight(), "100 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); it("flex_basis_flex_grow_row", function () { var config = Yoga.Config.create(); diff --git a/tests/YGFlexTest.cpp b/tests/YGFlexTest.cpp index 90f93248..67cc2bbc 100644 --- a/tests/YGFlexTest.cpp +++ b/tests/YGFlexTest.cpp @@ -73,14 +73,12 @@ TEST(YogaTest, flex_shrink_flex_grow_row) { YGNodeStyleSetHeight(root, 500); const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexGrow(root_child0, 0); YGNodeStyleSetFlexShrink(root_child0, 1); YGNodeStyleSetWidth(root_child0, 500); YGNodeStyleSetHeight(root_child0, 100); YGNodeInsertChild(root, root_child0, 0); const YGNodeRef root_child1 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexGrow(root_child1, 0); YGNodeStyleSetFlexShrink(root_child1, 1); YGNodeStyleSetWidth(root_child1, 500); YGNodeStyleSetHeight(root_child1, 100); @@ -101,6 +99,24 @@ TEST(YogaTest, flex_shrink_flex_grow_row) { ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + YGNodeFreeRecursive(root); YGConfigFree(config); @@ -115,7 +131,6 @@ TEST(YogaTest, flex_shrink_flex_grow_child_flex_shrink_other_child) { YGNodeStyleSetHeight(root, 500); const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetFlexGrow(root_child0, 0); YGNodeStyleSetFlexShrink(root_child0, 1); YGNodeStyleSetWidth(root_child0, 500); YGNodeStyleSetHeight(root_child0, 100); @@ -143,6 +158,24 @@ TEST(YogaTest, flex_shrink_flex_grow_child_flex_shrink_other_child) { ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + YGNodeFreeRecursive(root); YGConfigFree(config); From a0b3586fb3699b8ad98681f4e74a1aab26fbb8c0 Mon Sep 17 00:00:00 2001 From: Daniel Hood Date: Wed, 7 Nov 2018 08:47:17 -0800 Subject: [PATCH 091/189] Fix build error caused by -Werror=class-memaccess (#823) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: OS: Arch Linux GCC Version: gcc (GCC) 8.2.1 20180831 Clang Version: 6.0.1 (tags/RELEASE_601/final) Build Log Before Fix: command: `buck build //:yoga` ``` Not using buckd because watchman isn't installed. yoga/Yoga.cpp: In function ‘void YGZeroOutLayoutRecursivly(YGNodeRef)’: yoga/Yoga.cpp:1854:51: error: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘struct YGLayout’; use assignment or value-initialization instead [-Werror=class-memaccess] memset(&(node->getLayout()), 0, sizeof(YGLayout)); ^ In file included from yoga/YGNode.h:11, from yoga/Utils.h:9, from yoga/Yoga.cpp:13: yoga/YGLayout.h:12:8: note: ‘struct YGLayout’ declared here struct YGLayout { ^~~~~~~~ cc1plus: all warnings being treated as errors Build failed: Command failed with exit code 1. stderr: yoga/Yoga.cpp: In function ‘void YGZeroOutLayoutRecursivly(YGNodeRef)’: yoga/Yoga.cpp:1854:51: error: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘struct YGLayout’; use assignment or value-initialization instead [-Werror=class-memaccess] memset(&(node->getLayout()), 0, sizeof(YGLayout)); ^ In file included from yoga/YGNode.h:11, from yoga/Utils.h:9, from yoga/Yoga.cpp:13: yoga/YGLayout.h:12:8: note: ‘struct YGLayout’ declared here struct YGLayout { ^~~~~~~~ cc1plus: all warnings being treated as errors When running . When building rule //:yoga#compile-Yoga.cpp.o9b5477b5,default. Parsing buck files: finished in 0.8 sec (100%) Building: finished in 2.2 sec (100%) 10/10 jobs, 1 updated Total time: 3.3 sec ``` Build Log After Fix command: `buck build //:yoga` ``` Not using buckd because watchman isn't installed. Parsing buck files: finished in 0.8 sec (100%) Building: finished in 0.6 sec (100%) 1/1 jobs, 0 updated Total time: 1.6 sec ``` All tests are passing Pull Request resolved: https://github.com/facebook/yoga/pull/823 Reviewed By: davidaurelio Differential Revision: D10486023 Pulled By: passy fbshipit-source-id: e9de734c3ce6c45ea4a8edd5d78206901d85ca84 --- yoga/Yoga.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 55283473..6e42d51a 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1850,7 +1850,9 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( } static void YGZeroOutLayoutRecursivly(const YGNodeRef node) { - memset(&(node->getLayout()), 0, sizeof(YGLayout)); + node->getLayout() = {}; + node->setLayoutDimension(0, 0); + node->setLayoutDimension(0, 1); node->setHasNewLayout(true); node->cloneChildrenIfNeeded(); const uint32_t childCount = YGNodeGetChildCount(node); From 7a60399b2bbd6e4220bb320b0669cd8d6bfb55c5 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 7 Nov 2018 09:33:33 -0800 Subject: [PATCH 092/189] Add Yoga JNI bindings to libcoldstart Summary: Yoga's JNI bindings are usually loaded during class loading, and can stall the UI thread. Here, we try to mitigate the problem by adding the bindings to libcoldstart. Reviewed By: michalgr Differential Revision: D12956818 fbshipit-source-id: 9dda5cb6d26c2bae64606bc2d7c98ab8f7c05a30 --- java/BUCK | 1 + java/com/facebook/yoga/YogaJNI.java | 8 +++++--- tools/build_defs/oss/yoga_defs.bzl | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/java/BUCK b/java/BUCK index 14210ed1..87a44ad6 100644 --- a/java/BUCK +++ b/java/BUCK @@ -10,6 +10,7 @@ yoga_cxx_library( srcs = glob(["jni/*.cpp"]), headers = glob(["jni/*.h"]), header_namespace = "", + allow_jni_merging = True, compiler_flags = [ "-fno-omit-frame-pointer", "-fexceptions", diff --git a/java/com/facebook/yoga/YogaJNI.java b/java/com/facebook/yoga/YogaJNI.java index deccbcf5..fb013804 100644 --- a/java/com/facebook/yoga/YogaJNI.java +++ b/java/com/facebook/yoga/YogaJNI.java @@ -10,6 +10,7 @@ package com.facebook.yoga; import com.facebook.soloader.SoLoader; public class YogaJNI { + private static boolean isInitialized = false; // Known constants. 1-3 used in previous experiments. Do not reuse. public static int JNI_FAST_CALLS = 4; @@ -19,12 +20,13 @@ public class YogaJNI { private static native void jni_bindNativeMethods(boolean useFastCall); - static boolean init() { - if (SoLoader.loadLibrary("yoga")) { + static synchronized boolean init() { + if (!isInitialized) { + isInitialized = true; + SoLoader.loadLibrary("yoga"); jni_bindNativeMethods(useFastCall); return true; } - return false; } } diff --git a/tools/build_defs/oss/yoga_defs.bzl b/tools/build_defs/oss/yoga_defs.bzl index 6b3ac1d5..7eca7b9b 100644 --- a/tools/build_defs/oss/yoga_defs.bzl +++ b/tools/build_defs/oss/yoga_defs.bzl @@ -174,6 +174,8 @@ def yoga_cxx_binary(*args, **kwargs): def yoga_cxx_library(*args, **kwargs): # Currently unused kwargs.pop("platforms", None) + kwargs.pop("allow_jni_merging", None) + native.cxx_library(*args, **kwargs) def yoga_cxx_test(*args, **kwargs): From 4e2011c38156359fe8379befbd4c207f7fac066a Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Wed, 14 Nov 2018 02:49:27 -0800 Subject: [PATCH 093/189] added functionality using which child node can tell parent node to use it as a reference baseline Summary: @public Currently only parent can tell the layout to align its children based on baseline. But if one of the children is a column or row then basealign does not work as expected. We have added an api setReferenceBaseline which when set to true would mean that it's baseline would be considered as the reference baseline for parent amongst its siblings. If there are more than one siblings with referenceBaseline set, the first one would be considered. Reviewed By: davidaurelio Differential Revision: D12883323 fbshipit-source-id: 19beccfc47d98bb38f81f5b66ba764e83680f821 --- csharp/Facebook.Yoga/Native.cs | 8 + csharp/Facebook.Yoga/YogaNode.cs | 15 +- java/com/facebook/yoga/YogaNode.java | 13 + java/jni/YGJNI.cpp | 13 + javascript/sources/Node.cc | 8 + javascript/sources/Node.hh | 4 +- javascript/sources/nbind.cc | 3 + tests/YGAlignBaselineTest.cpp | 688 ++++++++++++++++++++++++++- yoga/YGNode.h | 9 + yoga/Yoga.cpp | 11 +- yoga/Yoga.h | 6 + 11 files changed, 774 insertions(+), 4 deletions(-) diff --git a/csharp/Facebook.Yoga/Native.cs b/csharp/Facebook.Yoga/Native.cs index 06b08c74..02e9399d 100644 --- a/csharp/Facebook.Yoga/Native.cs +++ b/csharp/Facebook.Yoga/Native.cs @@ -88,6 +88,14 @@ namespace Facebook.Yoga [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeRemoveChild(YGNodeHandle node, YGNodeHandle child); + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + public static extern void YGNodeSetIsReferenceBaseline( + YGNodeHandle node, + bool isReferenceBaseline); + + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + public static extern bool YGNodeIsReferenceBaseline(YGNodeHandle node); + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeCalculateLayout( YGNodeHandle node, diff --git a/csharp/Facebook.Yoga/YogaNode.cs b/csharp/Facebook.Yoga/YogaNode.cs index 57e7c7d9..b1f30b22 100644 --- a/csharp/Facebook.Yoga/YogaNode.cs +++ b/csharp/Facebook.Yoga/YogaNode.cs @@ -519,6 +519,19 @@ namespace Facebook.Yoga Native.YGNodeSetHasNewLayout(_ygNode, false); } + public bool IsReferenceBaseline + { + get + { + return Native.YGNodeIsReferenceBaseline(_ygNode); + } + + set + { + Native.YGNodeSetIsReferenceBaseline(_ygNode, value); + } + } + public bool ValuesEqual(float f1, float f2) { if (float.IsNaN(f1) || float.IsNaN(f2)) @@ -594,7 +607,7 @@ namespace Facebook.Yoga } public void CalculateLayout( - float width = YogaConstants.Undefined, + float width = YogaConstants.Undefined, float height = YogaConstants.Undefined) { Native.YGNodeCalculateLayout( diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 282931dc..efbfc89b 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -159,6 +159,7 @@ public class YogaNode implements Cloneable { } private static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index); + public void addChildAt(YogaNode child, int i) { if (child.mOwner != null) { throw new IllegalStateException("Child already has a parent, it must be removed first."); @@ -183,6 +184,18 @@ public class YogaNode implements Cloneable { jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i); } + private static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline); + + public void setIsReferenceBaseline(boolean isReferenceBaseline) { + jni_YGNodeSetIsReferenceBaseline(mNativePointer, isReferenceBaseline); + } + + private static native boolean jni_YGNodeIsReferenceBaseline(long nativePointer); + + public boolean isReferenceBaseline() { + return jni_YGNodeIsReferenceBaseline(mNativePointer); + } + private static native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer); private native long jni_YGNodeClone(long nativePointer, Object newNode); diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index d7854656..5d80a3d2 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -371,6 +371,17 @@ void jni_YGNodeRemoveChild(jlong nativePointer, jlong childPointer) { _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } +void jni_YGNodeSetIsReferenceBaseline( + jlong nativePointer, + jboolean isReferenceBaseline) { + YGNodeSetIsReferenceBaseline( + _jlong2YGNodeRef(nativePointer), isReferenceBaseline); +} + +jboolean jni_YGNodeIsReferenceBaseline(jlong nativePointer) { + return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer)); +} + void jni_YGNodeCalculateLayout( alias_ref, jlong nativePointer, @@ -666,6 +677,8 @@ jint jni_YGNodeGetInstanceCount() { YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), \ YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), \ YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), \ + YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline), \ + YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline), \ YGMakeNativeMethod(jni_YGNodeCalculateLayout), \ YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty), \ YGMakeCriticalNativeMethod( \ diff --git a/javascript/sources/Node.cc b/javascript/sources/Node.cc index a2305819..c684da28 100644 --- a/javascript/sources/Node.cc +++ b/javascript/sources/Node.cc @@ -253,6 +253,10 @@ void Node::setPaddingPercent(int edge, double padding) YGNodeStyleSetPaddingPercent(m_node, static_cast(edge), padding); } +void Node::setIsReferenceBaseline(bool isReferenceBaseline) { + YGNodeSetIsReferenceBaseline(m_node, isReferenceBaseline); +} + int Node::getPositionType(void) const { return YGNodeStyleGetPositionType(m_node); @@ -368,6 +372,10 @@ Value Node::getPadding(int edge) const return Value::fromYGValue(YGNodeStyleGetPadding(m_node, static_cast(edge))); } +bool Node::isReferenceBaseline() { + return YGNodeIsReferenceBaseline(m_node); +} + void Node::insertChild(Node * child, unsigned index) { YGNodeInsertChild(m_node, child->m_node, index); diff --git a/javascript/sources/Node.hh b/javascript/sources/Node.hh index ef9887e4..593745b2 100644 --- a/javascript/sources/Node.hh +++ b/javascript/sources/Node.hh @@ -187,7 +187,9 @@ class Node { double getComputedBorder(int edge) const; double getComputedPadding(int edge) const; - private: + public: + void setIsReferenceBaseline(bool isReferenceBaseline); + bool isReferenceBaseline(); YGNodeRef m_node; diff --git a/javascript/sources/nbind.cc b/javascript/sources/nbind.cc index 53ff0206..0ea7e0db 100644 --- a/javascript/sources/nbind.cc +++ b/javascript/sources/nbind.cc @@ -150,6 +150,9 @@ NBIND_CLASS(Node) method(getParent); method(getChild); + method(isReferenceBaseline); + method(setIsReferenceBaseline); + method(setMeasureFunc); method(unsetMeasureFunc); diff --git a/tests/YGAlignBaselineTest.cpp b/tests/YGAlignBaselineTest.cpp index 78179b98..0ede52bd 100644 --- a/tests/YGAlignBaselineTest.cpp +++ b/tests/YGAlignBaselineTest.cpp @@ -5,8 +5,8 @@ * file in the root directory of this source tree. * */ - #include +#include #include static float @@ -38,6 +38,22 @@ static YGSize _measure2( }; } +static YGNodeRef createYGNode( + YGConfigRef config, + YGFlexDirection direction, + int width, + int height, + bool alignBaseline) { + const YGNodeRef node = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(node, direction); + if (alignBaseline) { + YGNodeStyleSetAlignItems(node, YGAlignBaseline); + } + YGNodeStyleSetWidth(node, width); + YGNodeStyleSetHeight(node, height); + return node; +} + // Test case for bug in T32999822 TEST(YogaTest, align_baseline_parent_ht_not_specified) { YGConfigRef config = YGConfigNew(); @@ -164,3 +180,673 @@ TEST(YogaTest, align_baseline_with_no_baseline_func_and_no_parent_ht) { YGConfigFree(config); } + +TEST(YogaTest, align_baseline_parent_using_child_in_column_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 800, false); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_with_padding_in_column_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 800, false); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeLeft, 100); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeRight, 100); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeTop, 100); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeBottom, 100); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_with_padding_using_child_in_column_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 800, false); + YGNodeStyleSetPadding(root_child1, YGEdgeLeft, 100); + YGNodeStyleSetPadding(root_child1, YGEdgeRight, 100); + YGNodeStyleSetPadding(root_child1, YGEdgeTop, 100); + YGNodeStyleSetPadding(root_child1, YGEdgeBottom, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_with_margin_using_child_in_column_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 800, false); + YGNodeStyleSetMargin(root_child1, YGEdgeLeft, 100); + YGNodeStyleSetMargin(root_child1, YGEdgeRight, 100); + YGNodeStyleSetMargin(root_child1, YGEdgeTop, 100); + YGNodeStyleSetMargin(root_child1, YGEdgeBottom, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(600, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_with_margin_in_column_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 800, false); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeLeft, 100); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeRight, 100); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeTop, 100); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeBottom, 100); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, align_baseline_parent_using_child_in_row_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionRow, 500, 800, true); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 500, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_with_padding_in_row_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionRow, 500, 800, true); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 500, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeLeft, 100); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeRight, 100); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeTop, 100); + YGNodeStyleSetPadding(root_child1_child1, YGEdgeBottom, 100); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_with_margin_in_row_as_reference) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionRow, 500, 800, true); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 500, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeLeft, 100); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeRight, 100); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeTop, 100); + YGNodeStyleSetMargin(root_child1_child1, YGEdgeBottom, 100); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(600, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_in_column_as_reference_with_no_baseline_func) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 800, false); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_in_row_as_reference_with_no_baseline_func) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = + createYGNode(config, YGFlexDirectionRow, 1000, 1000, true); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = + createYGNode(config, YGFlexDirectionRow, 500, 800, true); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 500, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_in_column_as_reference_with_height_not_specified) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 1000); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionColumn); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(800, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_in_row_as_reference_with_height_not_specified) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 1000); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 500, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + root_child1_child1->setBaseLineFunc(_baselineFunc); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(900, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_in_column_as_reference_with_no_baseline_func_and_height_not_specified) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 1000); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionColumn); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 300, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST( + YogaTest, + align_baseline_parent_using_child_in_row_as_reference_with_no_baseline_func_and_height_not_specified) { + YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignBaseline); + YGNodeStyleSetWidth(root, 1000); + + const YGNodeRef root_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 600, false); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child1_child0 = + createYGNode(config, YGFlexDirectionColumn, 500, 500, false); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + const YGNodeRef root_child1_child1 = + createYGNode(config, YGFlexDirectionColumn, 500, 400, false); + YGNodeSetIsReferenceBaseline(root_child1_child1, true); + YGNodeInsertChild(root_child1, root_child1_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/YGNode.h b/yoga/YGNode.h index d771aad2..103b5076 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -17,6 +17,7 @@ struct YGNode { void* context_ = nullptr; YGPrintFunc print_ = nullptr; bool hasNewLayout_ = true; + bool isReferenceBaseline_ = false; YGNodeType nodeType_ = YGNodeTypeDefault; YGMeasureFunc measure_ = nullptr; YGBaselineFunc baseline_ = nullptr; @@ -93,6 +94,10 @@ struct YGNode { return lineIndex_; } + bool isReferenceBaseline() { + return isReferenceBaseline_; + } + // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. // This method will return the parent of the YGNode when a YGNode only belongs @@ -211,6 +216,10 @@ struct YGNode { lineIndex_ = lineIndex; } + void setIsReferenceBaseline(bool isReferenceBaseline) { + isReferenceBaseline_ = isReferenceBaseline; + } + void setOwner(YGNodeRef owner) { owner_ = owner; } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6e42d51a..8afe45ff 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -380,6 +380,14 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) { memcpy(dest, src, sizeof(YGConfig)); } +void YGNodeSetIsReferenceBaseline(YGNodeRef node, bool isReferenceBaseline) { + node->setIsReferenceBaseline(isReferenceBaseline); +} + +bool YGNodeIsReferenceBaseline(YGNodeRef node) { + return node->isReferenceBaseline(); +} + void YGNodeInsertChild( const YGNodeRef node, const YGNodeRef child, @@ -1138,7 +1146,8 @@ static float YGBaseline(const YGNodeRef node) { if (child->getStyle().positionType == YGPositionTypeAbsolute) { continue; } - if (YGNodeAlignItem(node, child) == YGAlignBaseline) { + if (YGNodeAlignItem(node, child) == YGAlignBaseline || + child->isReferenceBaseline()) { baselineChild = child; break; } diff --git a/yoga/Yoga.h b/yoga/Yoga.h index d5da362d..dddab8bb 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -114,6 +114,12 @@ WIN_EXPORT void YGNodeSetChildren( const YGNodeRef children[], const uint32_t count); +WIN_EXPORT void YGNodeSetIsReferenceBaseline( + YGNodeRef node, + bool isReferenceBaseline); + +WIN_EXPORT bool YGNodeIsReferenceBaseline(YGNodeRef node); + WIN_EXPORT void YGNodeCalculateLayout( const YGNodeRef node, const float availableWidth, From 63570613d303e23f88d6de7aa3c1a9d3a536bfd6 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Wed, 14 Nov 2018 04:00:48 -0800 Subject: [PATCH 094/189] added basic java, csharp and javascript tests for reference baseline feature Summary: @public We added a functionality using which child node can tell parent node to use it as a reference baseline. Added some tests for java, csharp, javascript language bindings. Reviewed By: davidaurelio Differential Revision: D12997442 fbshipit-source-id: 4717167d2b3862bf2af87b663bda82f9c1eae33e --- .../Facebook.Yoga/YGAlignBaselineTest.cs | 104 ++++++++++++ .../facebook/yoga/YGAlignBaselineTest.java | 122 ++++++++++++++ .../Facebook.Yoga/YGAlignBaselineTest.js | 156 ++++++++++++++++++ 3 files changed, 382 insertions(+) create mode 100644 csharp/tests/Facebook.Yoga/YGAlignBaselineTest.cs create mode 100644 java/tests/com/facebook/yoga/YGAlignBaselineTest.java create mode 100644 javascript/tests/Facebook.Yoga/YGAlignBaselineTest.js diff --git a/csharp/tests/Facebook.Yoga/YGAlignBaselineTest.cs b/csharp/tests/Facebook.Yoga/YGAlignBaselineTest.cs new file mode 100644 index 00000000..ea62d3ae --- /dev/null +++ b/csharp/tests/Facebook.Yoga/YGAlignBaselineTest.cs @@ -0,0 +1,104 @@ +/** + * 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. + */ + +using System; +using NUnit.Framework; + +namespace Facebook.Yoga +{ + [TestFixture] + public class YGAlignBaselineTest + { + [Test] + public void Test_align_baseline_parent_using_child_in_column_as_reference() + { + YogaConfig config = new YogaConfig(); + YogaNode root = createYGNode(config, YogaFlexDirection.Row, 1000, 1000, true); + + YogaNode root_child0 = createYGNode(config, YogaFlexDirection.Column, 500, 600, false); + root.Insert(0, root_child0); + + YogaNode root_child1 = createYGNode(config, YogaFlexDirection.Column, 500, 800, false); + root.Insert(1, root_child1); + + YogaNode root_child1_child0 = createYGNode(config, YogaFlexDirection.Column, 500, 300, false); + root_child1.Insert(0, root_child1_child0); + + YogaNode root_child1_child1 = createYGNode(config, YogaFlexDirection.Column, 500, 400, false); + root_child1_child1.SetBaselineFunction((_, width, height) => { + return height / 2; + }); + root_child1_child1.IsReferenceBaseline = true; + root_child1.Insert(1, root_child1_child1); + + root.CalculateLayout(); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + + Assert.AreEqual(500f, root_child1.LayoutX); + Assert.AreEqual(100f, root_child1.LayoutY); + + Assert.AreEqual(0f, root_child1_child0.LayoutX); + Assert.AreEqual(0f, root_child1_child0.LayoutY); + + Assert.AreEqual(0f, root_child1_child1.LayoutX); + Assert.AreEqual(300f, root_child1_child1.LayoutY); + } + + [Test] + public void Test_align_baseline_parent_using_child_in_row_as_reference() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = createYGNode(config, YogaFlexDirection.Row, 1000, 1000, true); + + YogaNode root_child0 = createYGNode(config, YogaFlexDirection.Column, 500, 600, false); + root.Insert(0, root_child0); + + YogaNode root_child1 = createYGNode(config, YogaFlexDirection.Row, 500, 800, true); + root.Insert(1, root_child1); + + YogaNode root_child1_child0 = createYGNode(config, YogaFlexDirection.Row, 500, 500, false); + root_child1.Insert(0, root_child1_child0); + + YogaNode root_child1_child1 = createYGNode(config, YogaFlexDirection.Row, 500, 400, false); + root_child1_child1.SetBaselineFunction((_, width, height) => { + return height / 2; + }); + root_child1_child1.IsReferenceBaseline = true; + root_child1.Insert(1, root_child1_child1); + + root.StyleDirection = YogaDirection.LTR; + + root.CalculateLayout(); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + + Assert.AreEqual(500f, root_child1.LayoutX); + Assert.AreEqual(100f, root_child1.LayoutY); + + Assert.AreEqual(0f, root_child1_child0.LayoutX); + Assert.AreEqual(0f, root_child1_child0.LayoutY); + + Assert.AreEqual(500f, root_child1_child1.LayoutX); + Assert.AreEqual(300f, root_child1_child1.LayoutY); + } + + private YogaNode createYGNode(YogaConfig config, YogaFlexDirection flexDirection, int width, int height, bool alignBaseline) { + YogaNode node = new YogaNode(config); + node.FlexDirection = flexDirection; + node.Width = width; + node.Height = height; + if (alignBaseline) { + node.AlignItems = YogaAlign.Baseline; + } + return node; + } + } +} diff --git a/java/tests/com/facebook/yoga/YGAlignBaselineTest.java b/java/tests/com/facebook/yoga/YGAlignBaselineTest.java new file mode 100644 index 00000000..46258b41 --- /dev/null +++ b/java/tests/com/facebook/yoga/YGAlignBaselineTest.java @@ -0,0 +1,122 @@ +/** + * 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 static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class YGAlignBaselineTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + + private YogaBaselineFunction getBaselineFunc() { + return new YogaBaselineFunction() { + @Override + public float baseline(YogaNode node, float width, float height) { + return height / 2; + } + }; + } + + @Test + public void test_align_baseline_parent_using_child_in_column_as_reference() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = createYGNode(config, YogaFlexDirection.ROW, 1000f, 1000f, true); + + final YogaNode root_child0 = createYGNode(config, YogaFlexDirection.COLUMN, 500f, 600f, false); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createYGNode(config, YogaFlexDirection.COLUMN, 500f, 800f, false); + root.addChildAt(root_child1, 1); + + final YogaNode root_child1_child0 = + createYGNode(config, YogaFlexDirection.COLUMN, 500f, 300f, false); + root_child1.addChildAt(root_child1_child0, 0); + + final YogaNode root_child1_child1 = + createYGNode(config, YogaFlexDirection.COLUMN, 500f, 400f, false); + root_child1_child1.setBaselineFunction(getBaselineFunc()); + root_child1_child1.setIsReferenceBaseline(true); + root_child1.addChildAt(root_child1_child1, 1); + + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + + assertEquals(500f, root_child1.getLayoutX(), 0.0f); + assertEquals(100f, root_child1.getLayoutY(), 0.0f); + + assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f); + + assertEquals(0f, root_child1_child1.getLayoutX(), 0.0f); + assertEquals(300f, root_child1_child1.getLayoutY(), 0.0f); + } + + @Test + public void test_align_baseline_parent_using_child_in_row_as_reference() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = createYGNode(config, YogaFlexDirection.ROW, 1000f, 1000f, true); + + final YogaNode root_child0 = createYGNode(config, YogaFlexDirection.COLUMN, 500f, 600f, false); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createYGNode(config, YogaFlexDirection.ROW, 500f, 800f, true); + root.addChildAt(root_child1, 1); + + final YogaNode root_child1_child0 = + createYGNode(config, YogaFlexDirection.COLUMN, 500f, 500f, false); + root_child1.addChildAt(root_child1_child0, 0); + + final YogaNode root_child1_child1 = + createYGNode(config, YogaFlexDirection.COLUMN, 500f, 400f, false); + root_child1_child1.setBaselineFunction(getBaselineFunc()); + root_child1_child1.setIsReferenceBaseline(true); + root_child1.addChildAt(root_child1_child1, 1); + + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + + assertEquals(500f, root_child1.getLayoutX(), 0.0f); + assertEquals(100f, root_child1.getLayoutY(), 0.0f); + + assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f); + + assertEquals(500f, root_child1_child1.getLayoutX(), 0.0f); + assertEquals(300f, root_child1_child1.getLayoutY(), 0.0f); + } + + private YogaNode createYGNode( + YogaConfig config, + YogaFlexDirection flexDirection, + float width, + float height, + boolean alignBaseline) { + YogaNode node = mNodeFactory.create(config); + node.setFlexDirection(flexDirection); + node.setWidth(width); + node.setHeight(height); + if (alignBaseline) { + node.setAlignItems(YogaAlign.BASELINE); + } + return node; + } +} diff --git a/javascript/tests/Facebook.Yoga/YGAlignBaselineTest.js b/javascript/tests/Facebook.Yoga/YGAlignBaselineTest.js new file mode 100644 index 00000000..34f186f4 --- /dev/null +++ b/javascript/tests/Facebook.Yoga/YGAlignBaselineTest.js @@ -0,0 +1,156 @@ +/** + * 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. + */ + +var Yoga = Yoga || require("../../sources/entry-" + process.env.TEST_ENTRY); + +it("align_baseline_parent_using_child_in_column_as_reference", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root.setWidth(1000); + root.setHeight(1000); + root.setAlignItems(Yoga.ALIGN_BASELINE); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child0.setWidth(500); + root_child0.setHeight(600); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(config); + root_child1.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child1.setWidth(500); + root_child1.setHeight(800); + root.insertChild(root_child1, 1); + + var root_child1_child0 = Yoga.Node.create(config); + root_child1_child0.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child1_child0.setWidth(500); + root_child1_child0.setHeight(300); + root_child1.insertChild(root_child1_child0, 0); + + var root_child1_child1 = Yoga.Node.create(config); + root_child1_child1.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child1_child1.setWidth(500); + root_child1_child1.setHeight(400); + root_child1_child1.setIsReferenceBaseline(true); + root_child1.insertChild(root_child1_child1, 1); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root_child0.getComputedLeft(), + "0 === root_child0.getComputedLeft() (" + + root_child0.getComputedLeft() + ")"); + console.assert(100 === root_child0.getComputedTop(), + "100 === root_child0.getComputedTop() (" + + root_child0.getComputedTop() + ")"); + + console.assert(500 === root_child1.getComputedLeft(), + "500 === root_child1.getComputedLeft() (" + + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), + "0 === root_child1.getComputedTop() (" + + root_child1.getComputedTop() + ")"); + + console.assert(0 === root_child1_child0.getComputedLeft(), + "0 === root_child1_child0.getComputedLeft() (" + + root_child1_child0.getComputedLeft() + ")"); + console.assert(0 === root_child1_child0.getComputedTop(), + "0 === root_child1_child0.getComputedTop() (" + + root_child1_child0.getComputedTop() + ")"); + + console.assert(0 === root_child1_child1.getComputedLeft(), + "0 === root_child1_child1.getComputedLeft() (" + + root_child1_child1.getComputedLeft() + ")"); + console.assert(300 === root_child1_child1.getComputedTop(), + "300 === root_child1_child1.getComputedTop() (" + + root_child1_child1.getComputedTop() + ")"); + + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); + +it("align_baseline_parent_using_child_in_row_as_reference", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root.setWidth(1000); + root.setHeight(1000); + root.setAlignItems(Yoga.ALIGN_BASELINE); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child0.setWidth(500); + root_child0.setHeight(600); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(config); + root_child1.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root_child1.setWidth(500); + root_child1.setHeight(800); + root.insertChild(root_child1, 1); + + var root_child1_child0 = Yoga.Node.create(config); + root_child1_child0.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child1_child0.setWidth(500); + root_child1_child0.setHeight(500); + root_child1.insertChild(root_child1_child0, 0); + + var root_child1_child1 = Yoga.Node.create(config); + root_child1_child1.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN); + root_child1_child1.setWidth(500); + root_child1_child1.setHeight(400); + root_child1_child1.setIsReferenceBaseline(true); + root_child1.insertChild(root_child1_child1, 1); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root_child0.getComputedLeft(), + "0 === root_child0.getComputedLeft() (" + + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), + "0 === root_child0.getComputedTop() (" + + root_child0.getComputedTop() + ")"); + + console.assert(500 === root_child1.getComputedLeft(), + "500 === root_child1.getComputedLeft() (" + + root_child1.getComputedLeft() + ")"); + console.assert(200 === root_child1.getComputedTop(), + "200 === root_child1.getComputedTop() (" + + root_child1.getComputedTop() + ")"); + + console.assert(0 === root_child1_child0.getComputedLeft(), + "0 === root_child1_child0.getComputedLeft() (" + + root_child1_child0.getComputedLeft() + ")"); + console.assert(0 === root_child1_child0.getComputedTop(), + "0 === root_child1_child0.getComputedTop() (" + + root_child1_child0.getComputedTop() + ")"); + + console.assert(500 === root_child1_child1.getComputedLeft(), + "500 === root_child1_child1.getComputedLeft() (" + + root_child1_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1_child1.getComputedTop(), + "0 === root_child1_child1.getComputedTop() (" + + root_child1_child1.getComputedTop() + ")"); + + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); From 7d7d9a7ef0791f1ebedc38f4519722e9a6874475 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 15 Nov 2018 08:06:24 -0800 Subject: [PATCH 095/189] Back to yearless format for MIT license Summary: @public Restores the yearless format of the MIT license. Reviewed By: SidharthGuglani Differential Revision: D13082510 fbshipit-source-id: f5a849b06652cedf68547d4a7963398b2627915f --- java/com/facebook/yoga/YogaAlign.java | 2 +- java/com/facebook/yoga/YogaConfig.java | 2 +- java/com/facebook/yoga/YogaDimension.java | 2 +- java/com/facebook/yoga/YogaDirection.java | 2 +- java/com/facebook/yoga/YogaDisplay.java | 2 +- java/com/facebook/yoga/YogaEdge.java | 2 +- java/com/facebook/yoga/YogaExperimentalFeature.java | 2 +- java/com/facebook/yoga/YogaFlexDirection.java | 2 +- java/com/facebook/yoga/YogaJustify.java | 2 +- java/com/facebook/yoga/YogaLogLevel.java | 2 +- java/com/facebook/yoga/YogaMeasureMode.java | 2 +- java/com/facebook/yoga/YogaNode.java | 2 +- java/com/facebook/yoga/YogaNodeType.java | 2 +- java/com/facebook/yoga/YogaOverflow.java | 2 +- java/com/facebook/yoga/YogaPositionType.java | 2 +- java/com/facebook/yoga/YogaPrintOptions.java | 2 +- java/com/facebook/yoga/YogaUnit.java | 2 +- java/com/facebook/yoga/YogaValue.java | 2 +- java/com/facebook/yoga/YogaWrap.java | 2 +- java/jni/YGJNI.cpp | 2 +- tests/YGComputedMarginTest.cpp | 2 +- tests/YGComputedPaddingTest.cpp | 2 +- tests/YGRoundingFunctionTest.cpp | 2 +- yoga/YGNode.cpp | 2 +- yoga/Yoga.cpp | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/java/com/facebook/yoga/YogaAlign.java b/java/com/facebook/yoga/YogaAlign.java index 6a84ffaf..94878fd7 100644 --- a/java/com/facebook/yoga/YogaAlign.java +++ b/java/com/facebook/yoga/YogaAlign.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index b8312bd4..57561df7 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaDimension.java b/java/com/facebook/yoga/YogaDimension.java index 42f1ce76..2ef27726 100644 --- a/java/com/facebook/yoga/YogaDimension.java +++ b/java/com/facebook/yoga/YogaDimension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaDirection.java b/java/com/facebook/yoga/YogaDirection.java index 78d377d8..6a5017cf 100644 --- a/java/com/facebook/yoga/YogaDirection.java +++ b/java/com/facebook/yoga/YogaDirection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaDisplay.java b/java/com/facebook/yoga/YogaDisplay.java index df7bff2f..3ba4d56c 100644 --- a/java/com/facebook/yoga/YogaDisplay.java +++ b/java/com/facebook/yoga/YogaDisplay.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaEdge.java b/java/com/facebook/yoga/YogaEdge.java index 8d7d1b68..80a783e7 100644 --- a/java/com/facebook/yoga/YogaEdge.java +++ b/java/com/facebook/yoga/YogaEdge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaExperimentalFeature.java b/java/com/facebook/yoga/YogaExperimentalFeature.java index 82f2db94..33a8389d 100644 --- a/java/com/facebook/yoga/YogaExperimentalFeature.java +++ b/java/com/facebook/yoga/YogaExperimentalFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaFlexDirection.java b/java/com/facebook/yoga/YogaFlexDirection.java index 3d31caa2..c5f9ab5d 100644 --- a/java/com/facebook/yoga/YogaFlexDirection.java +++ b/java/com/facebook/yoga/YogaFlexDirection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaJustify.java b/java/com/facebook/yoga/YogaJustify.java index 521dad28..6b1b83f5 100644 --- a/java/com/facebook/yoga/YogaJustify.java +++ b/java/com/facebook/yoga/YogaJustify.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaLogLevel.java b/java/com/facebook/yoga/YogaLogLevel.java index e6a9498e..29476d67 100644 --- a/java/com/facebook/yoga/YogaLogLevel.java +++ b/java/com/facebook/yoga/YogaLogLevel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaMeasureMode.java b/java/com/facebook/yoga/YogaMeasureMode.java index 7b24c26f..24399f62 100644 --- a/java/com/facebook/yoga/YogaMeasureMode.java +++ b/java/com/facebook/yoga/YogaMeasureMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index efbfc89b..f3d4a53a 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaNodeType.java b/java/com/facebook/yoga/YogaNodeType.java index c9dd58de..28db7f1f 100644 --- a/java/com/facebook/yoga/YogaNodeType.java +++ b/java/com/facebook/yoga/YogaNodeType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaOverflow.java b/java/com/facebook/yoga/YogaOverflow.java index 3003451f..8dec3649 100644 --- a/java/com/facebook/yoga/YogaOverflow.java +++ b/java/com/facebook/yoga/YogaOverflow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaPositionType.java b/java/com/facebook/yoga/YogaPositionType.java index ecdcb950..0392e6f8 100644 --- a/java/com/facebook/yoga/YogaPositionType.java +++ b/java/com/facebook/yoga/YogaPositionType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaPrintOptions.java b/java/com/facebook/yoga/YogaPrintOptions.java index 226c1a2a..fb1a6b14 100644 --- a/java/com/facebook/yoga/YogaPrintOptions.java +++ b/java/com/facebook/yoga/YogaPrintOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaUnit.java b/java/com/facebook/yoga/YogaUnit.java index 76c40676..b9a98e95 100644 --- a/java/com/facebook/yoga/YogaUnit.java +++ b/java/com/facebook/yoga/YogaUnit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaValue.java b/java/com/facebook/yoga/YogaValue.java index 1eeb0f03..947cfcc7 100644 --- a/java/com/facebook/yoga/YogaValue.java +++ b/java/com/facebook/yoga/YogaValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/com/facebook/yoga/YogaWrap.java b/java/com/facebook/yoga/YogaWrap.java index 17001973..45f1220c 100644 --- a/java/com/facebook/yoga/YogaWrap.java +++ b/java/com/facebook/yoga/YogaWrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 5d80a3d2..7261a315 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/tests/YGComputedMarginTest.cpp b/tests/YGComputedMarginTest.cpp index 619a2444..a3d1f442 100644 --- a/tests/YGComputedMarginTest.cpp +++ b/tests/YGComputedMarginTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/tests/YGComputedPaddingTest.cpp b/tests/YGComputedPaddingTest.cpp index e40542c7..fad7ce1b 100644 --- a/tests/YGComputedPaddingTest.cpp +++ b/tests/YGComputedPaddingTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/tests/YGRoundingFunctionTest.cpp b/tests/YGRoundingFunctionTest.cpp index 7d82f8bf..fa16b60e 100644 --- a/tests/YGRoundingFunctionTest.cpp +++ b/tests/YGRoundingFunctionTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 76f662e7..6b49f167 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 8afe45ff..df127dbe 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. From dd12907632eb7b480ab8316243a204cf70410098 Mon Sep 17 00:00:00 2001 From: Amir Shalem Date: Thu, 22 Nov 2018 02:33:33 -0800 Subject: [PATCH 096/189] Add getUndefined() method to obtain the undefined value Summary: Add getUndefined() method to obtain the undefined value. This would allow to obtain the Yoga undefined value in runtime, and not just in compile time Reviewed By: davidaurelio Differential Revision: D13136972 fbshipit-source-id: aa198aa1ea65bb6b7302abeba6f9f5d483a45ff3 --- java/com/facebook/yoga/YogaConstants.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index 10f152d4..61e212ef 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -35,4 +35,8 @@ public class YogaConstants { public static boolean isUndefined(YogaValue value) { return value.unit == YogaUnit.UNDEFINED; } + + public static float getUndefined() { + return UNDEFINED; + } } From 8d5bbecd3dfd31bd2c09bedbfcd4d0e65f05ea96 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 22 Nov 2018 03:48:16 -0800 Subject: [PATCH 097/189] Pass primitives by value Summary: @public Passes all `float`, `bool`, etc. by value, not by reference. Reviewed By: astreet Differential Revision: D13153500 fbshipit-source-id: 95529bc2efcff144044e2c25087915b2b7ede179 --- yoga/Utils.cpp | 2 +- yoga/Utils.h | 2 +- yoga/YGNode.cpp | 20 ++++++++++---------- yoga/YGNode.h | 20 ++++++++++---------- yoga/Yoga.cpp | 18 +++++++++--------- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index fa21a55b..5322642f 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -52,7 +52,7 @@ bool YGFloatsEqual(const float a, const float b) { return yoga::isUndefined(a) && yoga::isUndefined(b); } -float YGFloatSanitize(const float& val) { +float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } diff --git a/yoga/Utils.h b/yoga/Utils.h index e538cad9..db257ae5 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -91,7 +91,7 @@ bool YGFloatArrayEqual( } // This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise -float YGFloatSanitize(const float& val); +float YGFloatSanitize(const float val); // This function unwraps optional and returns YGUndefined if not defined or // op.value otherwise diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 6b49f167..7d3f37c2 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -13,7 +13,7 @@ using namespace facebook; YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection& axis, - const float& axisSize) const { + const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { const YGValue* leadingPosition = YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined); @@ -32,7 +32,7 @@ YGFloatOptional YGNode::getLeadingPosition( YGFloatOptional YGNode::getTrailingPosition( const YGFlexDirection& axis, - const float& axisSize) const { + const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { const YGValue* trailingPosition = YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined); @@ -67,7 +67,7 @@ bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const { YGFloatOptional YGNode::getLeadingMargin( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.margin[YGEdgeStart].unit != YGUnitUndefined) { return YGResolveValueMargin(style_.margin[YGEdgeStart], widthSize); @@ -80,7 +80,7 @@ YGFloatOptional YGNode::getLeadingMargin( YGFloatOptional YGNode::getTrailingMargin( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { return YGResolveValueMargin(style_.margin[YGEdgeEnd], widthSize); @@ -93,7 +93,7 @@ YGFloatOptional YGNode::getTrailingMargin( YGFloatOptional YGNode::getMarginForAxis( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { return getLeadingMargin(axis, widthSize) + getTrailingMargin(axis, widthSize); } @@ -205,7 +205,7 @@ void YGNode::setLayoutDimension(float dimension, int index) { // +left or -right depending on which is defined. YGFloatOptional YGNode::relativePosition( const YGFlexDirection& axis, - const float& axisSize) const { + const float axisSize) const { if (isLeadingPositionDefined(axis)) { return getLeadingPosition(axis, axisSize); } @@ -453,7 +453,7 @@ float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { YGFloatOptional YGNode::getLeadingPadding( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { const YGFloatOptional& paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && @@ -470,7 +470,7 @@ YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getTrailingPadding( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.padding[YGEdgeEnd].unit != YGUnitUndefined && !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() && @@ -487,14 +487,14 @@ YGFloatOptional YGNode::getTrailingPadding( YGFloatOptional YGNode::getLeadingPaddingAndBorder( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { return getLeadingPadding(axis, widthSize) + YGFloatOptional(getLeadingBorder(axis)); } YGFloatOptional YGNode::getTrailingPaddingAndBorder( const YGFlexDirection& axis, - const float& widthSize) const { + const float widthSize) const { return getTrailingPadding(axis, widthSize) + YGFloatOptional(getTrailingBorder(axis)); } diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 103b5076..698c07e4 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -34,7 +34,7 @@ struct YGNode { YGFloatOptional relativePosition( const YGFlexDirection& axis, - const float& axisSize) const; + const float axisSize) const; public: YGNode() = default; @@ -139,35 +139,35 @@ struct YGNode { // Methods related to positions, margin, padding and border YGFloatOptional getLeadingPosition( const YGFlexDirection& axis, - const float& axisSize) const; + const float axisSize) const; bool isLeadingPositionDefined(const YGFlexDirection& axis) const; bool isTrailingPosDefined(const YGFlexDirection& axis) const; YGFloatOptional getTrailingPosition( const YGFlexDirection& axis, - const float& axisSize) const; + const float axisSize) const; YGFloatOptional getLeadingMargin( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; YGFloatOptional getTrailingMargin( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; float getLeadingBorder(const YGFlexDirection& flexDirection) const; float getTrailingBorder(const YGFlexDirection& flexDirection) const; YGFloatOptional getLeadingPadding( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; YGFloatOptional getTrailingPadding( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; YGFloatOptional getLeadingPaddingAndBorder( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; YGFloatOptional getTrailingPaddingAndBorder( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; YGFloatOptional getMarginForAxis( const YGFlexDirection& axis, - const float& widthSize) const; + const float widthSize) const; // Setters void setContext(void* context) { diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index df127dbe..e0b84d7c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1221,8 +1221,8 @@ static inline bool YGNodeIsLayoutDimDefined( static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( const YGNodeRef node, const YGFlexDirection& axis, - const float& value, - const float& axisSize) { + const float value, + const float axisSize) { YGFloatOptional min; YGFloatOptional max; @@ -2422,17 +2422,17 @@ static void YGResolveFlexibleLength( static void YGJustifyMainAxis( const YGNodeRef node, YGCollectFlexItemsRowValues& collectedFlexItemsValues, - const uint32_t& startOfLineIndex, + const uint32_t startOfLineIndex, const YGFlexDirection& mainAxis, const YGFlexDirection& crossAxis, const YGMeasureMode& measureModeMainDim, const YGMeasureMode& measureModeCrossDim, - const float& mainAxisownerSize, - const float& ownerWidth, - const float& availableInnerMainDim, - const float& availableInnerCrossDim, - const float& availableInnerWidth, - const bool& performLayout) { + const float mainAxisownerSize, + const float ownerWidth, + const float availableInnerMainDim, + const float availableInnerCrossDim, + const float availableInnerWidth, + const bool performLayout) { const YGStyle& style = node->getStyle(); const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); From 339c5574b8f9b2c4763c05efe780c5f71f0fb971 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 22 Nov 2018 03:59:22 -0800 Subject: [PATCH 098/189] Dealloc JNI implementation experiment Summary: @public Remove ability to configure Yoga to run with/without JNI fast calls on dalvik / art. This switches to always run with fast calls. Reviewed By: astreet Differential Revision: D13144652 fbshipit-source-id: 091aab0cd1290d46346323d3e26a11dd0bb17187 --- java/com/facebook/yoga/YogaConfig.java | 3 +- java/com/facebook/yoga/YogaJNI.java | 32 ---- java/com/facebook/yoga/YogaNode.java | 3 +- java/jni/YGJNI.cpp | 224 +++++++++++-------------- 4 files changed, 106 insertions(+), 156 deletions(-) delete mode 100644 java/com/facebook/yoga/YogaJNI.java diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index 57561df7..40de7d2c 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -8,6 +8,7 @@ package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; @DoNotStrip public class YogaConfig { @@ -15,7 +16,7 @@ public class YogaConfig { public static int SPACING_TYPE = 1; static { - YogaJNI.init(); + SoLoader.loadLibrary("yoga"); } long mNativePointer; diff --git a/java/com/facebook/yoga/YogaJNI.java b/java/com/facebook/yoga/YogaJNI.java deleted file mode 100644 index fb013804..00000000 --- a/java/com/facebook/yoga/YogaJNI.java +++ /dev/null @@ -1,32 +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.soloader.SoLoader; - -public class YogaJNI { - private static boolean isInitialized = false; - - // Known constants. 1-3 used in previous experiments. Do not reuse. - public static int JNI_FAST_CALLS = 4; - - // set before loading any other Yoga code - public static boolean useFastCall = false; - - private static native void jni_bindNativeMethods(boolean useFastCall); - - static synchronized boolean init() { - if (!isInitialized) { - isInitialized = true; - SoLoader.loadLibrary("yoga"); - jni_bindNativeMethods(useFastCall); - return true; - } - return false; - } -} diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index f3d4a53a..7dd26947 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -8,6 +8,7 @@ package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @@ -16,7 +17,7 @@ import javax.annotation.Nullable; public class YogaNode implements Cloneable { static { - YogaJNI.init(); + SoLoader.loadLibrary("yoga"); } /** diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 7261a315..8c6536d4 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. + * Copyright (c) 2018-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. @@ -658,132 +658,112 @@ jint jni_YGNodeGetInstanceCount() { } #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) -#define YGRealMakeCriticalNativeMethod(name) \ - makeCriticalNativeMethod(#name, name) -#define YGWrapCriticalNativeMethodForRegularCall(name) \ - makeNativeMethod( \ - #name, \ - ::facebook::jni::detail::CriticalMethod::call<&name>) - -#define YGRegisterNatives(YGMakeCriticalNativeMethod) \ - registerNatives( \ - "com/facebook/yoga/YogaNode", \ - { \ - YGMakeNativeMethod(jni_YGNodeNew), \ - YGMakeNativeMethod(jni_YGNodeNewWithConfig), \ - YGMakeCriticalNativeMethod(jni_YGNodeFree), \ - YGMakeCriticalNativeMethod(jni_YGNodeReset), \ - YGMakeCriticalNativeMethod(jni_YGNodeClearChildren), \ - YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), \ - YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), \ - YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline), \ - YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline), \ - YGMakeNativeMethod(jni_YGNodeCalculateLayout), \ - YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty), \ - YGMakeCriticalNativeMethod( \ - jni_YGNodeMarkDirtyAndPropogateToDescendants), \ - YGMakeCriticalNativeMethod(jni_YGNodeIsDirty), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetHasMeasureFunc), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetHasBaselineFunc), \ - YGMakeCriticalNativeMethod(jni_YGNodeCopyStyle), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexDirection), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetJustifyContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetJustifyContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignItems), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignItems), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignSelf), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignSelf), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignContent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPositionType), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionType), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexWrap), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetOverflow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetOverflow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDisplay), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDisplay), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlex), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexGrow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexGrow), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexShrink), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexShrink), \ - YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasis), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMargin), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMargin), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetPadding), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPadding), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPaddingPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetBorder), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetBorder), \ - YGMakeNativeMethod(jni_YGNodeStyleGetPosition), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPosition), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightAuto), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidthPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeightPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidth), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidthPercent), \ - YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeight), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAspectRatio), \ - YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAspectRatio), \ - YGMakeCriticalNativeMethod(jni_YGNodeGetInstanceCount), \ - YGMakeCriticalNativeMethod(jni_YGNodePrint), \ - YGMakeNativeMethod(jni_YGNodeClone), \ - YGMakeCriticalNativeMethod(jni_YGNodeSetOwner), \ - }); \ - registerNatives( \ - "com/facebook/yoga/YogaConfig", \ - { \ - YGMakeNativeMethod(jni_YGConfigNew), \ - YGMakeNativeMethod(jni_YGConfigFree), \ - YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), \ - YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), \ - YGMakeNativeMethod(jni_YGConfigSetPrintTreeFlag), \ - YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), \ - YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), \ - YGMakeNativeMethod(jni_YGConfigSetLogger), \ - YGMakeNativeMethod(jni_YGConfigSetHasCloneNodeFunc), \ - YGMakeNativeMethod( \ - jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), \ - }); - -void jni_bindNativeMethods(alias_ref, jboolean useFastCall) { - if (useFastCall) { - YGRegisterNatives(YGRealMakeCriticalNativeMethod); - } else { - YGRegisterNatives(YGWrapCriticalNativeMethodForRegularCall); - } -} +#define YGMakeCriticalNativeMethod(name) makeCriticalNativeMethod(#name, name) jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( - "com/facebook/yoga/YogaJNI", + "com/facebook/yoga/YogaNode", { - YGMakeNativeMethod(jni_bindNativeMethods), + YGMakeNativeMethod(jni_YGNodeNew), + YGMakeNativeMethod(jni_YGNodeNewWithConfig), + YGMakeCriticalNativeMethod(jni_YGNodeFree), + YGMakeCriticalNativeMethod(jni_YGNodeReset), + YGMakeCriticalNativeMethod(jni_YGNodeClearChildren), + YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), + YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), + YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), + YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline), + YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline), + YGMakeNativeMethod(jni_YGNodeCalculateLayout), + YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty), + YGMakeCriticalNativeMethod( + jni_YGNodeMarkDirtyAndPropogateToDescendants), + YGMakeCriticalNativeMethod(jni_YGNodeIsDirty), + YGMakeCriticalNativeMethod(jni_YGNodeSetHasMeasureFunc), + YGMakeCriticalNativeMethod(jni_YGNodeSetHasBaselineFunc), + YGMakeCriticalNativeMethod(jni_YGNodeCopyStyle), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexDirection), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetJustifyContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetJustifyContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignItems), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignItems), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignSelf), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignSelf), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAlignContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAlignContent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetPositionType), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionType), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexWrap), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetOverflow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetOverflow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetDisplay), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetDisplay), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlex), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexGrow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexGrow), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetFlexShrink), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexShrink), + YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasis), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetFlexBasisAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetMargin), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMargin), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMarginAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetPadding), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPadding), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPaddingPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetBorder), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetBorder), + YGMakeNativeMethod(jni_YGNodeStyleGetPosition), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPosition), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetPositionPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetWidthAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetHeightAuto), + YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinWidthPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMinHeightPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidth), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxWidthPercent), + YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeight), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), + YGMakeCriticalNativeMethod(jni_YGNodeStyleGetAspectRatio), + YGMakeCriticalNativeMethod(jni_YGNodeStyleSetAspectRatio), + YGMakeCriticalNativeMethod(jni_YGNodeGetInstanceCount), + YGMakeCriticalNativeMethod(jni_YGNodePrint), + YGMakeNativeMethod(jni_YGNodeClone), + YGMakeCriticalNativeMethod(jni_YGNodeSetOwner), + }); + registerNatives( + "com/facebook/yoga/YogaConfig", + { + YGMakeNativeMethod(jni_YGConfigNew), + YGMakeNativeMethod(jni_YGConfigFree), + YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), + YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), + YGMakeNativeMethod(jni_YGConfigSetPrintTreeFlag), + YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), + YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), + YGMakeNativeMethod(jni_YGConfigSetLogger), + YGMakeNativeMethod(jni_YGConfigSetHasCloneNodeFunc), + YGMakeNativeMethod( + jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), }); }); } From 8f181c72594c99993b857de8f1f8efcc95dc8ea0 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 22 Nov 2018 08:06:25 -0800 Subject: [PATCH 099/189] Pass enums by value Summary: @public passes all enum values by value, not by reference. Reviewed By: astreet Differential Revision: D13156390 fbshipit-source-id: 56aea66c16ab3325594f67b9017afa18a678d281 --- yoga/YGNode.cpp | 28 ++++++++++++++-------------- yoga/YGNode.h | 28 ++++++++++++++-------------- yoga/Yoga.cpp | 10 +++++----- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 7d3f37c2..189a3df1 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -12,7 +12,7 @@ using namespace facebook; YGFloatOptional YGNode::getLeadingPosition( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { const YGValue* leadingPosition = @@ -31,7 +31,7 @@ YGFloatOptional YGNode::getLeadingPosition( } YGFloatOptional YGNode::getTrailingPosition( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { const YGValue* trailingPosition = @@ -49,7 +49,7 @@ YGFloatOptional YGNode::getTrailingPosition( : YGResolveValue(*trailingPosition, axisSize); } -bool YGNode::isLeadingPositionDefined(const YGFlexDirection& axis) const { +bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined) ->unit != YGUnitUndefined) || @@ -57,7 +57,7 @@ bool YGNode::isLeadingPositionDefined(const YGFlexDirection& axis) const { ->unit != YGUnitUndefined; } -bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const { +bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined) ->unit != YGUnitUndefined) || @@ -66,7 +66,7 @@ bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const { } YGFloatOptional YGNode::getLeadingMargin( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.margin[YGEdgeStart].unit != YGUnitUndefined) { @@ -79,7 +79,7 @@ YGFloatOptional YGNode::getLeadingMargin( } YGFloatOptional YGNode::getTrailingMargin( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { @@ -92,7 +92,7 @@ YGFloatOptional YGNode::getTrailingMargin( } YGFloatOptional YGNode::getMarginForAxis( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { return getLeadingMargin(axis, widthSize) + getTrailingMargin(axis, widthSize); } @@ -204,7 +204,7 @@ void YGNode::setLayoutDimension(float dimension, int index) { // If both left and right are defined, then use left. Otherwise return // +left or -right depending on which is defined. YGFloatOptional YGNode::relativePosition( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float axisSize) const { if (isLeadingPositionDefined(axis)) { return getLeadingPosition(axis, axisSize); @@ -424,7 +424,7 @@ bool YGNode::isNodeFlexible() { (resolveFlexGrow() != 0 || resolveFlexShrink() != 0)); } -float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { +float YGNode::getLeadingBorder(const YGFlexDirection axis) const { if (YGFlexDirectionIsRow(axis) && style_.border[YGEdgeStart].unit != YGUnitUndefined && !yoga::isUndefined(style_.border[YGEdgeStart].value) && @@ -437,7 +437,7 @@ float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { return YGFloatMax(computedEdgeValue, 0.0f); } -float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { +float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { if (YGFlexDirectionIsRow(flexDirection) && style_.border[YGEdgeEnd].unit != YGUnitUndefined && !yoga::isUndefined(style_.border[YGEdgeEnd].value) && @@ -452,7 +452,7 @@ float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { } YGFloatOptional YGNode::getLeadingPadding( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { const YGFloatOptional& paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); @@ -469,7 +469,7 @@ YGFloatOptional YGNode::getLeadingPadding( } YGFloatOptional YGNode::getTrailingPadding( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { if (YGFlexDirectionIsRow(axis) && style_.padding[YGEdgeEnd].unit != YGUnitUndefined && @@ -486,14 +486,14 @@ YGFloatOptional YGNode::getTrailingPadding( } YGFloatOptional YGNode::getLeadingPaddingAndBorder( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { return getLeadingPadding(axis, widthSize) + YGFloatOptional(getLeadingBorder(axis)); } YGFloatOptional YGNode::getTrailingPaddingAndBorder( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const { return getTrailingPadding(axis, widthSize) + YGFloatOptional(getTrailingBorder(axis)); diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 698c07e4..678926d3 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -33,7 +33,7 @@ struct YGNode { {YGValueUndefined, YGValueUndefined}}; YGFloatOptional relativePosition( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float axisSize) const; public: @@ -138,35 +138,35 @@ struct YGNode { // Methods related to positions, margin, padding and border YGFloatOptional getLeadingPosition( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float axisSize) const; - bool isLeadingPositionDefined(const YGFlexDirection& axis) const; - bool isTrailingPosDefined(const YGFlexDirection& axis) const; + bool isLeadingPositionDefined(const YGFlexDirection axis) const; + bool isTrailingPosDefined(const YGFlexDirection axis) const; YGFloatOptional getTrailingPosition( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float axisSize) const; YGFloatOptional getLeadingMargin( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; YGFloatOptional getTrailingMargin( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; - float getLeadingBorder(const YGFlexDirection& flexDirection) const; - float getTrailingBorder(const YGFlexDirection& flexDirection) const; + float getLeadingBorder(const YGFlexDirection flexDirection) const; + float getTrailingBorder(const YGFlexDirection flexDirection) const; YGFloatOptional getLeadingPadding( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; YGFloatOptional getTrailingPadding( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; YGFloatOptional getLeadingPaddingAndBorder( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; YGFloatOptional getTrailingPaddingAndBorder( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; YGFloatOptional getMarginForAxis( - const YGFlexDirection& axis, + const YGFlexDirection axis, const float widthSize) const; // Setters diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index e0b84d7c..d05e0da9 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1220,7 +1220,7 @@ static inline bool YGNodeIsLayoutDimDefined( static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( const YGNodeRef node, - const YGFlexDirection& axis, + const YGFlexDirection axis, const float value, const float axisSize) { YGFloatOptional min; @@ -2423,10 +2423,10 @@ static void YGJustifyMainAxis( const YGNodeRef node, YGCollectFlexItemsRowValues& collectedFlexItemsValues, const uint32_t startOfLineIndex, - const YGFlexDirection& mainAxis, - const YGFlexDirection& crossAxis, - const YGMeasureMode& measureModeMainDim, - const YGMeasureMode& measureModeCrossDim, + const YGFlexDirection mainAxis, + const YGFlexDirection crossAxis, + const YGMeasureMode measureModeMainDim, + const YGMeasureMode measureModeCrossDim, const float mainAxisownerSize, const float ownerWidth, const float availableInnerMainDim, From 02a2309b2a8208e652e351cf8a195c17694b1f01 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 22 Nov 2018 08:06:25 -0800 Subject: [PATCH 100/189] `YGNodeComputeFlexBasisForChildren`: remove output param Summary: @public `YGNodeComputeFlexBasisForChildren` was using an output parameter (`float&`) that is always initialised to `0.0f`. Here, we move the initialisation inside `YGNodeComputeFlexBasisForChildren`, and simply return the result. Reviewed By: astreet Differential Revision: D13167509 fbshipit-source-id: cbea20e2deb82ec75a1c158b16c94f4a3e5e4c99 --- yoga/Yoga.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index d05e0da9..10f27bf0 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1911,7 +1911,7 @@ static float YGNodeCalculateAvailableInnerDim( return availableInnerDim; } -static void YGNodeComputeFlexBasisForChildren( +static float YGNodeComputeFlexBasisForChildren( const YGNodeRef node, const float availableInnerWidth, const float availableInnerHeight, @@ -1920,8 +1920,8 @@ static void YGNodeComputeFlexBasisForChildren( YGDirection direction, YGFlexDirection mainAxis, const YGConfigRef config, - bool performLayout, - float& totalOuterFlexBasis) { + bool performLayout) { + float totalOuterFlexBasis = 0.0f; YGNodeRef singleFlexChild = nullptr; YGVector children = node->getChildren(); YGMeasureMode measureModeMainDim = @@ -1991,6 +1991,8 @@ static void YGNodeComputeFlexBasisForChildren( child->getLayout().computedFlexBasis + child->getMarginForAxis(mainAxis, availableInnerWidth)); } + + return totalOuterFlexBasis; } // This function assumes that all the children of node have their @@ -2902,11 +2904,9 @@ static void YGNodelayoutImpl( const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; - float totalOuterFlexBasis = 0; - // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM - YGNodeComputeFlexBasisForChildren( + float totalOuterFlexBasis = YGNodeComputeFlexBasisForChildren( node, availableInnerWidth, availableInnerHeight, @@ -2915,8 +2915,7 @@ static void YGNodelayoutImpl( direction, mainAxis, config, - performLayout, - totalOuterFlexBasis); + performLayout); const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined ? false From 89394a2dd6ccfa34466403e3a476cbf99e98fa52 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Sat, 24 Nov 2018 16:23:54 -0800 Subject: [PATCH 101/189] Data types for marker API Summary: @public Adds types for a marker API in Yoga. This will allow us to register callbacks that Yoga can use to log performance data without hard-coding the backend system for that. Reviewed By: SidharthGuglani Differential Revision: D13118830 fbshipit-source-id: b42a42c609f0cf66212186f7f20ee572522d59e3 --- yoga/YGConfig.h | 4 +++- yoga/YGMarker.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 yoga/YGMarker.h diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index 941e0dcd..b5f3c5fd 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -6,6 +6,7 @@ * */ #pragma once +#include "YGMarker.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -14,11 +15,12 @@ struct YGConfig { bool useWebDefaults = false; bool useLegacyStretchBehaviour = false; bool shouldDiffLayoutWithoutLegacyStretchBehaviour = false; + bool printTree = false; float pointScaleFactor = 1.0f; YGLogger logger; YGCloneNodeFunc cloneNodeCallback = nullptr; void* context = nullptr; - bool printTree = false; + YGMarkerCallbacks markerCallbacks = {nullptr, nullptr}; YGConfig(YGLogger logger); }; diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h new file mode 100644 index 00000000..00c582ab --- /dev/null +++ b/yoga/YGMarker.h @@ -0,0 +1,32 @@ +/** + * 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 "YGMacros.h" + +YG_EXTERN_C_BEGIN + +typedef struct YGNode* YGNodeRef; + +typedef YG_ENUM_BEGIN(YGMarkerType) {} +YG_ENUM_END(YGMarkerType); + +typedef union { + int unused; +} YGMarkerData; + +typedef struct { + // accepts marker type, a node ref, and marker data (depends on marker type) + // can return a handle or id that Yoga will pass to endMarker + void* (*startMarker)(YGMarkerType, YGNodeRef, YGMarkerData); + // accepts marker type, a node ref, marker data, and marker id as returned + // by startMarker + void (*endMarker)(YGMarkerType, YGNodeRef, YGMarkerData, void* id); +} YGMarkerCallbacks; + +YG_EXTERN_C_END From 8e48edaa0bf25f38052a3b3297705e61416701b0 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Mon, 26 Nov 2018 07:26:28 -0800 Subject: [PATCH 102/189] calling markDirtyAndPropogate when setting isReferenceBaseline value Summary: @public Marking the node as dirty when isReferenceBaseline property is changed Reviewed By: davidaurelio Differential Revision: D13147742 fbshipit-source-id: 3bbff1cfceeadfbf77380519e4638f2984fc2009 --- yoga/Yoga.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 10f27bf0..491cc1ee 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -381,7 +381,10 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) { } void YGNodeSetIsReferenceBaseline(YGNodeRef node, bool isReferenceBaseline) { - node->setIsReferenceBaseline(isReferenceBaseline); + if (node->isReferenceBaseline() != isReferenceBaseline) { + node->setIsReferenceBaseline(isReferenceBaseline); + node->markDirtyAndPropogate(); + } } bool YGNodeIsReferenceBaseline(YGNodeRef node) { From 9725d5b21b550da8d17453047d30d8e53df08bfe Mon Sep 17 00:00:00 2001 From: Tomas Reimers Date: Mon, 26 Nov 2018 16:00:37 -0800 Subject: [PATCH 103/189] Create a recursive free with cleanup function Reviewed By: davidaurelio Differential Revision: D13119307 fbshipit-source-id: 162bb4fd6d7620f61cbac010d0dc236d81738b71 --- yoga/Yoga.cpp | 11 ++++++++++- yoga/Yoga.h | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 491cc1ee..463107ee 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -319,7 +319,9 @@ static void YGConfigFreeRecursive(const YGNodeRef root) { } } -void YGNodeFreeRecursive(const YGNodeRef root) { +void YGNodeFreeRecursiveWithCleanupFunc( + const YGNodeRef root, + YGNodeCleanupFunc cleanup) { while (YGNodeGetChildCount(root) > 0) { const YGNodeRef child = YGNodeGetChild(root, 0); if (child->getOwner() != root) { @@ -329,9 +331,16 @@ void YGNodeFreeRecursive(const YGNodeRef root) { YGNodeRemoveChild(root, child); YGNodeFreeRecursive(child); } + if (cleanup != nullptr) { + cleanup(root); + } YGNodeFree(root); } +void YGNodeFreeRecursive(const YGNodeRef root) { + return YGNodeFreeRecursiveWithCleanupFunc(root, nullptr); +} + void YGNodeReset(const YGNodeRef node) { YGAssertWithNode( node, diff --git a/yoga/Yoga.h b/yoga/Yoga.h index dddab8bb..04e0bf1d 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -70,6 +70,7 @@ typedef float ( *YGBaselineFunc)(YGNodeRef node, const float width, const float height); typedef void (*YGDirtiedFunc)(YGNodeRef node); typedef void (*YGPrintFunc)(YGNodeRef node); +typedef void (*YGNodeCleanupFunc)(YGNodeRef node); typedef int (*YGLogger)( const YGConfigRef config, const YGNodeRef node, @@ -84,6 +85,9 @@ WIN_EXPORT YGNodeRef YGNodeNew(void); WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config); WIN_EXPORT YGNodeRef YGNodeClone(const YGNodeRef node); WIN_EXPORT void YGNodeFree(const YGNodeRef node); +WIN_EXPORT void YGNodeFreeRecursiveWithCleanupFunc( + const YGNodeRef node, + YGNodeCleanupFunc cleanup); WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node); WIN_EXPORT void YGNodeReset(const YGNodeRef node); WIN_EXPORT int32_t YGNodeGetInstanceCount(void); From 6d8ee777917971a5605379af0e901cda3681add6 Mon Sep 17 00:00:00 2001 From: Tnarita0000 Date: Tue, 27 Nov 2018 03:39:54 -0800 Subject: [PATCH 104/189] Fix typo 'laid our' to 'laid out' (#833) Summary: I've fixed typo `laid our` to `laid out` in [`website/contents/properties/layout-direction.md`]. Pull Request resolved: https://github.com/facebook/yoga/pull/833 Differential Revision: D13196468 Pulled By: passy fbshipit-source-id: 8b51e0d93fd0b6b131b7ea9446fff28ffeca9764 --- website/contents/properties/layout-direction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/contents/properties/layout-direction.md b/website/contents/properties/layout-direction.md index 869b5d47..76c43fd2 100644 --- a/website/contents/properties/layout-direction.md +++ b/website/contents/properties/layout-direction.md @@ -14,10 +14,10 @@ refers to `right`. When localizing your apps for markets with RTL languages you should customize this by either by passing a direction to the `CalculateLayout` call or by setting the direction on the root node. -**LTR (DEFAULT)** Text and children and laid our from left to right. Margin and +**LTR (DEFAULT)** Text and children and laid out from left to right. Margin and padding applied the start of an element are applied on the left side. -**RTL** Text and children and laid our from right to left. Margin and +**RTL** Text and children and laid out from right to left. Margin and padding applied the start of an element are applied on the right side. From bdae838516856b1548b9c237f027002a296b3c93 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Tue, 27 Nov 2018 15:13:56 -0800 Subject: [PATCH 105/189] Sort build file loads. Summary: drop-conflicts Reviewed By: passy Differential Revision: D13176350 fbshipit-source-id: 0f875a6c0f1eca2f992026bb2b2d0851f90f5d2f --- android/sample/BUCK | 2 +- csharp/BUCK | 2 +- lib/appcompat/BUCK | 2 +- lib/soloader/BUCK | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/sample/BUCK b/android/sample/BUCK index 0989fcd6..7a408bb9 100644 --- a/android/sample/BUCK +++ b/android/sample/BUCK @@ -4,8 +4,8 @@ # This source code is licensed under the license found in the # LICENSE-examples file in the root directory of this source tree. -load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource") +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") yoga_android_binary( name = "sample", diff --git a/csharp/BUCK b/csharp/BUCK index 685b227f..0f8a0bf8 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -3,7 +3,6 @@ # 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:fb_native_wrapper.bzl", "fb_native") load( "//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", @@ -11,6 +10,7 @@ load( "yoga_cxx_library", "yoga_dep", ) +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"] diff --git a/lib/appcompat/BUCK b/lib/appcompat/BUCK index b3262494..670c5f20 100644 --- a/lib/appcompat/BUCK +++ b/lib/appcompat/BUCK @@ -3,8 +3,8 @@ # 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:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") fb_native.android_prebuilt_aar( name = "appcompat", diff --git a/lib/soloader/BUCK b/lib/soloader/BUCK index 04e2f5ff..5f3cc331 100644 --- a/lib/soloader/BUCK +++ b/lib/soloader/BUCK @@ -3,8 +3,8 @@ # 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:fb_native_wrapper.bzl", "fb_native") load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") fb_native.android_prebuilt_aar( name = "soloader", From 6f6e0ce339cd310fd9ba7f4f9b068684331e0938 Mon Sep 17 00:00:00 2001 From: Eddie Zhang Date: Thu, 29 Nov 2018 11:13:36 -0800 Subject: [PATCH 106/189] Fix typo in Yoga Layout documentation Summary: Found and fixed typo on https://yogalayout.com/docs/justify-content/ Reviewed By: danielbuechele Differential Revision: D13199988 fbshipit-source-id: 029cf812f09c48822ec11b054bf0c987f718191d --- website/contents/properties/justify-content.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/contents/properties/justify-content.md b/website/contents/properties/justify-content.md index af159e66..84ccb335 100644 --- a/website/contents/properties/justify-content.md +++ b/website/contents/properties/justify-content.md @@ -22,7 +22,7 @@ remaining space between the children. **SPACE AROUND** Evenly space of children across the container's main axis, distributing remaining space around the children. Compared to `space between` using -`Sspace around` will result in space being distributed to the beginning of +`space around` will result in space being distributed to the beginning of the first child and end of the last child. From 98c1c180afdb053e13e7212e979191f73ac6ad59 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 29 Nov 2018 11:35:34 -0800 Subject: [PATCH 107/189] Remove extraneous file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public This file shouldn’t be here Reviewed By: SidharthGuglani Differential Revision: D13255658 fbshipit-source-id: 1b40ab674bbf451d04797516a24c3bd2fef7222d --- .../yoga/src/main/cpp/yoga/Yoga-internal.h | 121 ------------------ 1 file changed, 121 deletions(-) delete mode 100644 fbandroid/libraries/components/lib/yoga/src/main/cpp/yoga/Yoga-internal.h diff --git a/fbandroid/libraries/components/lib/yoga/src/main/cpp/yoga/Yoga-internal.h b/fbandroid/libraries/components/lib/yoga/src/main/cpp/yoga/Yoga-internal.h deleted file mode 100644 index ccc9e197..00000000 --- a/fbandroid/libraries/components/lib/yoga/src/main/cpp/yoga/Yoga-internal.h +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#pragma once -#include -#include -#include -#include -#include "Yoga.h" - -using YGVector = std::vector; - -YG_EXTERN_C_BEGIN - -WIN_EXPORT float YGRoundValueToPixelGrid( - const float value, - const float pointScaleFactor, - const bool forceCeil, - const bool forceFloor); - -YG_EXTERN_C_END - -extern const std::array trailing; -extern const std::array leading; -extern bool YGValueEqual(const YGValue a, const YGValue b); -extern const YGValue YGValueUndefined; -extern const YGValue YGValueAuto; -extern const YGValue YGValueZero; - -template -bool YGValueArrayEqual( - const std::array val1, - const std::array val2) { - bool areEqual = true; - for (uint32_t i = 0; i < size && areEqual; ++i) { - areEqual = YGValueEqual(val1[i], val2[i]); - } - return areEqual; -} - -const YGValue kYGValueUndefined = {YGUndefined, YGUnitUndefined}; -const YGValue kYGValueAuto = {YGUndefined, YGUnitAuto}; -const std::array kYGDefaultEdgeValuesUnit = { - {kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined}}; -const std::array kYGDefaultDimensionValuesAutoUnit = { - {kYGValueAuto, kYGValueAuto}}; -const std::array kYGDefaultDimensionValuesUnit = { - {kYGValueUndefined, kYGValueUndefined}}; - -struct YGCachedMeasurement { - float availableWidth; - float availableHeight; - YGMeasureMode widthMeasureMode; - YGMeasureMode heightMeasureMode; - - float computedWidth; - float computedHeight; - - bool operator==(YGCachedMeasurement measurement) const { - bool isEqual = widthMeasureMode == measurement.widthMeasureMode && - heightMeasureMode == measurement.heightMeasureMode; - - if (!std::isnan(availableWidth) || - !std::isnan(measurement.availableWidth)) { - isEqual = isEqual && availableWidth == measurement.availableWidth; - } - if (!std::isnan(availableHeight) || - !std::isnan(measurement.availableHeight)) { - isEqual = isEqual && availableHeight == measurement.availableHeight; - } - if (!std::isnan(computedWidth) || !std::isnan(measurement.computedWidth)) { - isEqual = isEqual && computedWidth == measurement.computedWidth; - } - if (!std::isnan(computedHeight) || - !std::isnan(measurement.computedHeight)) { - isEqual = isEqual && computedHeight == measurement.computedHeight; - } - - return isEqual; - } -}; - -// This value was chosen based on empiracle data. Even the most complicated -// layouts should not require more than 16 entries to fit within the cache. -#define YG_MAX_CACHED_RESULT_COUNT 16 - -struct YGConfig { - bool experimentalFeatures[YGExperimentalFeatureCount + 1]; - bool useWebDefaults; - bool useLegacyStretchBehaviour; - bool shouldDiffLayoutWithoutLegacyStretchBehaviour; - float pointScaleFactor; - YGLogger logger; - YGNodeClonedFunc cloneNodeCallback; - void* context; -}; - -static const float kDefaultFlexGrow = 0.0f; -static const float kDefaultFlexShrink = 0.0f; -static const float kWebDefaultFlexShrink = 1.0f; - -extern bool YGFloatsEqual(const float a, const float b); -extern bool YGValueEqual(const YGValue a, const YGValue b); -extern const YGValue* YGComputedEdgeValue( - const std::array& edges, - const YGEdge edge, - const YGValue* const defaultValue); From b9972cee6e9958076a2d8ad2e1054d207a229809 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 29 Nov 2018 11:35:34 -0800 Subject: [PATCH 108/189] Adjust yearless format for MIT license Summary: @public Adjust license headers throughout the project Reviewed By: SidharthGuglani Differential Revision: D13255691 fbshipit-source-id: 98be2aa372a94e7a54a65e3d64e5c6a436b18083 --- YogaKit/Source/UIView+Yoga.h | 5 ++--- YogaKit/Source/YGLayout+Private.h | 5 ++--- YogaKit/Source/YGLayout.h | 5 ++--- benchmark/YGBenchmark.c | 5 ++--- csharp/Yoga/YGInterop.cpp | 5 ++--- csharp/Yoga/YGInterop.h | 5 ++--- csharp/Yoga/dllmain.cpp | 5 ++--- csharp/Yoga/stdafx.cpp | 5 ++--- csharp/Yoga/stdafx.h | 5 ++--- csharp/Yoga/targetver.h | 5 ++--- java/jni/YGJNI.cpp | 9 ++++----- javascript/sources/Config.cc | 5 ++--- javascript/sources/Node.cc | 5 ++--- javascript/sources/global.cc | 5 ++--- javascript/sources/nbind.cc | 5 ++--- lib/fb/src/main/cpp/assert.cpp | 7 +++---- lib/fb/src/main/cpp/include/fb/ALog.h | 7 +++---- lib/fb/src/main/cpp/include/fb/Countable.h | 7 +++---- lib/fb/src/main/cpp/include/fb/Environment.h | 7 +++---- lib/fb/src/main/cpp/include/fb/ProgramLocation.h | 7 +++---- lib/fb/src/main/cpp/include/fb/RefPtr.h | 7 +++---- lib/fb/src/main/cpp/include/fb/StaticInitialized.h | 7 +++---- lib/fb/src/main/cpp/include/fb/ThreadLocal.h | 7 +++---- lib/fb/src/main/cpp/include/fb/assert.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Boxed.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/ByteBuffer.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Common.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Context.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h | 9 ++++----- lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Exceptions.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/File.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h | 9 ++++----- lib/fb/src/main/cpp/include/fb/fbjni/Iterator-inl.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Iterator.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/JThread.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Meta-forward.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h | 9 ++++----- lib/fb/src/main/cpp/include/fb/fbjni/Meta.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/MetaConvert.h | 8 ++++++-- lib/fb/src/main/cpp/include/fb/fbjni/NativeRunnable.h | 7 +++---- .../main/cpp/include/fb/fbjni/ReferenceAllocators-inl.h | 7 +++---- .../src/main/cpp/include/fb/fbjni/ReferenceAllocators.h | 7 +++---- .../src/main/cpp/include/fb/fbjni/References-forward.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h | 9 ++++----- lib/fb/src/main/cpp/include/fb/fbjni/References.h | 8 +++----- lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h | 9 ++++----- lib/fb/src/main/cpp/include/fb/fbjni/Registration.h | 7 +++---- lib/fb/src/main/cpp/include/fb/fbjni/TypeTraits.h | 7 +++---- lib/fb/src/main/cpp/include/fb/lyra.h | 8 ++++++-- lib/fb/src/main/cpp/include/fb/noncopyable.h | 7 +++---- lib/fb/src/main/cpp/include/fb/nonmovable.h | 7 +++---- lib/fb/src/main/cpp/include/fb/visibility.h | 7 +++---- lib/fb/src/main/cpp/include/jni/Countable.h | 7 +++---- lib/fb/src/main/cpp/include/jni/GlobalReference.h | 7 +++---- lib/fb/src/main/cpp/include/jni/LocalReference.h | 7 +++---- lib/fb/src/main/cpp/include/jni/LocalString.h | 7 +++---- lib/fb/src/main/cpp/include/jni/Registration.h | 7 +++---- lib/fb/src/main/cpp/include/jni/WeakReference.h | 7 +++---- lib/fb/src/main/cpp/include/jni/jni_helpers.h | 7 +++---- lib/fb/src/main/cpp/jni/ByteBuffer.cpp | 7 +++---- lib/fb/src/main/cpp/jni/Countable.cpp | 7 +++---- lib/fb/src/main/cpp/jni/Environment.cpp | 7 +++---- lib/fb/src/main/cpp/jni/Exceptions.cpp | 7 +++---- lib/fb/src/main/cpp/jni/Hybrid.cpp | 7 +++---- lib/fb/src/main/cpp/jni/LocalString.cpp | 7 +++---- lib/fb/src/main/cpp/jni/OnLoad.cpp | 7 +++---- lib/fb/src/main/cpp/jni/References.cpp | 7 +++---- lib/fb/src/main/cpp/jni/WeakReference.cpp | 7 +++---- lib/fb/src/main/cpp/jni/fbjni.cpp | 7 +++---- lib/fb/src/main/cpp/jni/jni_helpers.cpp | 7 +++---- lib/fb/src/main/cpp/log.cpp | 7 +++---- lib/fb/src/main/cpp/lyra/lyra.cpp | 8 ++++++-- lib/fb/src/main/cpp/onload.cpp | 7 +++---- lib/jni/jni.h | 5 ++--- tests/YGAbsolutePositionTest.cpp | 5 ++--- tests/YGAlignBaselineTest.cpp | 9 ++++----- tests/YGAlignContentTest.cpp | 5 ++--- tests/YGAlignItemsTest.cpp | 9 ++++----- tests/YGAlignSelfTest.cpp | 5 ++--- tests/YGAndroidNewsFeed.cpp | 5 ++--- tests/YGAspectRatioTest.cpp | 5 ++--- tests/YGBaselineFuncTest.cpp | 5 ++--- tests/YGBorderTest.cpp | 5 ++--- tests/YGComputedMarginTest.cpp | 9 ++++----- tests/YGComputedPaddingTest.cpp | 9 ++++----- tests/YGDefaultValuesTest.cpp | 5 ++--- tests/YGDimensionTest.cpp | 5 ++--- tests/YGDirtiedTest.cpp | 5 ++--- tests/YGDirtyMarkingTest.cpp | 5 ++--- tests/YGDisplayTest.cpp | 5 ++--- tests/YGEdgeTest.cpp | 5 ++--- tests/YGFlexDirectionTest.cpp | 5 ++--- tests/YGFlexTest.cpp | 9 ++++----- tests/YGFlexWrapTest.cpp | 5 ++--- tests/YGHadOverflowTest.cpp | 8 ++++++-- tests/YGInfiniteHeightTest.cpp | 5 ++--- tests/YGJustifyContentTest.cpp | 4 ++-- tests/YGLayoutDiffingTest.cpp | 5 ++--- tests/YGLoggerTest.cpp | 9 ++++----- tests/YGMarginTest.cpp | 5 ++--- tests/YGMeasureCacheTest.cpp | 5 ++--- tests/YGMeasureModeTest.cpp | 5 ++--- tests/YGMeasureTest.cpp | 9 ++++----- tests/YGMinMaxDimensionTest.cpp | 5 ++--- tests/YGNodeChildTest.cpp | 5 ++--- tests/YGPaddingTest.cpp | 9 ++++----- tests/YGPercentageTest.cpp | 5 ++--- tests/YGPersistenceTest.cpp | 5 ++--- tests/YGRelayoutTest.cpp | 5 ++--- tests/YGRoundingFunctionTest.cpp | 9 ++++----- tests/YGRoundingMeasureFuncTest.cpp | 5 ++--- tests/YGRoundingTest.cpp | 5 ++--- tests/YGSizeOverflowTest.cpp | 5 ++--- tests/YGStyleTest.cpp | 5 ++--- tests/YGTraversalTest.cpp | 5 ++--- tests/YGTreeMutationTest.cpp | 5 ++--- tests/YGZeroOutLayoutRecursivlyTest.cpp | 5 ++--- yoga/Utils.cpp | 9 ++++----- yoga/Utils.h | 5 ++--- yoga/YGConfig.cpp | 9 ++++----- yoga/YGConfig.h | 9 ++++----- yoga/YGEnums.cpp | 5 ++--- yoga/YGEnums.h | 5 ++--- yoga/YGFloatOptional.cpp | 9 ++++----- yoga/YGFloatOptional.h | 9 ++++----- yoga/YGLayout.cpp | 9 ++++----- yoga/YGLayout.h | 9 ++++----- yoga/YGMacros.h | 5 ++--- yoga/YGMarker.h | 5 ++--- yoga/YGNode.cpp | 9 ++++----- yoga/YGNode.h | 9 ++++----- yoga/YGNodePrint.cpp | 7 +++---- yoga/YGNodePrint.h | 4 ++-- yoga/YGStyle.cpp | 9 ++++----- yoga/YGStyle.h | 9 ++++----- yoga/Yoga-internal.h | 9 ++++----- yoga/Yoga.cpp | 9 ++++----- yoga/Yoga.h | 9 ++++----- 140 files changed, 407 insertions(+), 526 deletions(-) diff --git a/YogaKit/Source/UIView+Yoga.h b/YogaKit/Source/UIView+Yoga.h index 68675188..6b012bb6 100644 --- a/YogaKit/Source/UIView+Yoga.h +++ b/YogaKit/Source/UIView+Yoga.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #import "YGLayout.h" #import diff --git a/YogaKit/Source/YGLayout+Private.h b/YogaKit/Source/YGLayout+Private.h index e680222d..601eda18 100644 --- a/YogaKit/Source/YGLayout+Private.h +++ b/YogaKit/Source/YGLayout+Private.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #import "YGLayout.h" #import diff --git a/YogaKit/Source/YGLayout.h b/YogaKit/Source/YGLayout.h index 37aa2345..8aff3b5e 100644 --- a/YogaKit/Source/YGLayout.h +++ b/YogaKit/Source/YGLayout.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #import #import #import diff --git a/benchmark/YGBenchmark.c b/benchmark/YGBenchmark.c index 3198e96f..7256e8f3 100644 --- a/benchmark/YGBenchmark.c +++ b/benchmark/YGBenchmark.c @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/csharp/Yoga/YGInterop.cpp b/csharp/Yoga/YGInterop.cpp index f4fa1337..30a8979b 100644 --- a/csharp/Yoga/YGInterop.cpp +++ b/csharp/Yoga/YGInterop.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include "YGInterop.h" static YGInteropLogger gManagedLogger; diff --git a/csharp/Yoga/YGInterop.h b/csharp/Yoga/YGInterop.h index bbd0d029..597a2cc8 100644 --- a/csharp/Yoga/YGInterop.h +++ b/csharp/Yoga/YGInterop.h @@ -1,10 +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. + * 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 diff --git a/csharp/Yoga/dllmain.cpp b/csharp/Yoga/dllmain.cpp index 18aee01d..88c48a02 100644 --- a/csharp/Yoga/dllmain.cpp +++ b/csharp/Yoga/dllmain.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // dllmain.cpp : Defines the entry point for the DLL application. #include "stdafx.h" diff --git a/csharp/Yoga/stdafx.cpp b/csharp/Yoga/stdafx.cpp index a353183e..1d59258a 100644 --- a/csharp/Yoga/stdafx.cpp +++ b/csharp/Yoga/stdafx.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // stdafx.cpp : source file that includes just the standard includes // Yoga.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information diff --git a/csharp/Yoga/stdafx.h b/csharp/Yoga/stdafx.h index c9c782b8..3d3c3aec 100644 --- a/csharp/Yoga/stdafx.h +++ b/csharp/Yoga/stdafx.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently diff --git a/csharp/Yoga/targetver.h b/csharp/Yoga/targetver.h index 91b65674..f74769cf 100644 --- a/csharp/Yoga/targetver.h +++ b/csharp/Yoga/targetver.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #pragma once // Including SDKDDKVer.h defines the highest available Windows platform. diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 8c6536d4..fb4ec3c6 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -1,9 +1,8 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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 #include diff --git a/javascript/sources/Config.cc b/javascript/sources/Config.cc index f3b4ff87..60e5bafc 100644 --- a/javascript/sources/Config.cc +++ b/javascript/sources/Config.cc @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include "./Config.hh" diff --git a/javascript/sources/Node.cc b/javascript/sources/Node.cc index c684da28..108bc4b5 100644 --- a/javascript/sources/Node.cc +++ b/javascript/sources/Node.cc @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/javascript/sources/global.cc b/javascript/sources/global.cc index 1f36c07d..96096e83 100644 --- a/javascript/sources/global.cc +++ b/javascript/sources/global.cc @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include "./global.hh" diff --git a/javascript/sources/nbind.cc b/javascript/sources/nbind.cc index 0ea7e0db..c778fe8a 100644 --- a/javascript/sources/nbind.cc +++ b/javascript/sources/nbind.cc @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include "./Node.hh" diff --git a/lib/fb/src/main/cpp/assert.cpp b/lib/fb/src/main/cpp/assert.cpp index dd64bebc..be64e787 100644 --- a/lib/fb/src/main/cpp/assert.cpp +++ b/lib/fb/src/main/cpp/assert.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/lib/fb/src/main/cpp/include/fb/ALog.h b/lib/fb/src/main/cpp/include/fb/ALog.h index 164288b4..6ea846ee 100644 --- a/lib/fb/src/main/cpp/include/fb/ALog.h +++ b/lib/fb/src/main/cpp/include/fb/ALog.h @@ -1,10 +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. + * 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. diff --git a/lib/fb/src/main/cpp/include/fb/Countable.h b/lib/fb/src/main/cpp/include/fb/Countable.h index 01afe983..b355ab67 100644 --- a/lib/fb/src/main/cpp/include/fb/Countable.h +++ b/lib/fb/src/main/cpp/include/fb/Countable.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/fb/Environment.h b/lib/fb/src/main/cpp/include/fb/Environment.h index 55f12f95..53b14c80 100644 --- a/lib/fb/src/main/cpp/include/fb/Environment.h +++ b/lib/fb/src/main/cpp/include/fb/Environment.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/fb/ProgramLocation.h b/lib/fb/src/main/cpp/include/fb/ProgramLocation.h index cc23ee71..57c44c1d 100644 --- a/lib/fb/src/main/cpp/include/fb/ProgramLocation.h +++ b/lib/fb/src/main/cpp/include/fb/ProgramLocation.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/fb/RefPtr.h b/lib/fb/src/main/cpp/include/fb/RefPtr.h index e39bd026..8c22a151 100644 --- a/lib/fb/src/main/cpp/include/fb/RefPtr.h +++ b/lib/fb/src/main/cpp/include/fb/RefPtr.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/fb/StaticInitialized.h b/lib/fb/src/main/cpp/include/fb/StaticInitialized.h index 566e02cd..c8b84dea 100644 --- a/lib/fb/src/main/cpp/include/fb/StaticInitialized.h +++ b/lib/fb/src/main/cpp/include/fb/StaticInitialized.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/fb/ThreadLocal.h b/lib/fb/src/main/cpp/include/fb/ThreadLocal.h index 675950fc..4ea9e6ca 100644 --- a/lib/fb/src/main/cpp/include/fb/ThreadLocal.h +++ b/lib/fb/src/main/cpp/include/fb/ThreadLocal.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/assert.h b/lib/fb/src/main/cpp/include/fb/assert.h index a6b747f7..f6dce42b 100644 --- a/lib/fb/src/main/cpp/include/fb/assert.h +++ b/lib/fb/src/main/cpp/include/fb/assert.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni.h b/lib/fb/src/main/cpp/include/fb/fbjni.h index 49e4f502..9f0da1ab 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Boxed.h b/lib/fb/src/main/cpp/include/fb/fbjni/Boxed.h index 71058e04..36ab9a31 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Boxed.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Boxed.h @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/ByteBuffer.h b/lib/fb/src/main/cpp/include/fb/fbjni/ByteBuffer.h index 61f7be9f..41c7acc3 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/ByteBuffer.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/ByteBuffer.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Common.h b/lib/fb/src/main/cpp/include/fb/fbjni/Common.h index 0a6e8521..6025f6d6 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Common.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Common.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - /** @file Common.h * * Defining the stuff that don't deserve headers of their own... diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Context.h b/lib/fb/src/main/cpp/include/fb/fbjni/Context.h index 4505842c..cf5bcb2d 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Context.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Context.h @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h index fd927843..e5c86069 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses-inl.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses.h b/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses.h index 8b2ba839..227e9c79 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/CoreClasses.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #pragma once /** @file CoreClasses.h diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Exceptions.h b/lib/fb/src/main/cpp/include/fb/fbjni/Exceptions.h index 4a47619d..fe28154f 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Exceptions.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Exceptions.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - /** * @file Exceptions.h * diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/File.h b/lib/fb/src/main/cpp/include/fb/fbjni/File.h index 9b52183a..857826cc 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/File.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/File.h @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h b/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h index f34ec0f7..8db5b0b9 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Hybrid.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Iterator-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/Iterator-inl.h index 8e7083c8..f7c62dcc 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Iterator-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Iterator-inl.h @@ -1,10 +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. + * 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 { diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Iterator.h b/lib/fb/src/main/cpp/include/fb/fbjni/Iterator.h index 1fae26fb..18afea6a 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Iterator.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Iterator.h @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/JThread.h b/lib/fb/src/main/cpp/include/fb/fbjni/JThread.h index 6bcf9641..7ef4b63b 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/JThread.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/JThread.h @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Meta-forward.h b/lib/fb/src/main/cpp/include/fb/fbjni/Meta-forward.h index 833acc04..e975f884 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Meta-forward.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Meta-forward.h @@ -1,10 +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. + * 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 { diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h index eeac9a01..dfa2c375 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Meta-inl.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Meta.h b/lib/fb/src/main/cpp/include/fb/fbjni/Meta.h index ec5eb6ef..418dffbd 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Meta.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Meta.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - /** @file meta.h * * Provides wrappers for meta data such as methods and fields. diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/MetaConvert.h b/lib/fb/src/main/cpp/include/fb/fbjni/MetaConvert.h index 33027c7e..690a6164 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/MetaConvert.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/MetaConvert.h @@ -1,5 +1,9 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/NativeRunnable.h b/lib/fb/src/main/cpp/include/fb/fbjni/NativeRunnable.h index 015c42e5..f459ebf6 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/NativeRunnable.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/NativeRunnable.h @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators-inl.h index 60ca6531..907ff603 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators-inl.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators.h b/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators.h index 7ccdc5db..e20eef9b 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/ReferenceAllocators.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - /** * @file ReferenceAllocators.h * diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/References-forward.h b/lib/fb/src/main/cpp/include/fb/fbjni/References-forward.h index 78b4f327..eab78de8 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/References-forward.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/References-forward.h @@ -1,10 +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. + * 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 "ReferenceAllocators.h" diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h index c5049f51..d3329f41 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/References-inl.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/References.h b/lib/fb/src/main/cpp/include/fb/fbjni/References.h index 884e68d7..00492501 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/References.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/References.h @@ -1,11 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - - /** @file References.h * * Functionality similar to smart pointers, but for references into the VM. Four main reference diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h b/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h index fc1422e3..030baace 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Registration-inl.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/Registration.h b/lib/fb/src/main/cpp/include/fb/fbjni/Registration.h index 74cd7b40..7545840e 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/Registration.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/Registration.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/fbjni/TypeTraits.h b/lib/fb/src/main/cpp/include/fb/fbjni/TypeTraits.h index c38a90b3..95c146fc 100644 --- a/lib/fb/src/main/cpp/include/fb/fbjni/TypeTraits.h +++ b/lib/fb/src/main/cpp/include/fb/fbjni/TypeTraits.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/lyra.h b/lib/fb/src/main/cpp/include/fb/lyra.h index c60ff27b..0d199e6e 100644 --- a/lib/fb/src/main/cpp/include/fb/lyra.h +++ b/lib/fb/src/main/cpp/include/fb/lyra.h @@ -1,5 +1,9 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/** + * 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 diff --git a/lib/fb/src/main/cpp/include/fb/noncopyable.h b/lib/fb/src/main/cpp/include/fb/noncopyable.h index 283f0fac..ec00ada5 100644 --- a/lib/fb/src/main/cpp/include/fb/noncopyable.h +++ b/lib/fb/src/main/cpp/include/fb/noncopyable.h @@ -1,10 +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. + * 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 { diff --git a/lib/fb/src/main/cpp/include/fb/nonmovable.h b/lib/fb/src/main/cpp/include/fb/nonmovable.h index 819f7193..9b39b8c6 100644 --- a/lib/fb/src/main/cpp/include/fb/nonmovable.h +++ b/lib/fb/src/main/cpp/include/fb/nonmovable.h @@ -1,10 +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. + * 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 { diff --git a/lib/fb/src/main/cpp/include/fb/visibility.h b/lib/fb/src/main/cpp/include/fb/visibility.h index 098d5ddc..310fbe11 100644 --- a/lib/fb/src/main/cpp/include/fb/visibility.h +++ b/lib/fb/src/main/cpp/include/fb/visibility.h @@ -1,10 +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. + * 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"))) diff --git a/lib/fb/src/main/cpp/include/jni/Countable.h b/lib/fb/src/main/cpp/include/jni/Countable.h index 8a8d3206..b2708aae 100644 --- a/lib/fb/src/main/cpp/include/jni/Countable.h +++ b/lib/fb/src/main/cpp/include/jni/Countable.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/jni/GlobalReference.h b/lib/fb/src/main/cpp/include/jni/GlobalReference.h index 15624bb5..9ebdfcd5 100644 --- a/lib/fb/src/main/cpp/include/jni/GlobalReference.h +++ b/lib/fb/src/main/cpp/include/jni/GlobalReference.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/jni/LocalReference.h b/lib/fb/src/main/cpp/include/jni/LocalReference.h index 03aad078..b565ee74 100644 --- a/lib/fb/src/main/cpp/include/jni/LocalReference.h +++ b/lib/fb/src/main/cpp/include/jni/LocalReference.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/jni/LocalString.h b/lib/fb/src/main/cpp/include/jni/LocalString.h index 19edabf5..34316531 100644 --- a/lib/fb/src/main/cpp/include/jni/LocalString.h +++ b/lib/fb/src/main/cpp/include/jni/LocalString.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/include/jni/Registration.h b/lib/fb/src/main/cpp/include/jni/Registration.h index 1b19418e..553ddaf8 100644 --- a/lib/fb/src/main/cpp/include/jni/Registration.h +++ b/lib/fb/src/main/cpp/include/jni/Registration.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/jni/WeakReference.h b/lib/fb/src/main/cpp/include/jni/WeakReference.h index 7b1df7c8..70630b10 100644 --- a/lib/fb/src/main/cpp/include/jni/WeakReference.h +++ b/lib/fb/src/main/cpp/include/jni/WeakReference.h @@ -1,10 +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. + * 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 #include diff --git a/lib/fb/src/main/cpp/include/jni/jni_helpers.h b/lib/fb/src/main/cpp/include/jni/jni_helpers.h index cabf6572..cf6504a4 100644 --- a/lib/fb/src/main/cpp/include/jni/jni_helpers.h +++ b/lib/fb/src/main/cpp/include/jni/jni_helpers.h @@ -1,10 +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. + * 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 diff --git a/lib/fb/src/main/cpp/jni/ByteBuffer.cpp b/lib/fb/src/main/cpp/jni/ByteBuffer.cpp index dce234fd..9d7cbda9 100644 --- a/lib/fb/src/main/cpp/jni/ByteBuffer.cpp +++ b/lib/fb/src/main/cpp/jni/ByteBuffer.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/lib/fb/src/main/cpp/jni/Countable.cpp b/lib/fb/src/main/cpp/jni/Countable.cpp index 1d4bfc55..bbb6f23d 100644 --- a/lib/fb/src/main/cpp/jni/Countable.cpp +++ b/lib/fb/src/main/cpp/jni/Countable.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/lib/fb/src/main/cpp/jni/Environment.cpp b/lib/fb/src/main/cpp/jni/Environment.cpp index b9523df3..8d37cb52 100644 --- a/lib/fb/src/main/cpp/jni/Environment.cpp +++ b/lib/fb/src/main/cpp/jni/Environment.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/lib/fb/src/main/cpp/jni/Exceptions.cpp b/lib/fb/src/main/cpp/jni/Exceptions.cpp index 754a2d4d..8688dfbf 100644 --- a/lib/fb/src/main/cpp/jni/Exceptions.cpp +++ b/lib/fb/src/main/cpp/jni/Exceptions.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/lib/fb/src/main/cpp/jni/Hybrid.cpp b/lib/fb/src/main/cpp/jni/Hybrid.cpp index 2956bba2..c04560a5 100644 --- a/lib/fb/src/main/cpp/jni/Hybrid.cpp +++ b/lib/fb/src/main/cpp/jni/Hybrid.cpp @@ -1,10 +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. + * 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" diff --git a/lib/fb/src/main/cpp/jni/LocalString.cpp b/lib/fb/src/main/cpp/jni/LocalString.cpp index 073ef32f..9233ec02 100644 --- a/lib/fb/src/main/cpp/jni/LocalString.cpp +++ b/lib/fb/src/main/cpp/jni/LocalString.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/lib/fb/src/main/cpp/jni/OnLoad.cpp b/lib/fb/src/main/cpp/jni/OnLoad.cpp index ebd8c879..a95393f8 100644 --- a/lib/fb/src/main/cpp/jni/OnLoad.cpp +++ b/lib/fb/src/main/cpp/jni/OnLoad.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/lib/fb/src/main/cpp/jni/References.cpp b/lib/fb/src/main/cpp/jni/References.cpp index d41010f8..71284b0e 100644 --- a/lib/fb/src/main/cpp/jni/References.cpp +++ b/lib/fb/src/main/cpp/jni/References.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include namespace facebook { diff --git a/lib/fb/src/main/cpp/jni/WeakReference.cpp b/lib/fb/src/main/cpp/jni/WeakReference.cpp index bdf3f24d..5552a763 100644 --- a/lib/fb/src/main/cpp/jni/WeakReference.cpp +++ b/lib/fb/src/main/cpp/jni/WeakReference.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/lib/fb/src/main/cpp/jni/fbjni.cpp b/lib/fb/src/main/cpp/jni/fbjni.cpp index 51adf9a8..c556fabb 100644 --- a/lib/fb/src/main/cpp/jni/fbjni.cpp +++ b/lib/fb/src/main/cpp/jni/fbjni.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/lib/fb/src/main/cpp/jni/jni_helpers.cpp b/lib/fb/src/main/cpp/jni/jni_helpers.cpp index 86dbbc57..c45217bf 100644 --- a/lib/fb/src/main/cpp/jni/jni_helpers.cpp +++ b/lib/fb/src/main/cpp/jni/jni_helpers.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/lib/fb/src/main/cpp/log.cpp b/lib/fb/src/main/cpp/log.cpp index 7d2a70df..8d22bcbc 100644 --- a/lib/fb/src/main/cpp/log.cpp +++ b/lib/fb/src/main/cpp/log.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/lib/fb/src/main/cpp/lyra/lyra.cpp b/lib/fb/src/main/cpp/lyra/lyra.cpp index f915ecef..4d125da7 100644 --- a/lib/fb/src/main/cpp/lyra/lyra.cpp +++ b/lib/fb/src/main/cpp/lyra/lyra.cpp @@ -1,5 +1,9 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/** + * 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 #include diff --git a/lib/fb/src/main/cpp/onload.cpp b/lib/fb/src/main/cpp/onload.cpp index 158d8832..c451bcba 100644 --- a/lib/fb/src/main/cpp/onload.cpp +++ b/lib/fb/src/main/cpp/onload.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #ifndef DISABLE_CPUCAP #include diff --git a/lib/jni/jni.h b/lib/jni/jni.h index 34d46448..91b28ab4 100644 --- a/lib/jni/jni.h +++ b/lib/jni/jni.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #pragma once #ifdef __ANDROID__ diff --git a/tests/YGAbsolutePositionTest.cpp b/tests/YGAbsolutePositionTest.cpp index f9ec49a3..1faf554f 100644 --- a/tests/YGAbsolutePositionTest.cpp +++ b/tests/YGAbsolutePositionTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGAbsolutePositionTest.html #include diff --git a/tests/YGAlignBaselineTest.cpp b/tests/YGAlignBaselineTest.cpp index 0ede52bd..eae27908 100644 --- a/tests/YGAlignBaselineTest.cpp +++ b/tests/YGAlignBaselineTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 #include diff --git a/tests/YGAlignContentTest.cpp b/tests/YGAlignContentTest.cpp index 1a46ad50..af6fe529 100644 --- a/tests/YGAlignContentTest.cpp +++ b/tests/YGAlignContentTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignContentTest.html #include diff --git a/tests/YGAlignItemsTest.cpp b/tests/YGAlignItemsTest.cpp index 0b4ddba1..345b6a29 100644 --- a/tests/YGAlignItemsTest.cpp +++ b/tests/YGAlignItemsTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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. */ // @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignItemsTest.html diff --git a/tests/YGAlignSelfTest.cpp b/tests/YGAlignSelfTest.cpp index eec2bae4..8bcacff7 100644 --- a/tests/YGAlignSelfTest.cpp +++ b/tests/YGAlignSelfTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignSelfTest.html #include diff --git a/tests/YGAndroidNewsFeed.cpp b/tests/YGAndroidNewsFeed.cpp index 9496bf71..db3753d6 100644 --- a/tests/YGAndroidNewsFeed.cpp +++ b/tests/YGAndroidNewsFeed.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGAndroidNewsFeed.html #include diff --git a/tests/YGAspectRatioTest.cpp b/tests/YGAspectRatioTest.cpp index 8f2dc8e3..9d99569b 100644 --- a/tests/YGAspectRatioTest.cpp +++ b/tests/YGAspectRatioTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGBaselineFuncTest.cpp b/tests/YGBaselineFuncTest.cpp index 362904cb..97d86050 100644 --- a/tests/YGBaselineFuncTest.cpp +++ b/tests/YGBaselineFuncTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGBorderTest.cpp b/tests/YGBorderTest.cpp index 540c448a..75571ccc 100644 --- a/tests/YGBorderTest.cpp +++ b/tests/YGBorderTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGBorderTest.html #include diff --git a/tests/YGComputedMarginTest.cpp b/tests/YGComputedMarginTest.cpp index a3d1f442..8468dd6b 100644 --- a/tests/YGComputedMarginTest.cpp +++ b/tests/YGComputedMarginTest.cpp @@ -1,9 +1,8 @@ -/* - * Copyright (c) Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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 #include diff --git a/tests/YGComputedPaddingTest.cpp b/tests/YGComputedPaddingTest.cpp index fad7ce1b..2a22607f 100644 --- a/tests/YGComputedPaddingTest.cpp +++ b/tests/YGComputedPaddingTest.cpp @@ -1,9 +1,8 @@ -/* - * Copyright (c) Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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 #include diff --git a/tests/YGDefaultValuesTest.cpp b/tests/YGDefaultValuesTest.cpp index 82aa7323..4d4d2c5c 100644 --- a/tests/YGDefaultValuesTest.cpp +++ b/tests/YGDefaultValuesTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGDimensionTest.cpp b/tests/YGDimensionTest.cpp index 04a14846..9baf4006 100644 --- a/tests/YGDimensionTest.cpp +++ b/tests/YGDimensionTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGDimensionTest.html #include diff --git a/tests/YGDirtiedTest.cpp b/tests/YGDirtiedTest.cpp index f68c1450..5fb291be 100644 --- a/tests/YGDirtiedTest.cpp +++ b/tests/YGDirtiedTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGDirtyMarkingTest.cpp b/tests/YGDirtyMarkingTest.cpp index 709b8904..984e7228 100644 --- a/tests/YGDirtyMarkingTest.cpp +++ b/tests/YGDirtyMarkingTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGDisplayTest.cpp b/tests/YGDisplayTest.cpp index 46e3ed3e..52ff9cc8 100644 --- a/tests/YGDisplayTest.cpp +++ b/tests/YGDisplayTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html #include diff --git a/tests/YGEdgeTest.cpp b/tests/YGEdgeTest.cpp index f4d92d7c..fb907df6 100644 --- a/tests/YGEdgeTest.cpp +++ b/tests/YGEdgeTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGFlexDirectionTest.cpp b/tests/YGFlexDirectionTest.cpp index 7bd003df..92bc450d 100644 --- a/tests/YGFlexDirectionTest.cpp +++ b/tests/YGFlexDirectionTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexDirectionTest.html #include diff --git a/tests/YGFlexTest.cpp b/tests/YGFlexTest.cpp index 67cc2bbc..5ba49f43 100644 --- a/tests/YGFlexTest.cpp +++ b/tests/YGFlexTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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. */ // @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html diff --git a/tests/YGFlexWrapTest.cpp b/tests/YGFlexWrapTest.cpp index abe241a1..12d4e353 100644 --- a/tests/YGFlexWrapTest.cpp +++ b/tests/YGFlexWrapTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexWrapTest.html #include diff --git a/tests/YGHadOverflowTest.cpp b/tests/YGHadOverflowTest.cpp index 47dc2809..d0f8a332 100644 --- a/tests/YGHadOverflowTest.cpp +++ b/tests/YGHadOverflowTest.cpp @@ -1,5 +1,9 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/** + * 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 #include diff --git a/tests/YGInfiniteHeightTest.cpp b/tests/YGInfiniteHeightTest.cpp index 3e189caf..6a0cf307 100644 --- a/tests/YGInfiniteHeightTest.cpp +++ b/tests/YGInfiniteHeightTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGJustifyContentTest.cpp b/tests/YGJustifyContentTest.cpp index 7ed1c72b..34deb973 100644 --- a/tests/YGJustifyContentTest.cpp +++ b/tests/YGJustifyContentTest.cpp @@ -1,8 +1,8 @@ /** * 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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ // @Generated by gentest/gentest.rb from // gentest/fixtures/YGJustifyContentTest.html diff --git a/tests/YGLayoutDiffingTest.cpp b/tests/YGLayoutDiffingTest.cpp index cb24a295..96361d16 100644 --- a/tests/YGLayoutDiffingTest.cpp +++ b/tests/YGLayoutDiffingTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGLoggerTest.cpp b/tests/YGLoggerTest.cpp index ccf0ad2b..3cf1095a 100644 --- a/tests/YGLoggerTest.cpp +++ b/tests/YGLoggerTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 #include diff --git a/tests/YGMarginTest.cpp b/tests/YGMarginTest.cpp index ba1b3cbc..6eb01a50 100644 --- a/tests/YGMarginTest.cpp +++ b/tests/YGMarginTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGMarginTest.html #include diff --git a/tests/YGMeasureCacheTest.cpp b/tests/YGMeasureCacheTest.cpp index bd56172f..dfb7d2e9 100644 --- a/tests/YGMeasureCacheTest.cpp +++ b/tests/YGMeasureCacheTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGMeasureModeTest.cpp b/tests/YGMeasureModeTest.cpp index f05ddd89..9dd0416e 100644 --- a/tests/YGMeasureModeTest.cpp +++ b/tests/YGMeasureModeTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGMeasureTest.cpp b/tests/YGMeasureTest.cpp index 93db13b1..a330523d 100644 --- a/tests/YGMeasureTest.cpp +++ b/tests/YGMeasureTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 #include diff --git a/tests/YGMinMaxDimensionTest.cpp b/tests/YGMinMaxDimensionTest.cpp index d38148be..dd16e5f9 100644 --- a/tests/YGMinMaxDimensionTest.cpp +++ b/tests/YGMinMaxDimensionTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGMinMaxDimensionTest.html #include diff --git a/tests/YGNodeChildTest.cpp b/tests/YGNodeChildTest.cpp index c159d9e4..b5aa6cfe 100644 --- a/tests/YGNodeChildTest.cpp +++ b/tests/YGNodeChildTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGPaddingTest.cpp b/tests/YGPaddingTest.cpp index 1a961c9c..c6f431b8 100644 --- a/tests/YGPaddingTest.cpp +++ b/tests/YGPaddingTest.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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. */ // @Generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html diff --git a/tests/YGPercentageTest.cpp b/tests/YGPercentageTest.cpp index 660af91f..93776413 100644 --- a/tests/YGPercentageTest.cpp +++ b/tests/YGPercentageTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html #include diff --git a/tests/YGPersistenceTest.cpp b/tests/YGPersistenceTest.cpp index 43101fc5..c9d94e89 100644 --- a/tests/YGPersistenceTest.cpp +++ b/tests/YGPersistenceTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGRelayoutTest.cpp b/tests/YGRelayoutTest.cpp index 990e948d..fdbe3608 100644 --- a/tests/YGRelayoutTest.cpp +++ b/tests/YGRelayoutTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGRoundingFunctionTest.cpp b/tests/YGRoundingFunctionTest.cpp index fa16b60e..672e8afd 100644 --- a/tests/YGRoundingFunctionTest.cpp +++ b/tests/YGRoundingFunctionTest.cpp @@ -1,9 +1,8 @@ -/* - * Copyright (c) Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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 #include diff --git a/tests/YGRoundingMeasureFuncTest.cpp b/tests/YGRoundingMeasureFuncTest.cpp index db9ea701..5cf2120f 100644 --- a/tests/YGRoundingMeasureFuncTest.cpp +++ b/tests/YGRoundingMeasureFuncTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGRoundingTest.cpp b/tests/YGRoundingTest.cpp index ee91c6cd..84f3da73 100644 --- a/tests/YGRoundingTest.cpp +++ b/tests/YGRoundingTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGRoundingTest.html #include diff --git a/tests/YGSizeOverflowTest.cpp b/tests/YGSizeOverflowTest.cpp index 06f5be17..73b35b72 100644 --- a/tests/YGSizeOverflowTest.cpp +++ b/tests/YGSizeOverflowTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGSizeOverflowTest.html #include diff --git a/tests/YGStyleTest.cpp b/tests/YGStyleTest.cpp index f36ed312..c5722708 100644 --- a/tests/YGStyleTest.cpp +++ b/tests/YGStyleTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include #include diff --git a/tests/YGTraversalTest.cpp b/tests/YGTraversalTest.cpp index 471919c8..c77ba3f4 100644 --- a/tests/YGTraversalTest.cpp +++ b/tests/YGTraversalTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGTreeMutationTest.cpp b/tests/YGTreeMutationTest.cpp index 70c9a970..a7a625cd 100644 --- a/tests/YGTreeMutationTest.cpp +++ b/tests/YGTreeMutationTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/tests/YGZeroOutLayoutRecursivlyTest.cpp b/tests/YGZeroOutLayoutRecursivlyTest.cpp index 735fa62d..052f60d5 100644 --- a/tests/YGZeroOutLayoutRecursivlyTest.cpp +++ b/tests/YGZeroOutLayoutRecursivlyTest.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include #include diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 5322642f..74cc38c9 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "Utils.h" diff --git a/yoga/Utils.h b/yoga/Utils.h index db257ae5..d578511c 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -1,10 +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. + * 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 "YGNode.h" #include "Yoga-internal.h" diff --git a/yoga/YGConfig.cpp b/yoga/YGConfig.cpp index e0edd3f7..2f73dd9a 100644 --- a/yoga/YGConfig.cpp +++ b/yoga/YGConfig.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGConfig.h" diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index b5f3c5fd..c9b871fe 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGMarker.h" diff --git a/yoga/YGEnums.cpp b/yoga/YGEnums.cpp index 5f8ef9af..e2518176 100644 --- a/yoga/YGEnums.cpp +++ b/yoga/YGEnums.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include "YGEnums.h" const char *YGAlignToString(const YGAlign value){ diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index db555281..da223051 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -1,10 +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. + * 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 "YGMacros.h" diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index c7ade6a2..d023dccb 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGFloatOptional.h" #include diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 2578b9dd..07fbb64b 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index 0f362f88..6f55d862 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGLayout.h" #include "Utils.h" diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 812ed6bd..2a0215d3 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGFloatOptional.h" diff --git a/yoga/YGMacros.h b/yoga/YGMacros.h index 0aafdca3..7da8a870 100644 --- a/yoga/YGMacros.h +++ b/yoga/YGMacros.h @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #pragma once #ifdef __cplusplus diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 00c582ab..3eb665fe 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -1,10 +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. + * 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 "YGMacros.h" diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 189a3df1..1694692c 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -1,9 +1,8 @@ -/* - * Copyright (c) Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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 "YGNode.h" #include diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 678926d3..719eb2ea 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index cd11bec6..541a6fef 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -1,10 +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. + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. */ - #include "YGNodePrint.h" #include #include "YGEnums.h" diff --git a/yoga/YGNodePrint.h b/yoga/YGNodePrint.h index a4f24cb5..9d36ba8d 100644 --- a/yoga/YGNodePrint.h +++ b/yoga/YGNodePrint.h @@ -1,8 +1,8 @@ /** * 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. + * 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 diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 46a65b28..bc90463e 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGStyle.h" diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 04a74545..c3a01d44 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 "YGFloatOptional.h" diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 0e02646c..1e9a1aaf 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 463107ee..6abfb7d3 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1,9 +1,8 @@ -/* - * Copyright (c) Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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 "Yoga.h" #include diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 04e0bf1d..96e71dc7 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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 From 0962c5220c866c6e3be157d79d3bc7844cc24ced Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:07 -0800 Subject: [PATCH 109/189] Roll back `-ffast-math` Summary: @public `-ffast-math` does not have measurable performance benefits. By using `NaN` for *undefined* values again, we can squeeze `YGFloatOptional` into 32 bits. This will also enable us to store `YGValue` (or a variant of it) in 32 bits. Reviewed By: SidharthGuglani Differential Revision: D13119110 fbshipit-source-id: 4e6964240bf74ebc22d8783107b89d536a1a0842 --- csharp/Facebook.Yoga/YogaConstants.cs | 23 +++-------------- java/com/facebook/yoga/YogaConstants.java | 30 +++++------------------ tools/build_defs/oss/yoga_defs.bzl | 1 - yoga/Utils.h | 14 +++-------- yoga/Yoga-internal.h | 10 +------- yoga/Yoga.cpp | 5 +--- yoga/Yoga.h | 15 ++++++------ 7 files changed, 21 insertions(+), 77 deletions(-) diff --git a/csharp/Facebook.Yoga/YogaConstants.cs b/csharp/Facebook.Yoga/YogaConstants.cs index a715b43c..9e05cca3 100644 --- a/csharp/Facebook.Yoga/YogaConstants.cs +++ b/csharp/Facebook.Yoga/YogaConstants.cs @@ -1,4 +1,4 @@ -/** +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -9,28 +9,11 @@ namespace Facebook.Yoga { public static class YogaConstants { - /** - * Large positive number signifies that the property(float) is undefined. Earlier we used to have - * YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as - * it assumes all floating-point calculation involve and result into finite numbers. For more - * information regarding -ffast-math compiler flag in clang, have a look at - * https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math - */ - public const float Undefined = 10E20F; + public const float Undefined = float.NaN; public static bool IsUndefined(float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN, - // the benefit of which - // was that if NAN is involved in any mathematical expression the result was NAN. But since we - // want to have `-ffast-math` - // flag being used by compiler which assumes that the floating point values are not NAN and Inf, - // we represent YGUndefined as 10.1E20. - // But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would - // change. - // So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it - // is undefined. - return value >= 10E8F || value <= -10E8; + return float.IsNaN(value); } public static bool IsUndefined(YogaValue value) diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index 61e212ef..b04a7e53 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -1,35 +1,17 @@ -/* - * 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. +/** + * 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 YogaConstants { - /** - * Large positive number signifies that the property(float) is undefined. Earlier we used to have - * YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as - * it assumes all floating-point calculation involve and result into finite numbers. For more - * information regarding -ffast-math compiler flag in clang, have a look at - * https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math - */ - public static final float UNDEFINED = (float) (10E20); + public static final float UNDEFINED = Float.NaN; public static boolean isUndefined(float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN, - // the benefit of which - // was that if NAN is involved in any mathematical expression the result was NAN. But since we - // want to have `-ffast-math` - // flag being used by compiler which assumes that the floating point values are not NAN and Inf, - // we represent YGUndefined as 10.1E20. - // But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would - // change. - // So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it - // is undefined. - return (Float.compare(value, (float) 10E8) >= 0 || Float.compare(value, (float) -10E8) <= 0); + return Float.compare(value, UNDEFINED) == 0; } public static boolean isUndefined(YogaValue value) { diff --git a/tools/build_defs/oss/yoga_defs.bzl b/tools/build_defs/oss/yoga_defs.bzl index 7eca7b9b..5a5872fe 100644 --- a/tools/build_defs/oss/yoga_defs.bzl +++ b/tools/build_defs/oss/yoga_defs.bzl @@ -58,7 +58,6 @@ BASE_COMPILER_FLAGS = [ "-Wall", "-Werror", "-O3", - "-ffast-math", ] LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [ diff --git a/yoga/Utils.h b/yoga/Utils.h index d578511c..d007ff54 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -57,22 +57,12 @@ bool YGValueEqual(const YGValue a, const YGValue b); // difference between two floats is less than 0.0001f or both are undefined. bool YGFloatsEqual(const float a, const float b); -// We need custom max function, since we want that, if one argument is -// YGUndefined then the max funtion should return the other argument as the max -// value. We wouldn't have needed a custom max function if YGUndefined was NAN -// as fmax has the same behaviour, but with NAN we cannot use `-ffast-math` -// compiler flag. float YGFloatMax(const float a, const float b); YGFloatOptional YGFloatOptionalMax( const YGFloatOptional& op1, const YGFloatOptional& op2); -// We need custom min function, since we want that, if one argument is -// YGUndefined then the min funtion should return the other argument as the min -// value. We wouldn't have needed a custom min function if YGUndefined was NAN -// as fmin has the same behaviour, but with NAN we cannot use `-ffast-math` -// compiler flag. float YGFloatMin(const float a, const float b); // This custom float comparision function compares the array of float with @@ -106,7 +96,9 @@ inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) { flexDirection == YGFlexDirectionRowReverse; } -inline YGFloatOptional YGResolveValue(const YGValue value, const float ownerSize) { +inline YGFloatOptional YGResolveValue( + const YGValue value, + const float ownerSize) { switch (value.unit) { case YGUnitUndefined: case YGUnitAuto: diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 1e9a1aaf..ef5e5d8c 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -27,15 +27,7 @@ namespace facebook { namespace yoga { inline bool isUndefined(float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier - // it used to be NAN, the benefit of which was that if NAN is involved in any - // mathematical expression the result was NAN. But since we want to have - // `-ffast-math` flag being used by compiler which assumes that the floating - // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But - // now if YGUndefined is involved in any mathematical operations this - // value(10.1E20) would change. So the following check makes sure that if the - // value is outside a range (-10E8, 10E8) then it is undefined. - return value >= 10E8 || value <= -10E8; + return std::isnan(value); } } // namespace yoga diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6abfb7d3..d5fc12ef 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -18,10 +18,7 @@ /* define fmaxf if < VC12 */ #if _MSC_VER < 1800 __forceinline const float fmaxf(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { - return (a > b) ? a : b; - } - return YGFloatIsUndefined(a) ? b : a; + return (a > b) ? a : b; } #endif #endif diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 96e71dc7..61aae0fe 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -17,14 +17,13 @@ #include #endif -/** Large positive number signifies that the property(float) is undefined. - *Earlier we used to have YGundefined as NAN, but the downside of this is that - *we can't use -ffast-math compiler flag as it assumes all floating-point - *calculation involve and result into finite numbers. For more information - *regarding -ffast-math compiler flag in clang, have a look at - *https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math - **/ -#define YGUndefined 10E20F +// Not defined in MSVC++ +#ifndef NAN +static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; +#define NAN (*(const float*)__nan) +#endif + +#define YGUndefined NAN #include "YGEnums.h" #include "YGMacros.h" From d19da9e528842871e4610066b325c8cd6af0a160 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:08 -0800 Subject: [PATCH 110/189] Move out `YGValue` Summary: @public Creates a single header file for `YGValue`. This is in preparation of a more compact representation of `YGValue` within `YGStyle`. Also fixes the incorrect definition of NAN. Reviewed By: SidharthGuglani Differential Revision: D13172444 fbshipit-source-id: 4250dbcf8fe15ec3ecdee3913360a73bab633ce3 --- yoga/YGValue.cpp | 29 +++++++++++++++++++++++++++++ yoga/YGValue.h | 40 ++++++++++++++++++++++++++++++++++++++++ yoga/Yoga.cpp | 17 ----------------- yoga/Yoga.h | 28 +--------------------------- 4 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 yoga/YGValue.cpp create mode 100644 yoga/YGValue.h diff --git a/yoga/YGValue.cpp b/yoga/YGValue.cpp new file mode 100644 index 00000000..4bfe083d --- /dev/null +++ b/yoga/YGValue.cpp @@ -0,0 +1,29 @@ +/** + * 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 "YGValue.h" + +const YGValue YGValueZero = {0, YGUnitPoint}; +const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; +const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; + +bool operator==(const YGValue& lhs, const YGValue& rhs) { + if (lhs.unit != rhs.unit) { + return false; + } + + switch (lhs.unit) { + case YGUnitUndefined: + case YGUnitAuto: + return true; + default: + return lhs.value == rhs.value; + } +} + +bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} diff --git a/yoga/YGValue.h b/yoga/YGValue.h new file mode 100644 index 00000000..803b8e78 --- /dev/null +++ b/yoga/YGValue.h @@ -0,0 +1,40 @@ +/** + * 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 +#include "YGEnums.h" +#include "YGMacros.h" + +YG_EXTERN_C_BEGIN + +// Not defined in MSVC++ +#ifndef NAN +static const uint32_t __nan = 0x7fc00000; +#define NAN (*(const float*)__nan) +#endif + +#define YGUndefined NAN + +typedef struct YGValue { + float value; + YGUnit unit; +} YGValue; + +extern const YGValue YGValueAuto; +extern const YGValue YGValueUndefined; +extern const YGValue YGValueZero; + +YG_EXTERN_C_END + +#ifdef __cplusplus + +bool operator==(const YGValue& lhs, const YGValue& rhs); + +bool operator!=(const YGValue& lhs, const YGValue& rhs); + +#endif diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index d5fc12ef..246e0f41 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -39,23 +39,6 @@ static int YGDefaultLog( va_list args); #endif -const YGValue YGValueZero = {0, YGUnitPoint}; -const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; -const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; - -bool operator==(const YGValue& lhs, const YGValue& rhs) { - if ((lhs.unit == YGUnitUndefined && rhs.unit == YGUnitUndefined) || - (lhs.unit == YGUnitAuto && rhs.unit == YGUnitAuto)) { - return true; - } - - return lhs.unit == rhs.unit && lhs.value == rhs.value; -} - -bool operator!=(const YGValue& lhs, const YGValue& rhs) { - return !(lhs == rhs); -} - #ifdef ANDROID #include static int YGAndroidLog( diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 61aae0fe..787af6df 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -17,16 +17,9 @@ #include #endif -// Not defined in MSVC++ -#ifndef NAN -static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; -#define NAN (*(const float*)__nan) -#endif - -#define YGUndefined NAN - #include "YGEnums.h" #include "YGMacros.h" +#include "YGValue.h" YG_EXTERN_C_BEGIN @@ -35,25 +28,6 @@ typedef struct YGSize { float height; } YGSize; -typedef struct YGValue { - float value; - YGUnit unit; -} YGValue; - -extern const YGValue YGValueUndefined; -extern const YGValue YGValueAuto; - -#ifdef __cplusplus - -YG_EXTERN_C_END - -extern bool operator==(const YGValue& lhs, const YGValue& rhs); -extern bool operator!=(const YGValue& lhs, const YGValue& rhs); - -YG_EXTERN_C_BEGIN - -#endif - typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; From ed5c5a799f8111f1e55507158d68641133184771 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:08 -0800 Subject: [PATCH 111/189] Make equality operator for `YGValue` inlineable Summary: @public Makes `operator==` for `YGValue` an inline function. Reviewed By: SidharthGuglani Differential Revision: D13189356 fbshipit-source-id: 7fe61035acf635e22ebb1a1071925d6b3dad0616 --- yoga/YGValue.cpp | 18 ------------------ yoga/YGValue.h | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/yoga/YGValue.cpp b/yoga/YGValue.cpp index 4bfe083d..fcdd0c69 100644 --- a/yoga/YGValue.cpp +++ b/yoga/YGValue.cpp @@ -9,21 +9,3 @@ const YGValue YGValueZero = {0, YGUnitPoint}; const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; - -bool operator==(const YGValue& lhs, const YGValue& rhs) { - if (lhs.unit != rhs.unit) { - return false; - } - - switch (lhs.unit) { - case YGUnitUndefined: - case YGUnitAuto: - return true; - default: - return lhs.value == rhs.value; - } -} - -bool operator!=(const YGValue& lhs, const YGValue& rhs) { - return !(lhs == rhs); -} diff --git a/yoga/YGValue.h b/yoga/YGValue.h index 803b8e78..4e43f7b2 100644 --- a/yoga/YGValue.h +++ b/yoga/YGValue.h @@ -33,8 +33,24 @@ YG_EXTERN_C_END #ifdef __cplusplus -bool operator==(const YGValue& lhs, const YGValue& rhs); +inline bool operator==(const YGValue& lhs, const YGValue& rhs) { + if (lhs.unit != rhs.unit) { + return false; + } -bool operator!=(const YGValue& lhs, const YGValue& rhs); + switch (lhs.unit) { + case YGUnitUndefined: + case YGUnitAuto: + return true; + case YGUnitPoint: + case YGUnitPercent: + default: + return lhs.value == rhs.value; + } +} + +inline bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} #endif From ed3b54b603cc3bf3483812823e06fa166eb1cf71 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:08 -0800 Subject: [PATCH 112/189] Store `YGFloatOptional` in 32 bits Summary: @public After removing `-ffast-math`, `NaN` can again be used to represent `undefined`. That allows us to remove the additional flag from `YGFloatOptional`, and reduce memory usage. Reviewed By: SidharthGuglani Differential Revision: D13209157 fbshipit-source-id: 21b83c837a78f924a4ec23a9236ca2440b3c8606 --- tests/YGFloatOptionalTest.cpp | 163 ++++++++++++++++++++++++++++++++++ yoga/YGFloatOptional.cpp | 53 +++-------- yoga/YGFloatOptional.h | 32 +++---- yoga/YGNode.cpp | 2 +- 4 files changed, 192 insertions(+), 58 deletions(-) create mode 100644 tests/YGFloatOptionalTest.cpp diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp new file mode 100644 index 00000000..2096e5fd --- /dev/null +++ b/tests/YGFloatOptionalTest.cpp @@ -0,0 +1,163 @@ +/** + * 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 +#include +#include + +constexpr auto empty = YGFloatOptional{}; +constexpr auto zero = YGFloatOptional{0.0f}; +constexpr auto one = YGFloatOptional{1.0f}; +constexpr auto positive = YGFloatOptional{1234.5f}; +constexpr auto negative = YGFloatOptional{-9876.5f}; + +TEST(YGFloatOptional, value) { + ASSERT_EQ(zero.getValue(), 0.0f); + ASSERT_EQ(positive.getValue(), 1234.5f); + ASSERT_EQ(negative.getValue(), -9876.5f); + + ASSERT_TRUE(empty.isUndefined()); + ASSERT_FALSE(zero.isUndefined()); + ASSERT_FALSE(negative.isUndefined()); +} + +TEST(YGFloatOptional, equality) { + ASSERT_TRUE(empty == empty); + ASSERT_TRUE(empty == YGUndefined); + ASSERT_FALSE(empty == zero); + ASSERT_FALSE(empty == negative); + ASSERT_FALSE(empty == 12.3f); + + ASSERT_TRUE(zero == zero); + ASSERT_TRUE(zero == 0.0f); + ASSERT_FALSE(zero == positive); + ASSERT_FALSE(zero == -5555.5f); + + ASSERT_TRUE(one == one); + ASSERT_TRUE(one == 1.0f); + ASSERT_FALSE(one == positive); + + ASSERT_TRUE(negative == negative); + ASSERT_TRUE(negative == negative.getValue()); + ASSERT_FALSE(negative == zero); +} + +TEST(YGFloatOptional, inequality) { + ASSERT_FALSE(empty != empty); + ASSERT_FALSE(empty != YGUndefined); + ASSERT_TRUE(empty != zero); + ASSERT_TRUE(empty != negative); + ASSERT_TRUE(empty != 12.3f); + + ASSERT_FALSE(zero != zero); + ASSERT_FALSE(zero != 0.0f); + ASSERT_TRUE(zero != positive); + ASSERT_TRUE(zero != -5555.5f); + + ASSERT_FALSE(one != one); + ASSERT_FALSE(one != 1.0f); + ASSERT_TRUE(one != positive); + + ASSERT_FALSE(negative != negative); + ASSERT_FALSE(negative != negative.getValue()); + ASSERT_TRUE(negative != zero); +} + +TEST(YGFloatOptional, greater) { + ASSERT_FALSE(empty > empty); + ASSERT_FALSE(empty > zero); + ASSERT_FALSE(empty > one); + ASSERT_FALSE(empty > positive); + ASSERT_FALSE(empty > negative); + + ASSERT_TRUE(zero > negative); + ASSERT_FALSE(zero > zero); + ASSERT_FALSE(zero > positive); + ASSERT_FALSE(zero > one); + + ASSERT_TRUE(one > negative); + ASSERT_TRUE(one > zero); + ASSERT_FALSE(one > empty); + ASSERT_FALSE(one > positive); + + ASSERT_TRUE(negative > YGFloatOptional{-INFINITY}); + ASSERT_FALSE(negative > empty); +} + +TEST(YGFloatOptional, lower) { + ASSERT_FALSE(empty < empty); + ASSERT_FALSE(empty < zero); + ASSERT_FALSE(empty < one); + ASSERT_FALSE(empty < positive); + ASSERT_FALSE(empty < negative); + + ASSERT_TRUE(negative < zero); + ASSERT_FALSE(zero < zero); + ASSERT_FALSE(positive < zero); + ASSERT_FALSE(one < zero); + + ASSERT_TRUE(negative < one); + ASSERT_TRUE(zero < one); + ASSERT_FALSE(empty < one); + ASSERT_FALSE(positive < one); + + ASSERT_TRUE(YGFloatOptional{-INFINITY} < negative); + ASSERT_FALSE(empty < negative); +} + +TEST(YGFloatOptional, greater_equals) { + ASSERT_TRUE(empty >= empty); + ASSERT_FALSE(empty >= zero); + ASSERT_FALSE(empty >= one); + ASSERT_FALSE(empty >= positive); + ASSERT_FALSE(empty >= negative); + + ASSERT_TRUE(zero >= negative); + ASSERT_TRUE(zero >= zero); + ASSERT_FALSE(zero >= positive); + ASSERT_FALSE(zero >= one); + + ASSERT_TRUE(one >= negative); + ASSERT_TRUE(one >= zero); + ASSERT_FALSE(one >= empty); + ASSERT_FALSE(one >= positive); + + ASSERT_TRUE(negative >= YGFloatOptional{-INFINITY}); + ASSERT_TRUE(negative >= negative); + ASSERT_FALSE(negative >= empty); +} + +TEST(YGFloatOptional, lower_equals) { + ASSERT_TRUE(empty <= empty); + ASSERT_FALSE(zero <= empty); + ASSERT_FALSE(one <= empty); + ASSERT_FALSE(positive <= empty); + ASSERT_FALSE(negative <= empty); + + ASSERT_TRUE(negative <= zero); + ASSERT_TRUE(zero <= zero); + ASSERT_FALSE(positive <= zero); + ASSERT_FALSE(one <= zero); + + ASSERT_TRUE(negative <= one); + ASSERT_TRUE(zero <= one); + ASSERT_FALSE(empty <= one); + ASSERT_FALSE(positive <= one); + + ASSERT_TRUE(YGFloatOptional{-INFINITY} <= negative); + ASSERT_TRUE(negative <= negative); + ASSERT_FALSE(empty <= negative); +} + +TEST(YGFloatOptional, addition) { + ASSERT_EQ(zero + one, one); + ASSERT_EQ( + negative + positive, + YGFloatOptional{negative.getValue() + positive.getValue()}); + ASSERT_EQ(empty + zero, empty); + ASSERT_EQ(empty + empty, empty); + ASSERT_EQ(negative + empty, empty); +} diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index d023dccb..0bf89f29 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -7,23 +7,13 @@ #include "YGFloatOptional.h" #include #include -#include "Yoga.h" #include "Yoga-internal.h" +#include "Yoga.h" using namespace facebook; -YGFloatOptional::YGFloatOptional(float value) { - if (yoga::isUndefined(value)) { - isUndefined_ = true; - value_ = 0; - } else { - value_ = value; - isUndefined_ = false; - } -} - float YGFloatOptional::getValue() const { - if (isUndefined_) { + if (isUndefined()) { // Abort, accessing a value of an undefined float optional std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; std::exit(EXIT_FAILURE); @@ -31,53 +21,38 @@ float YGFloatOptional::getValue() const { return value_; } -bool YGFloatOptional::operator==(const YGFloatOptional& op) const { - if (isUndefined_ == op.isUndefined()) { - return isUndefined_ || value_ == op.getValue(); - } - return false; +bool YGFloatOptional::operator==(YGFloatOptional op) const { + return value_ == op.value_ || (isUndefined() && op.isUndefined()); } -bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { +bool YGFloatOptional::operator!=(YGFloatOptional op) const { return !(*this == op); } bool YGFloatOptional::operator==(float val) const { - if (yoga::isUndefined(val) == isUndefined_) { - return isUndefined_ || val == value_; - } - return false; + return value_ == val || (isUndefined() && yoga::isUndefined(val)); } bool YGFloatOptional::operator!=(float val) const { return !(*this == val); } -YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) { - if (!isUndefined_ && !op.isUndefined_) { - return YGFloatOptional(value_ + op.value_); - } - return YGFloatOptional(); +YGFloatOptional YGFloatOptional::operator+(YGFloatOptional op) const { + return YGFloatOptional{value_ + op.value_}; } -bool YGFloatOptional::operator>(const YGFloatOptional& op) const { - if (isUndefined_ || op.isUndefined_) { - return false; - } +bool YGFloatOptional::operator>(YGFloatOptional op) const { return value_ > op.value_; } -bool YGFloatOptional::operator<(const YGFloatOptional& op) const { - if (isUndefined_ || op.isUndefined_) { - return false; - } +bool YGFloatOptional::operator<(YGFloatOptional op) const { return value_ < op.value_; } -bool YGFloatOptional::operator>=(const YGFloatOptional& op) const { - return *this == op || *this > op; +bool YGFloatOptional::operator>=(YGFloatOptional op) const { + return *this > op || *this == op; } -bool YGFloatOptional::operator<=(const YGFloatOptional& op) const { - return *this == op || *this < op; +bool YGFloatOptional::operator<=(YGFloatOptional op) const { + return *this < op || *this == op; } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 07fbb64b..7b573d38 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -6,37 +6,33 @@ */ #pragma once +#include +#include + struct YGFloatOptional { private: - float value_ = 0; - bool isUndefined_ = true; + float value_ = std::numeric_limits::quiet_NaN(); public: - explicit YGFloatOptional(float value); - YGFloatOptional() = default; + explicit constexpr YGFloatOptional(float value) : value_(value) {} + constexpr YGFloatOptional() = default; // Program will terminate if the value of an undefined is accessed. Please // make sure to check if the optional is defined before calling this function. // To check if float optional is defined, use `isUndefined()`. float getValue() const; - // Sets the value of float optional, and thus isUndefined is assigned false. - void setValue(float val) { - value_ = val; - isUndefined_ = false; - } - bool isUndefined() const { - return isUndefined_; + return std::isnan(value_); } - YGFloatOptional operator+(const YGFloatOptional& op); - bool operator>(const YGFloatOptional& op) const; - bool operator<(const YGFloatOptional& op) const; - bool operator>=(const YGFloatOptional& op) const; - bool operator<=(const YGFloatOptional& op) const; - bool operator==(const YGFloatOptional& op) const; - bool operator!=(const YGFloatOptional& op) const; + YGFloatOptional operator+(YGFloatOptional op) const; + bool operator>(YGFloatOptional op) const; + bool operator<(YGFloatOptional op) const; + bool operator>=(YGFloatOptional op) const; + bool operator<=(YGFloatOptional op) const; + bool operator==(YGFloatOptional op) const; + bool operator!=(YGFloatOptional op) const; bool operator==(float val) const; bool operator!=(float val) const; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 1694692c..04c3c7f6 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -211,7 +211,7 @@ YGFloatOptional YGNode::relativePosition( YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize); if (!trailingPosition.isUndefined()) { - trailingPosition.setValue(-1 * trailingPosition.getValue()); + trailingPosition = YGFloatOptional{-1 * trailingPosition.getValue()}; } return trailingPosition; } From 50ec35575f8f14f288fa152b86520aab652f714d Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 113/189] Eliminate `YGFloatOptional::getValue()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public `YGFloatOptional::getValue()` has the unfortunate property of calling `std::exit` if the wrapped value is undefined. That forces `x.isUndefined() ? fallback : x.getValue()` as access pattern. Here, we replace that by introducing `YGFloatOptional::orElse(float)` which encapsulates that pattern. Other additions are `orElseGet([] { … })` and some extra operators. Reviewed By: SidharthGuglani Differential Revision: D13209152 fbshipit-source-id: 4e5deceaaaaf8eaed44846a8c152cc8b235e815c --- tests/YGFloatOptionalTest.cpp | 56 +++++++++++++++++++++---- yoga/Utils.cpp | 9 ++-- yoga/YGFloatOptional.cpp | 17 ++++---- yoga/YGFloatOptional.h | 27 ++++++++---- yoga/YGNode.cpp | 47 ++++++++------------- yoga/YGNodePrint.cpp | 3 +- yoga/YGStyle.cpp | 37 +++------------- yoga/Yoga.cpp | 79 ++++++++++++++++------------------- 8 files changed, 141 insertions(+), 134 deletions(-) diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp index 2096e5fd..cb4a35a7 100644 --- a/tests/YGFloatOptionalTest.cpp +++ b/tests/YGFloatOptionalTest.cpp @@ -6,7 +6,8 @@ */ #include #include -#include +#include +#include constexpr auto empty = YGFloatOptional{}; constexpr auto zero = YGFloatOptional{0.0f}; @@ -15,9 +16,10 @@ constexpr auto positive = YGFloatOptional{1234.5f}; constexpr auto negative = YGFloatOptional{-9876.5f}; TEST(YGFloatOptional, value) { - ASSERT_EQ(zero.getValue(), 0.0f); - ASSERT_EQ(positive.getValue(), 1234.5f); - ASSERT_EQ(negative.getValue(), -9876.5f); + ASSERT_EQ(zero.unwrap(), 0.0f); + ASSERT_EQ(positive.unwrap(), 1234.5f); + ASSERT_EQ(negative.unwrap(), -9876.5f); + ASSERT_TRUE(YGFloatIsUndefined(empty.unwrap())); ASSERT_TRUE(empty.isUndefined()); ASSERT_FALSE(zero.isUndefined()); @@ -41,7 +43,7 @@ TEST(YGFloatOptional, equality) { ASSERT_FALSE(one == positive); ASSERT_TRUE(negative == negative); - ASSERT_TRUE(negative == negative.getValue()); + ASSERT_TRUE(negative == negative.unwrap()); ASSERT_FALSE(negative == zero); } @@ -62,7 +64,7 @@ TEST(YGFloatOptional, inequality) { ASSERT_TRUE(one != positive); ASSERT_FALSE(negative != negative); - ASSERT_FALSE(negative != negative.getValue()); + ASSERT_FALSE(negative != negative.unwrap()); ASSERT_TRUE(negative != zero); } @@ -72,6 +74,10 @@ TEST(YGFloatOptional, greater) { ASSERT_FALSE(empty > one); ASSERT_FALSE(empty > positive); ASSERT_FALSE(empty > negative); + ASSERT_FALSE(zero > empty); + ASSERT_FALSE(one > empty); + ASSERT_FALSE(positive > empty); + ASSERT_FALSE(negative > empty); ASSERT_TRUE(zero > negative); ASSERT_FALSE(zero > zero); @@ -93,6 +99,10 @@ TEST(YGFloatOptional, lower) { ASSERT_FALSE(empty < one); ASSERT_FALSE(empty < positive); ASSERT_FALSE(empty < negative); + ASSERT_FALSE(zero < empty); + ASSERT_FALSE(one < empty); + ASSERT_FALSE(positive < empty); + ASSERT_FALSE(negative < empty); ASSERT_TRUE(negative < zero); ASSERT_FALSE(zero < zero); @@ -156,8 +166,40 @@ TEST(YGFloatOptional, addition) { ASSERT_EQ(zero + one, one); ASSERT_EQ( negative + positive, - YGFloatOptional{negative.getValue() + positive.getValue()}); + YGFloatOptional{negative.unwrap() + positive.unwrap()}); ASSERT_EQ(empty + zero, empty); ASSERT_EQ(empty + empty, empty); ASSERT_EQ(negative + empty, empty); } + +TEST(YGFloatOptional, subtraction) { + ASSERT_EQ(zero - one, YGFloatOptional{-1.0f}); + ASSERT_EQ( + negative - positive, + YGFloatOptional{negative.unwrap() - positive.unwrap()}); + ASSERT_EQ(empty - zero, empty); + ASSERT_EQ(empty - empty, empty); + ASSERT_EQ(negative - empty, empty); +} + +TEST(YGFloatOptional, unary_minus) { + ASSERT_EQ(-zero, zero); + ASSERT_EQ(-negative, YGFloatOptional{-negative.unwrap()}); + ASSERT_EQ(-positive, YGFloatOptional{-positive.unwrap()}); + ASSERT_EQ(-empty, empty); +} + +TEST(YGFloatOptional, orElse) { + ASSERT_EQ(empty.orElse(1.23f), 1.23f); + ASSERT_TRUE(YGFloatIsUndefined(empty.orElse(YGUndefined))); + ASSERT_EQ(one.orElse(1.23f), 1.0f); +} + +TEST(YGFloatOptional, orElseGet) { + auto x = empty.orElseGet([] { return 1.23f; }); + ASSERT_EQ(x, 1.23f); + ASSERT_TRUE(YGFloatIsUndefined(empty.orElseGet([] { return YGUndefined; }))); + + auto y = one.orElseGet([] { return 1.23f; }); + ASSERT_EQ(y, 1.0f); +} diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 74cc38c9..1d8eb71e 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -56,14 +56,17 @@ float YGFloatSanitize(const float val) { } float YGUnwrapFloatOptional(const YGFloatOptional& op) { - return op.isUndefined() ? YGUndefined : op.getValue(); + return op.unwrap(); } YGFloatOptional YGFloatOptionalMax( const YGFloatOptional& op1, const YGFloatOptional& op2) { - if (!op1.isUndefined() && !op2.isUndefined()) { - return op1.getValue() > op2.getValue() ? op1 : op2; + if (op1 > op2) { + return op1; + } + if (op2 > op1) { + return op2; } return op1.isUndefined() ? op2 : op1; } diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index 0bf89f29..263f24cb 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -12,15 +12,6 @@ using namespace facebook; -float YGFloatOptional::getValue() const { - if (isUndefined()) { - // Abort, accessing a value of an undefined float optional - std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; - std::exit(EXIT_FAILURE); - } - return value_; -} - bool YGFloatOptional::operator==(YGFloatOptional op) const { return value_ == op.value_ || (isUndefined() && op.isUndefined()); } @@ -37,10 +28,18 @@ bool YGFloatOptional::operator!=(float val) const { return !(*this == val); } +YGFloatOptional YGFloatOptional::operator-() const { + return YGFloatOptional{-value_}; +} + YGFloatOptional YGFloatOptional::operator+(YGFloatOptional op) const { return YGFloatOptional{value_ + op.value_}; } +YGFloatOptional YGFloatOptional::operator-(YGFloatOptional op) const { + return YGFloatOptional{value_ - op.value_}; +} + bool YGFloatOptional::operator>(YGFloatOptional op) const { return value_ > op.value_; } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 7b573d38..f6e654fb 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -6,7 +6,6 @@ */ #pragma once -#include #include struct YGFloatOptional { @@ -17,16 +16,28 @@ struct YGFloatOptional { explicit constexpr YGFloatOptional(float value) : value_(value) {} constexpr YGFloatOptional() = default; - // Program will terminate if the value of an undefined is accessed. Please - // make sure to check if the optional is defined before calling this function. - // To check if float optional is defined, use `isUndefined()`. - float getValue() const; - - bool isUndefined() const { - return std::isnan(value_); + // returns the wrapped value, or a value x with YGIsUndefined(x) == true + float unwrap() const { + return value_; } + constexpr bool isUndefined() const { + // std::isnan is not constexpr + return !(value_ == value_); + } + + constexpr float orElse(float other) const { + return isUndefined() ? other : value_; + } + + template + constexpr float orElseGet(Factory&& f) const { + return isUndefined() ? f() : value_; + } + + YGFloatOptional operator-() const; YGFloatOptional operator+(YGFloatOptional op) const; + YGFloatOptional operator-(YGFloatOptional op) const; bool operator>(YGFloatOptional op) const; bool operator<(YGFloatOptional op) const; bool operator>=(YGFloatOptional op) const; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 04c3c7f6..558a8937 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -209,11 +209,7 @@ YGFloatOptional YGNode::relativePosition( return getLeadingPosition(axis, axisSize); } - YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize); - if (!trailingPosition.isUndefined()) { - trailingPosition = YGFloatOptional{-1 * trailingPosition.getValue()}; - } - return trailingPosition; + return -getTrailingPosition(axis, axisSize); } void YGNode::setPosition( @@ -304,7 +300,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) { return flexBasis; } - if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) { + if (style_.flex > YGFloatOptional{0.0f}) { return config_->useWebDefaults ? YGValueAuto : YGValueZero; } return YGValueAuto; @@ -394,27 +390,23 @@ float YGNode::resolveFlexGrow() { if (owner_ == nullptr) { return 0.0; } - if (!style_.flexGrow.isUndefined()) { - return style_.flexGrow.getValue(); - } - if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) { - return style_.flex.getValue(); - } - return kDefaultFlexGrow; + + return style_.flexGrow.orElseGet( + [this] { return style_.flex.orElse(kDefaultFlexGrow); }); } float YGNode::resolveFlexShrink() { if (owner_ == nullptr) { return 0.0; } - if (!style_.flexShrink.isUndefined()) { - return style_.flexShrink.getValue(); - } - if (!config_->useWebDefaults && !style_.flex.isUndefined() && - style_.flex.getValue() < 0.0f) { - return -style_.flex.getValue(); - } - return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink; + return style_.flexShrink.orElseGet([this] { + if (style_.flex < YGFloatOptional{0.0f} && !config_->useWebDefaults) { + return -style_.flex.unwrap(); + } else { + return config_->useWebDefaults ? kWebDefaultFlexShrink + : kDefaultFlexShrink; + } + }); } bool YGNode::isNodeFlexible() { @@ -455,9 +447,7 @@ YGFloatOptional YGNode::getLeadingPadding( const float widthSize) const { const YGFloatOptional& paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); - if (YGFlexDirectionIsRow(axis) && - style_.padding[YGEdgeStart].unit != YGUnitUndefined && - !paddingEdgeStart.isUndefined() && paddingEdgeStart.getValue() >= 0.0f) { + if (YGFlexDirectionIsRow(axis) && paddingEdgeStart >= YGFloatOptional{0.0f}) { return paddingEdgeStart; } @@ -470,11 +460,10 @@ YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getTrailingPadding( const YGFlexDirection axis, const float widthSize) const { - if (YGFlexDirectionIsRow(axis) && - style_.padding[YGEdgeEnd].unit != YGUnitUndefined && - !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() && - YGResolveValue(style_.padding[YGEdgeEnd], widthSize).getValue() >= 0.0f) { - return YGResolveValue(style_.padding[YGEdgeEnd], widthSize); + const YGFloatOptional& paddingEdgeEnd = + YGResolveValue(style_.padding[YGEdgeEnd], widthSize); + if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) { + return paddingEdgeEnd; } YGFloatOptional resolvedValue = YGResolveValue( diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 541a6fef..c497996e 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -43,7 +43,7 @@ static void appendFloatOptionalIfDefined( const string key, const YGFloatOptional num) { if (!num.isUndefined()) { - appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue()); + appendFormatedString(base, "%s: %g; ", key.c_str(), num.unwrap()); } } @@ -71,7 +71,6 @@ appendNumberIfNotAuto(string* base, const string& key, const YGValue number) { static void appendNumberIfNotZero(string* base, const string& str, const YGValue number) { - if (number.unit == YGUnitAuto) { base->append(str + ": auto; "); } else if (!YGFloatsEqual(number.value, 0)) { diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index bc90463e..a2f4a17e 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -8,8 +8,8 @@ // Yoga specific properties, not compatible with flexbox specification bool YGStyle::operator==(const YGStyle& style) { - bool areNonFloatValuesEqual = direction == style.direction && - flexDirection == style.flexDirection && + return ( + direction == style.direction && flexDirection == style.flexDirection && justifyContent == style.justifyContent && alignContent == style.alignContent && alignItems == style.alignItems && alignSelf == style.alignSelf && positionType == style.positionType && @@ -21,34 +21,7 @@ bool YGStyle::operator==(const YGStyle& style) { YGValueArrayEqual(border, style.border) && YGValueArrayEqual(dimensions, style.dimensions) && YGValueArrayEqual(minDimensions, style.minDimensions) && - YGValueArrayEqual(maxDimensions, style.maxDimensions); - - areNonFloatValuesEqual = - areNonFloatValuesEqual && flex.isUndefined() == style.flex.isUndefined(); - if (areNonFloatValuesEqual && !flex.isUndefined() && - !style.flex.isUndefined()) { - areNonFloatValuesEqual = - areNonFloatValuesEqual && flex.getValue() == style.flex.getValue(); - } - - areNonFloatValuesEqual = areNonFloatValuesEqual && - flexGrow.isUndefined() == style.flexGrow.isUndefined(); - if (areNonFloatValuesEqual && !flexGrow.isUndefined()) { - areNonFloatValuesEqual = areNonFloatValuesEqual && - flexGrow.getValue() == style.flexGrow.getValue(); - } - - areNonFloatValuesEqual = areNonFloatValuesEqual && - flexShrink.isUndefined() == style.flexShrink.isUndefined(); - if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) { - areNonFloatValuesEqual = areNonFloatValuesEqual && - flexShrink.getValue() == style.flexShrink.getValue(); - } - - if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) { - areNonFloatValuesEqual = areNonFloatValuesEqual && - aspectRatio.getValue() == style.aspectRatio.getValue(); - } - - return areNonFloatValuesEqual; + YGValueArrayEqual(maxDimensions, style.maxDimensions) && + flex == style.flex && flexGrow == style.flexGrow && + flexShrink == style.flexShrink && aspectRatio == style.aspectRatio); } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 246e0f41..5197d994 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -579,16 +579,14 @@ void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) { } float YGNodeStyleGetFlexGrow(const YGNodeRef node) { - return node->getStyle().flexGrow.isUndefined() - ? kDefaultFlexGrow - : node->getStyle().flexGrow.getValue(); + return node->getStyle().flexGrow.orElse(kDefaultFlexGrow); } float YGNodeStyleGetFlexShrink(const YGNodeRef node) { - return node->getStyle().flexShrink.isUndefined() - ? (node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink - : kDefaultFlexShrink) - : node->getStyle().flexShrink.getValue(); + return node->getStyle().flexShrink.orElseGet([node] { + return node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink + : kDefaultFlexShrink; + }); } namespace { @@ -856,8 +854,7 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { // TODO(T26792433): Change the API to accept YGFloatOptional. float YGNodeStyleGetFlex(const YGNodeRef node) { - return node->getStyle().flex.isUndefined() ? YGUndefined - : node->getStyle().flex.getValue(); + return node->getStyle().flex.orElse(YGUndefined); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -959,7 +956,7 @@ float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) { // TODO(T26792433): Change the API to accept YGFloatOptional. float YGNodeStyleGetAspectRatio(const YGNodeRef node) { const YGFloatOptional op = node->getStyle().aspectRatio; - return op.isUndefined() ? YGUndefined : op.getValue(); + return op.orElse(YGUndefined); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -1229,15 +1226,15 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( node->getStyle().maxDimensions[YGDimensionWidth], axisSize); } - if (!max.isUndefined() && max.getValue() >= 0 && value > max.getValue()) { + if (max >= YGFloatOptional{0} && YGFloatOptional{value} > max) { return max; } - if (!min.isUndefined() && min.getValue() >= 0 && value < min.getValue()) { + if (min >= YGFloatOptional{0} && YGFloatOptional{value} < min) { return min; } - return YGFloatOptional(value); + return YGFloatOptional{value}; } // Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't @@ -1278,14 +1275,14 @@ static void YGConstrainMaxSizeForMode( switch (*mode) { case YGMeasureModeExactly: case YGMeasureModeAtMost: - *size = (maxSize.isUndefined() || *size < maxSize.getValue()) - ? *size - : maxSize.getValue(); + if (YGFloatOptional{*size} > maxSize) { + *size = maxSize.unwrap(); + } break; case YGMeasureModeUndefined: if (!maxSize.isUndefined()) { *mode = YGMeasureModeAtMost; - *size = maxSize.getValue(); + *size = maxSize.unwrap(); } break; } @@ -1395,16 +1392,15 @@ static void YGNodeComputeFlexBasisForChild( } } - if (!child->getStyle().aspectRatio.isUndefined()) { + auto hasAspectRatio = !child->getStyle().aspectRatio.isUndefined(); + auto aspectRatio = child->getStyle().aspectRatio.unwrap(); + if (hasAspectRatio) { if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) { - childHeight = marginColumn + - (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); + childHeight = marginColumn + (childWidth - marginRow) / aspectRatio; childHeightMeasureMode = YGMeasureModeExactly; } else if ( isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { - childWidth = marginRow + - (childHeight - marginColumn) * - child->getStyle().aspectRatio.getValue(); + childWidth = marginRow + (childHeight - marginColumn) * aspectRatio; childWidthMeasureMode = YGMeasureModeExactly; } } @@ -1422,9 +1418,8 @@ static void YGNodeComputeFlexBasisForChild( childWidthStretch) { childWidth = width; childWidthMeasureMode = YGMeasureModeExactly; - if (!child->getStyle().aspectRatio.isUndefined()) { - childHeight = - (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); + if (hasAspectRatio) { + childHeight = (childWidth - marginRow) / aspectRatio; childHeightMeasureMode = YGMeasureModeExactly; } } @@ -1439,9 +1434,8 @@ static void YGNodeComputeFlexBasisForChild( childHeight = height; childHeightMeasureMode = YGMeasureModeExactly; - if (!child->getStyle().aspectRatio.isUndefined()) { - childWidth = (childHeight - marginColumn) * - child->getStyle().aspectRatio.getValue(); + if (hasAspectRatio) { + childWidth = (childHeight - marginColumn) * aspectRatio; childWidthMeasureMode = YGMeasureModeExactly; } } @@ -1553,13 +1547,11 @@ static void YGNodeAbsoluteLayoutChild( // flexible. if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) { if (!child->getStyle().aspectRatio.isUndefined()) { + auto aspectRatio = child->getStyle().aspectRatio.unwrap(); if (YGFloatIsUndefined(childWidth)) { - childWidth = marginRow + - (childHeight - marginColumn) * - child->getStyle().aspectRatio.getValue(); + childWidth = marginRow + (childHeight - marginColumn) * aspectRatio; } else if (YGFloatIsUndefined(childHeight)) { - childHeight = marginColumn + - (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); + childHeight = marginColumn + (childWidth - marginRow) / aspectRatio; } } } @@ -1885,16 +1877,15 @@ static float YGNodeCalculateAvailableInnerDim( // constraints const YGFloatOptional minDimensionOptional = YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); - const float minInnerDim = minDimensionOptional.isUndefined() - ? 0.0f - : minDimensionOptional.getValue() - paddingAndBorder; + const float minInnerDim = + (minDimensionOptional - YGFloatOptional{paddingAndBorder}).orElse(0.0f); const YGFloatOptional maxDimensionOptional = YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim); - const float maxInnerDim = maxDimensionOptional.isUndefined() - ? FLT_MAX - : maxDimensionOptional.getValue() - paddingAndBorder; + const float maxInnerDim = + (maxDimensionOptional - YGFloatOptional{paddingAndBorder}) + .orElse(FLT_MAX); availableInnerDim = YGFloatMax(YGFloatMin(availableInnerDim, maxInnerDim), minInnerDim); } @@ -2162,9 +2153,9 @@ static float YGDistributeFreeSpaceSecondPass( if (!currentRelativeChild->getStyle().aspectRatio.isUndefined()) { childCrossSize = isMainAxisRow ? (childMainSize - marginMain) / - currentRelativeChild->getStyle().aspectRatio.getValue() + currentRelativeChild->getStyle().aspectRatio.unwrap() : (childMainSize - marginMain) * - currentRelativeChild->getStyle().aspectRatio.getValue(); + currentRelativeChild->getStyle().aspectRatio.unwrap(); childCrossMeasureMode = YGMeasureModeExactly; childCrossSize += marginCross; @@ -3131,9 +3122,9 @@ static void YGNodelayoutImpl( ? ((YGUnwrapFloatOptional(child->getMarginForAxis( crossAxis, availableInnerWidth)) + (isMainAxisRow ? childMainSize / - child->getStyle().aspectRatio.getValue() + child->getStyle().aspectRatio.unwrap() : childMainSize * - child->getStyle().aspectRatio.getValue()))) + child->getStyle().aspectRatio.unwrap()))) : collectedFlexItemsValues.crossDim; childMainSize += YGUnwrapFloatOptional( From 64c37767c25e86e66e9ef513dc800e54e4d1ac3b Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 114/189] Pass `YGFloatOptional` by value, not reference Summary: @public `YGFloatOptional` is a 32bit type now, and can be passed by value efficiently. Reviewed By: SidharthGuglani Differential Revision: D13209150 fbshipit-source-id: c7b937a640258256c97e082ba2f832754e191b9a --- yoga/Utils.cpp | 6 +++--- yoga/Utils.h | 6 +++--- yoga/YGNode.cpp | 6 +++--- yoga/YGNode.h | 2 +- yoga/Yoga.cpp | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 1d8eb71e..88ebd841 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -55,13 +55,13 @@ float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } -float YGUnwrapFloatOptional(const YGFloatOptional& op) { +float YGUnwrapFloatOptional(const YGFloatOptional op) { return op.unwrap(); } YGFloatOptional YGFloatOptionalMax( - const YGFloatOptional& op1, - const YGFloatOptional& op2) { + const YGFloatOptional op1, + const YGFloatOptional op2) { if (op1 > op2) { return op1; } diff --git a/yoga/Utils.h b/yoga/Utils.h index d007ff54..204b2718 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -60,8 +60,8 @@ bool YGFloatsEqual(const float a, const float b); float YGFloatMax(const float a, const float b); YGFloatOptional YGFloatOptionalMax( - const YGFloatOptional& op1, - const YGFloatOptional& op2); + const YGFloatOptional op1, + const YGFloatOptional op2); float YGFloatMin(const float a, const float b); @@ -85,7 +85,7 @@ float YGFloatSanitize(const float val); // This function unwraps optional and returns YGUndefined if not defined or // op.value otherwise // TODO: Get rid off this function -float YGUnwrapFloatOptional(const YGFloatOptional& op); +float YGUnwrapFloatOptional(const YGFloatOptional op); YGFlexDirection YGFlexDirectionCross( const YGFlexDirection flexDirection, diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 558a8937..83c1eabd 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -175,7 +175,7 @@ void YGNode::setLayoutLastOwnerDirection(YGDirection direction) { } void YGNode::setLayoutComputedFlexBasis( - const YGFloatOptional& computedFlexBasis) { + const YGFloatOptional computedFlexBasis) { layout_.computedFlexBasis = computedFlexBasis; } @@ -445,7 +445,7 @@ float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { YGFloatOptional YGNode::getLeadingPadding( const YGFlexDirection axis, const float widthSize) const { - const YGFloatOptional& paddingEdgeStart = + const YGFloatOptional paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && paddingEdgeStart >= YGFloatOptional{0.0f}) { return paddingEdgeStart; @@ -460,7 +460,7 @@ YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getTrailingPadding( const YGFlexDirection axis, const float widthSize) const { - const YGFloatOptional& paddingEdgeEnd = + const YGFloatOptional paddingEdgeEnd = YGResolveValue(style_.padding[YGEdgeEnd], widthSize); if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) { return paddingEdgeEnd; diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 719eb2ea..57312812 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -235,7 +235,7 @@ struct YGNode { void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); - void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis); + void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis); void setLayoutComputedFlexBasisGeneration( uint32_t computedFlexBasisGeneration); void setLayoutMeasuredDimension(float measuredDimension, int index); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 5197d994..e708f61c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1323,14 +1323,14 @@ static void YGNodeComputeFlexBasisForChild( child->getConfig(), YGExperimentalFeatureWebFlexBasis) && child->getLayout().computedFlexBasisGeneration != gCurrentGenerationCount)) { - const YGFloatOptional& paddingAndBorder = YGFloatOptional( + const YGFloatOptional paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)); child->setLayoutComputedFlexBasis( YGFloatOptionalMax(resolvedFlexBasis, paddingAndBorder)); } } else if (isMainAxisRow && isRowStyleDimDefined) { // The width is definite, so use that as the flex basis. - const YGFloatOptional& paddingAndBorder = YGFloatOptional( + const YGFloatOptional paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, ownerWidth)); child->setLayoutComputedFlexBasis(YGFloatOptionalMax( @@ -1339,7 +1339,7 @@ static void YGNodeComputeFlexBasisForChild( paddingAndBorder)); } else if (!isMainAxisRow && isColumnStyleDimDefined) { // The height is definite, so use that as the flex basis. - const YGFloatOptional& paddingAndBorder = + const YGFloatOptional paddingAndBorder = YGFloatOptional(YGNodePaddingAndBorderForAxis( child, YGFlexDirectionColumn, ownerWidth)); child->setLayoutComputedFlexBasis(YGFloatOptionalMax( From 59755d2874e8c47f707bdcafa59a1fc40c7570e3 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 115/189] Inline `YGFloatOptional` completely Summary: @public `YGFLoatOptional` only contains trivial functionality. Make it header-only. Reviewed By: SidharthGuglani Differential Revision: D13209151 fbshipit-source-id: 3ecca015fa0ac6644ae694b44bc53d840fbc5635 --- yoga/YGFloatOptional.cpp | 57 ---------------------------------------- yoga/YGFloatOptional.h | 47 ++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 69 deletions(-) delete mode 100644 yoga/YGFloatOptional.cpp diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp deleted file mode 100644 index 263f24cb..00000000 --- a/yoga/YGFloatOptional.cpp +++ /dev/null @@ -1,57 +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 "YGFloatOptional.h" -#include -#include -#include "Yoga-internal.h" -#include "Yoga.h" - -using namespace facebook; - -bool YGFloatOptional::operator==(YGFloatOptional op) const { - return value_ == op.value_ || (isUndefined() && op.isUndefined()); -} - -bool YGFloatOptional::operator!=(YGFloatOptional op) const { - return !(*this == op); -} - -bool YGFloatOptional::operator==(float val) const { - return value_ == val || (isUndefined() && yoga::isUndefined(val)); -} - -bool YGFloatOptional::operator!=(float val) const { - return !(*this == val); -} - -YGFloatOptional YGFloatOptional::operator-() const { - return YGFloatOptional{-value_}; -} - -YGFloatOptional YGFloatOptional::operator+(YGFloatOptional op) const { - return YGFloatOptional{value_ + op.value_}; -} - -YGFloatOptional YGFloatOptional::operator-(YGFloatOptional op) const { - return YGFloatOptional{value_ - op.value_}; -} - -bool YGFloatOptional::operator>(YGFloatOptional op) const { - return value_ > op.value_; -} - -bool YGFloatOptional::operator<(YGFloatOptional op) const { - return value_ < op.value_; -} - -bool YGFloatOptional::operator>=(YGFloatOptional op) const { - return *this > op || *this == op; -} - -bool YGFloatOptional::operator<=(YGFloatOptional op) const { - return *this < op || *this == op; -} diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index f6e654fb..3dd3d5c9 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -7,6 +7,7 @@ #pragma once #include +#include "Yoga-internal.h" struct YGFloatOptional { private: @@ -17,7 +18,7 @@ struct YGFloatOptional { constexpr YGFloatOptional() = default; // returns the wrapped value, or a value x with YGIsUndefined(x) == true - float unwrap() const { + constexpr float unwrap() const { return value_; } @@ -35,16 +36,38 @@ struct YGFloatOptional { return isUndefined() ? f() : value_; } - YGFloatOptional operator-() const; - YGFloatOptional operator+(YGFloatOptional op) const; - YGFloatOptional operator-(YGFloatOptional op) const; - bool operator>(YGFloatOptional op) const; - bool operator<(YGFloatOptional op) const; - bool operator>=(YGFloatOptional op) const; - bool operator<=(YGFloatOptional op) const; - bool operator==(YGFloatOptional op) const; - bool operator!=(YGFloatOptional op) const; + YGFloatOptional operator-() const { + return YGFloatOptional{-value_}; + } + YGFloatOptional operator+(YGFloatOptional op) const { + return YGFloatOptional{value_ + op.value_}; + } + YGFloatOptional operator-(YGFloatOptional op) const { + return YGFloatOptional{value_ - op.value_}; + } + bool operator>(YGFloatOptional op) const { + return value_ > op.value_; + } + bool operator<(YGFloatOptional op) const { + return value_ < op.value_; + } + bool operator>=(YGFloatOptional op) const { + return *this > op || *this == op; + } + bool operator<=(YGFloatOptional op) const { + return *this < op || *this == op; + } + bool operator==(YGFloatOptional op) const { + return value_ == op.value_ || (isUndefined() && op.isUndefined()); + } + bool operator!=(YGFloatOptional op) const { + return !(*this == op); + } - bool operator==(float val) const; - bool operator!=(float val) const; + bool operator==(float val) const { + return value_ == val || (isUndefined() && yoga::isUndefined(val)); + } + bool operator!=(float val) const { + return !(*this == val); + } }; From 9680ae98a69d62b8c4308be554b35515de62678a Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 116/189] Get rid of `static_cast` in `YGResolveValue` Summary: @public Removes `static_cast` from `YGResolveValue` Reviewed By: SidharthGuglani Differential Revision: D13209155 fbshipit-source-id: 76c27c89f6217af9dfef9e2620d639c9f3e212f5 --- yoga/Utils.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/yoga/Utils.h b/yoga/Utils.h index 204b2718..2a52eb2a 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -100,16 +100,13 @@ inline YGFloatOptional YGResolveValue( const YGValue value, const float ownerSize) { switch (value.unit) { - case YGUnitUndefined: - case YGUnitAuto: - return YGFloatOptional(); case YGUnitPoint: - return YGFloatOptional(value.value); + return YGFloatOptional{value.value}; case YGUnitPercent: - return YGFloatOptional( - static_cast(value.value * ownerSize * 0.01)); + return YGFloatOptional{value.value * ownerSize * 0.01f}; + default: + return YGFloatOptional{}; } - return YGFloatOptional(); } inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) { From b6498987faf60cb0c09e0f056e60b9d348b3fa12 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 117/189] Remove unnecessary `static` keyword MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public Header-declared inline functions shouldn’t be decleared `static` Reviewed By: SidharthGuglani Differential Revision: D13209156 fbshipit-source-id: e2d643a67e6f6c33c96dc71b0a90d00bd9b6f36f --- yoga/Utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yoga/Utils.h b/yoga/Utils.h index 2a52eb2a..7357009c 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -128,7 +128,7 @@ inline YGFlexDirection YGResolveFlexDirection( return flexDirection; } -static inline YGFloatOptional YGResolveValueMargin( +inline YGFloatOptional YGResolveValueMargin( const YGValue value, const float ownerSize) { return value.unit == YGUnitAuto ? YGFloatOptional(0) From 10b316f31551b7e60708cae1c225baf44c3eee4c Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 118/189] inline `YGUnwrapFloatOptional` Summary: @public Replaces C-style function call with C++ method invokation. Reviewed By: SidharthGuglani Differential Revision: D13209154 fbshipit-source-id: 14e650af4655efb3a659f3cd949a11df773aabcf --- yoga/Utils.cpp | 4 - yoga/Utils.h | 5 - yoga/YGNode.cpp | 14 +- yoga/Yoga.cpp | 390 +++++++++++++++++++++++++----------------------- 4 files changed, 212 insertions(+), 201 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 88ebd841..b246f943 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -55,10 +55,6 @@ float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } -float YGUnwrapFloatOptional(const YGFloatOptional op) { - return op.unwrap(); -} - YGFloatOptional YGFloatOptionalMax( const YGFloatOptional op1, const YGFloatOptional op2) { diff --git a/yoga/Utils.h b/yoga/Utils.h index 7357009c..a0d49235 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -82,11 +82,6 @@ bool YGFloatArrayEqual( // This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise float YGFloatSanitize(const float val); -// This function unwraps optional and returns YGUndefined if not defined or -// op.value otherwise -// TODO: Get rid off this function -float YGUnwrapFloatOptional(const YGFloatOptional op); - YGFlexDirection YGFlexDirectionCross( const YGFlexDirection flexDirection, const YGDirection direction); diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 83c1eabd..9ae03b01 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -232,20 +232,18 @@ void YGNode::setPosition( relativePosition(crossAxis, crossSize); setLayoutPosition( - YGUnwrapFloatOptional( - getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain), + (getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), leading[mainAxis]); setLayoutPosition( - YGUnwrapFloatOptional( - getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain), + (getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), trailing[mainAxis]); setLayoutPosition( - YGUnwrapFloatOptional( - getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross), + (getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross) + .unwrap(), leading[crossAxis]); setLayoutPosition( - YGUnwrapFloatOptional( - getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross), + (getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross) + .unwrap(), trailing[crossAxis]); } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index e708f61c..e000ab1d 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1093,9 +1093,9 @@ static inline float YGNodePaddingAndBorderForAxis( const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(axis, widthSize) + - node->getTrailingPaddingAndBorder(axis, widthSize)); + return (node->getLeadingPaddingAndBorder(axis, widthSize) + + node->getTrailingPaddingAndBorder(axis, widthSize)) + .unwrap(); } static inline YGAlign YGNodeAlignItem( @@ -1177,9 +1177,9 @@ static inline float YGNodeDimWithMargin( const YGFlexDirection axis, const float widthSize) { return node->getLayout().measuredDimensions[dim[axis]] + - YGUnwrapFloatOptional( - node->getLeadingMargin(axis, widthSize) + - node->getTrailingMargin(axis, widthSize)); + (node->getLeadingMargin(axis, widthSize) + + node->getTrailingMargin(axis, widthSize)) + .unwrap(); } static inline bool YGNodeIsStyleDimDefined( @@ -1246,8 +1246,7 @@ static inline float YGNodeBoundAxis( const float axisSize, const float widthSize) { return YGFloatMax( - YGUnwrapFloatOptional( - YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)), + (YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)).unwrap(), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } @@ -1354,22 +1353,24 @@ static void YGNodeComputeFlexBasisForChild( childWidthMeasureMode = YGMeasureModeUndefined; childHeightMeasureMode = YGMeasureModeUndefined; - auto marginRow = YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - auto marginColumn = YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + auto marginRow = + (child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); + auto marginColumn = + (child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); if (isRowStyleDimDefined) { childWidth = - YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionWidth), ownerWidth)) + + (YGResolveValue( + child->getResolvedDimension(YGDimensionWidth), ownerWidth)) + .unwrap() + marginRow; childWidthMeasureMode = YGMeasureModeExactly; } if (isColumnStyleDimDefined) { childHeight = - YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionHeight), ownerHeight)) + + (YGResolveValue( + child->getResolvedDimension(YGDimensionHeight), ownerHeight)) + .unwrap() + marginColumn; childHeightMeasureMode = YGMeasureModeExactly; } @@ -1495,13 +1496,14 @@ static void YGNodeAbsoluteLayoutChild( YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; auto marginRow = - YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width)); - auto marginColumn = YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionColumn, width)); + (child->getMarginForAxis(YGFlexDirectionRow, width)).unwrap(); + auto marginColumn = + (child->getMarginForAxis(YGFlexDirectionColumn, width)).unwrap(); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { - childWidth = YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionWidth), width)) + + childWidth = + (YGResolveValue(child->getResolvedDimension(YGDimensionWidth), width)) + .unwrap() + marginRow; } else { // If the child doesn't have a specified width, compute the width based @@ -1512,17 +1514,18 @@ static void YGNodeAbsoluteLayoutChild( childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] - (node->getLeadingBorder(YGFlexDirectionRow) + node->getTrailingBorder(YGFlexDirectionRow)) - - YGUnwrapFloatOptional( - child->getLeadingPosition(YGFlexDirectionRow, width) + - child->getTrailingPosition(YGFlexDirectionRow, width)); + (child->getLeadingPosition(YGFlexDirectionRow, width) + + child->getTrailingPosition(YGFlexDirectionRow, width)) + .unwrap(); childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) { - childHeight = YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionHeight), height)) + + childHeight = + (YGResolveValue(child->getResolvedDimension(YGDimensionHeight), height)) + .unwrap() + marginColumn; } else { // If the child doesn't have a specified height, compute the height @@ -1530,13 +1533,12 @@ static void YGNodeAbsoluteLayoutChild( // offsets if they're defined. if (child->isLeadingPositionDefined(YGFlexDirectionColumn) && child->isTrailingPosDefined(YGFlexDirectionColumn)) { - childHeight = - node->getLayout().measuredDimensions[YGDimensionHeight] - + childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] - (node->getLeadingBorder(YGFlexDirectionColumn) + node->getTrailingBorder(YGFlexDirectionColumn)) - - YGUnwrapFloatOptional( - child->getLeadingPosition(YGFlexDirectionColumn, height) + - child->getTrailingPosition(YGFlexDirectionColumn, height)); + (child->getLeadingPosition(YGFlexDirectionColumn, height) + + child->getTrailingPosition(YGFlexDirectionColumn, height)) + .unwrap(); childHeight = YGNodeBoundAxis( child, YGFlexDirectionColumn, childHeight, height, width); } @@ -1589,11 +1591,9 @@ static void YGNodeAbsoluteLayoutChild( "abs-measure", config); childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + - YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionRow, width)); + (child->getMarginForAxis(YGFlexDirectionRow, width)).unwrap(); childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionColumn, width)); + (child->getMarginForAxis(YGFlexDirectionColumn, width)).unwrap(); } YGLayoutNodeInternal( @@ -1615,9 +1615,10 @@ static void YGNodeAbsoluteLayoutChild( node->getLayout().measuredDimensions[dim[mainAxis]] - child->getLayout().measuredDimensions[dim[mainAxis]] - node->getTrailingBorder(mainAxis) - - YGUnwrapFloatOptional(child->getTrailingMargin(mainAxis, width)) - - YGUnwrapFloatOptional(child->getTrailingPosition( - mainAxis, isMainAxisRow ? width : height)), + (child->getTrailingMargin(mainAxis, width)).unwrap() - + (child->getTrailingPosition( + mainAxis, isMainAxisRow ? width : height)) + .unwrap(), leading[mainAxis]); } else if ( !child->isLeadingPositionDefined(mainAxis) && @@ -1642,9 +1643,10 @@ static void YGNodeAbsoluteLayoutChild( node->getLayout().measuredDimensions[dim[crossAxis]] - child->getLayout().measuredDimensions[dim[crossAxis]] - node->getTrailingBorder(crossAxis) - - YGUnwrapFloatOptional(child->getTrailingMargin(crossAxis, width)) - - YGUnwrapFloatOptional(child->getTrailingPosition( - crossAxis, isMainAxisRow ? height : width)), + (child->getTrailingMargin(crossAxis, width)).unwrap() - + (child->getTrailingPosition( + crossAxis, isMainAxisRow ? height : width)) + .unwrap(), leading[crossAxis]); } else if ( @@ -1683,10 +1685,10 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis( node, YGFlexDirectionColumn, availableWidth); - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, availableWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, availableWidth)); + const float marginAxisRow = + (node->getMarginForAxis(YGFlexDirectionRow, availableWidth)).unwrap(); + const float marginAxisColumn = + (node->getMarginForAxis(YGFlexDirectionColumn, availableWidth)).unwrap(); // We want to make sure we don't call measure with negative size const float innerWidth = YGFloatIsUndefined(availableWidth) @@ -1761,10 +1763,10 @@ static void YGNodeEmptyContainerSetMeasuredDimensions( YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, ownerWidth); - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + const float marginAxisRow = + (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); + const float marginAxisColumn = + (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); node->setLayoutMeasuredDimension( YGNodeBoundAxis( @@ -1805,10 +1807,10 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { - auto marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); - auto marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + auto marginAxisColumn = + (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); + auto marginAxisRow = + (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); node->setLayoutMeasuredDimension( YGNodeBoundAxis( @@ -1864,8 +1866,7 @@ static float YGNodeCalculateAvailableInnerDim( YGDimension dimension = YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight; - const float margin = - YGUnwrapFloatOptional(node->getMarginForAxis(direction, ownerDim)); + const float margin = (node->getMarginForAxis(direction, ownerDim)).unwrap(); const float paddingAndBorder = YGNodePaddingAndBorderForAxis(node, direction, ownerDim); @@ -1969,9 +1970,10 @@ static float YGNodeComputeFlexBasisForChildren( config); } - totalOuterFlexBasis += YGUnwrapFloatOptional( - child->getLayout().computedFlexBasis + - child->getMarginForAxis(mainAxis, availableInnerWidth)); + totalOuterFlexBasis += + (child->getLayout().computedFlexBasis + + child->getMarginForAxis(mainAxis, availableInnerWidth)) + .unwrap(); } return totalOuterFlexBasis; @@ -2006,14 +2008,15 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( continue; } child->setLineIndex(lineCount); - const float childMarginMainAxis = YGUnwrapFloatOptional( - child->getMarginForAxis(mainAxis, availableInnerWidth)); + const float childMarginMainAxis = + (child->getMarginForAxis(mainAxis, availableInnerWidth)).unwrap(); const float flexBasisWithMinAndMaxConstraints = - YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - child, - mainAxis, - YGUnwrapFloatOptional(child->getLayout().computedFlexBasis), - mainAxisownerSize)); + (YGNodeBoundAxisWithinMinAndMax( + child, + mainAxis, + (child->getLayout().computedFlexBasis).unwrap(), + mainAxisownerSize)) + .unwrap(); // If this is a multi-line flow and this item pushes us over the // available size, we've @@ -2039,7 +2042,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( // child dimension. flexAlgoRowMeasurement.totalFlexShrinkScaledFactors += -child->resolveFlexShrink() * - YGUnwrapFloatOptional(child->getLayout().computedFlexBasis); + (child->getLayout().computedFlexBasis).unwrap(); } flexAlgoRowMeasurement.relativeChildren.push_back(child); @@ -2086,12 +2089,13 @@ static float YGDistributeFreeSpaceSecondPass( const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - YGUnwrapFloatOptional( - currentRelativeChild->getLayout().computedFlexBasis), - mainAxisownerSize)); + childFlexBasis = + (YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + (currentRelativeChild->getLayout().computedFlexBasis).unwrap(), + mainAxisownerSize)) + .unwrap(); float updatedMainSize = childFlexBasis; if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && @@ -2141,10 +2145,12 @@ static float YGDistributeFreeSpaceSecondPass( deltaFreeSpace += updatedMainSize - childFlexBasis; - const float marginMain = YGUnwrapFloatOptional( - currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth)); - const float marginCross = YGUnwrapFloatOptional( - currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth)); + const float marginMain = + (currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth)) + .unwrap(); + const float marginCross = + (currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth)) + .unwrap(); float childCrossSize; float childMainSize = updatedMainSize + marginMain; @@ -2180,9 +2186,10 @@ static float YGDistributeFreeSpaceSecondPass( : YGMeasureModeAtMost; } else { childCrossSize = - YGUnwrapFloatOptional(YGResolveValue( - currentRelativeChild->getResolvedDimension(dim[crossAxis]), - availableInnerCrossDim)) + + (YGResolveValue( + currentRelativeChild->getResolvedDimension(dim[crossAxis]), + availableInnerCrossDim)) + .unwrap() + marginCross; const bool isLoosePercentageMeasurement = currentRelativeChild->getResolvedDimension(dim[crossAxis]).unit == @@ -2262,12 +2269,13 @@ static void YGDistributeFreeSpaceFirstPass( float deltaFreeSpace = 0; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - float childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - YGUnwrapFloatOptional( - currentRelativeChild->getLayout().computedFlexBasis), - mainAxisownerSize)); + float childFlexBasis = + (YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + (currentRelativeChild->getLayout().computedFlexBasis).unwrap(), + mainAxisownerSize)) + .unwrap(); if (collectedFlexItemsValues.remainingFreeSpace < 0) { flexShrinkScaledFactor = @@ -2418,10 +2426,10 @@ static void YGJustifyMainAxis( const float availableInnerWidth, const bool performLayout) { const YGStyle& style = node->getStyle(); - const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); - const float trailingPaddingAndBorderMain = YGUnwrapFloatOptional( - node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)); + const float leadingPaddingAndBorderMain = + (node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)).unwrap(); + const float trailingPaddingAndBorderMain = + (node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)).unwrap(); // If we are using "at most" rules in the main axis, make sure that // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && @@ -2437,8 +2445,9 @@ static void YGJustifyMainAxis( // `minAvailableMainDim` denotes minimum available space in which child // can be laid out, it will exclude space consumed by padding and border. const float minAvailableMainDim = - YGUnwrapFloatOptional(YGResolveValue( - style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - + (YGResolveValue( + style.minDimensions[dim[mainAxis]], mainAxisownerSize)) + .unwrap() - leadingPaddingAndBorderMain - trailingPaddingAndBorderMain; const float occupiedSpaceByChildNodes = availableInnerMainDim - collectedFlexItemsValues.remainingFreeSpace; @@ -2528,11 +2537,11 @@ static void YGJustifyMainAxis( // defined, we override the position to whatever the user said // (and margin/border). child->setLayoutPosition( - YGUnwrapFloatOptional( - child->getLeadingPosition(mainAxis, availableInnerMainDim)) + + (child->getLeadingPosition(mainAxis, availableInnerMainDim)) + .unwrap() + node->getLeadingBorder(mainAxis) + - YGUnwrapFloatOptional( - child->getLeadingMargin(mainAxis, availableInnerWidth)), + (child->getLeadingMargin(mainAxis, availableInnerWidth)) + .unwrap(), pos[mainAxis]); } } else { @@ -2566,9 +2575,9 @@ static void YGJustifyMainAxis( // they weren't computed. This means we can't call // YGNodeDimWithMargin. collectedFlexItemsValues.mainDim += betweenMainDim + - YGUnwrapFloatOptional(child->getMarginForAxis( - mainAxis, availableInnerWidth)) + - YGUnwrapFloatOptional(childLayout.computedFlexBasis); + (child->getMarginForAxis(mainAxis, availableInnerWidth)) + .unwrap() + + (childLayout.computedFlexBasis).unwrap(); collectedFlexItemsValues.crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus @@ -2580,12 +2589,14 @@ static void YGJustifyMainAxis( // If the child is baseline aligned then the cross dimension is // calculated by adding maxAscent and maxDescent from the baseline. const float ascent = YGBaseline(child) + - YGUnwrapFloatOptional(child->getLeadingMargin( - YGFlexDirectionColumn, availableInnerWidth)); + (child->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth)) + .unwrap(); const float descent = child->getLayout().measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional(child->getMarginForAxis( - YGFlexDirectionColumn, availableInnerWidth)) - + (child->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth)) + .unwrap() - ascent; maxAscentForCurrentLine = @@ -2738,20 +2749,16 @@ static void YGNodelayoutImpl( YGResolveFlexDirection(YGFlexDirectionColumn, direction); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getLeadingMargin(flexRowDirection, ownerWidth)), + (node->getLeadingMargin(flexRowDirection, ownerWidth)).unwrap(), YGEdgeStart); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getTrailingMargin(flexRowDirection, ownerWidth)), + (node->getTrailingMargin(flexRowDirection, ownerWidth)).unwrap(), YGEdgeEnd); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getLeadingMargin(flexColumnDirection, ownerWidth)), + (node->getLeadingMargin(flexColumnDirection, ownerWidth)).unwrap(), YGEdgeTop); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getTrailingMargin(flexColumnDirection, ownerWidth)), + (node->getTrailingMargin(flexColumnDirection, ownerWidth)).unwrap(), YGEdgeBottom); node->setLayoutBorder(node->getLeadingBorder(flexRowDirection), YGEdgeStart); @@ -2761,20 +2768,16 @@ static void YGNodelayoutImpl( node->getTrailingBorder(flexColumnDirection), YGEdgeBottom); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getLeadingPadding(flexRowDirection, ownerWidth)), + (node->getLeadingPadding(flexRowDirection, ownerWidth)).unwrap(), YGEdgeStart); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getTrailingPadding(flexRowDirection, ownerWidth)), + (node->getTrailingPadding(flexRowDirection, ownerWidth)).unwrap(), YGEdgeEnd); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getLeadingPadding(flexColumnDirection, ownerWidth)), + (node->getLeadingPadding(flexColumnDirection, ownerWidth)).unwrap(), YGEdgeTop); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getTrailingPadding(flexColumnDirection, ownerWidth)), + (node->getTrailingPadding(flexColumnDirection, ownerWidth)).unwrap(), YGEdgeBottom); if (node->getMeasure() != nullptr) { @@ -2832,8 +2835,8 @@ static void YGNodelayoutImpl( const float mainAxisownerSize = isMainAxisRow ? ownerWidth : ownerHeight; const float crossAxisownerSize = isMainAxisRow ? ownerHeight : ownerWidth; - const float leadingPaddingAndBorderCross = YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)); + const float leadingPaddingAndBorderCross = + (node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)).unwrap(); const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); const float paddingAndBorderAxisCross = @@ -2849,26 +2852,30 @@ static void YGNodelayoutImpl( const float paddingAndBorderAxisColumn = isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain; - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + const float marginAxisRow = + (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); + const float marginAxisColumn = + (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); const float minInnerWidth = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - + (YGResolveValue( + node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) + .unwrap() - paddingAndBorderAxisRow; const float maxInnerWidth = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - + (YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) + .unwrap() - paddingAndBorderAxisRow; const float minInnerHeight = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - + (YGResolveValue( + node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) + .unwrap() - paddingAndBorderAxisColumn; const float maxInnerHeight = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) - + (YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) + .unwrap() - paddingAndBorderAxisColumn; const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; @@ -3079,11 +3086,11 @@ static void YGNodelayoutImpl( child->isLeadingPositionDefined(crossAxis); if (isChildLeadingPosDefined) { child->setLayoutPosition( - YGUnwrapFloatOptional(child->getLeadingPosition( - crossAxis, availableInnerCrossDim)) + + (child->getLeadingPosition(crossAxis, availableInnerCrossDim)) + .unwrap() + node->getLeadingBorder(crossAxis) + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + (child->getLeadingMargin(crossAxis, availableInnerWidth)) + .unwrap(), pos[crossAxis]); } // If leading position is not defined or calculations result in Nan, @@ -3092,8 +3099,8 @@ static void YGNodelayoutImpl( YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( node->getLeadingBorder(crossAxis) + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + (child->getLeadingMargin(crossAxis, availableInnerWidth)) + .unwrap(), pos[crossAxis]); } } else { @@ -3119,16 +3126,17 @@ static void YGNodelayoutImpl( child->getLayout().measuredDimensions[dim[mainAxis]]; float childCrossSize = !child->getStyle().aspectRatio.isUndefined() - ? ((YGUnwrapFloatOptional(child->getMarginForAxis( - crossAxis, availableInnerWidth)) + + ? (((child->getMarginForAxis(crossAxis, availableInnerWidth)) + .unwrap() + (isMainAxisRow ? childMainSize / child->getStyle().aspectRatio.unwrap() : childMainSize * child->getStyle().aspectRatio.unwrap()))) : collectedFlexItemsValues.crossDim; - childMainSize += YGUnwrapFloatOptional( - child->getMarginForAxis(mainAxis, availableInnerWidth)); + childMainSize += + (child->getMarginForAxis(mainAxis, availableInnerWidth)) + .unwrap(); YGMeasureMode childMainMeasureMode = YGMeasureModeExactly; YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly; @@ -3270,17 +3278,19 @@ static void YGNodelayoutImpl( lineHeight = YGFloatMax( lineHeight, child->getLayout().measuredDimensions[dim[crossAxis]] + - YGUnwrapFloatOptional(child->getMarginForAxis( - crossAxis, availableInnerWidth))); + (child->getMarginForAxis(crossAxis, availableInnerWidth)) + .unwrap()); } if (YGNodeAlignItem(node, child) == YGAlignBaseline) { const float ascent = YGBaseline(child) + - YGUnwrapFloatOptional(child->getLeadingMargin( - YGFlexDirectionColumn, availableInnerWidth)); + (child->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth)) + .unwrap(); const float descent = child->getLayout().measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional(child->getMarginForAxis( - YGFlexDirectionColumn, availableInnerWidth)) - + (child->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth)) + .unwrap() - ascent; maxAscentForCurrentLine = YGFloatMax(maxAscentForCurrentLine, ascent); @@ -3305,16 +3315,18 @@ static void YGNodelayoutImpl( case YGAlignFlexStart: { child->setLayoutPosition( currentLead + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + (child->getLeadingMargin( + crossAxis, availableInnerWidth)) + .unwrap(), pos[crossAxis]); break; } case YGAlignFlexEnd: { child->setLayoutPosition( currentLead + lineHeight - - YGUnwrapFloatOptional(child->getTrailingMargin( - crossAxis, availableInnerWidth)) - + (child->getTrailingMargin( + crossAxis, availableInnerWidth)) + .unwrap() - child->getLayout().measuredDimensions[dim[crossAxis]], pos[crossAxis]); break; @@ -3331,8 +3343,9 @@ static void YGNodelayoutImpl( case YGAlignStretch: { child->setLayoutPosition( currentLead + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + (child->getLeadingMargin( + crossAxis, availableInnerWidth)) + .unwrap(), pos[crossAxis]); // Remeasure child with the line height as it as been only @@ -3342,15 +3355,17 @@ static void YGNodelayoutImpl( const float childWidth = isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionWidth] + - YGUnwrapFloatOptional(child->getMarginForAxis( - mainAxis, availableInnerWidth))) + (child->getMarginForAxis( + mainAxis, availableInnerWidth)) + .unwrap()) : lineHeight; const float childHeight = !isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional(child->getMarginForAxis( - crossAxis, availableInnerWidth))) + (child->getMarginForAxis( + crossAxis, availableInnerWidth)) + .unwrap()) : lineHeight; if (!(YGFloatsEqual( @@ -3380,8 +3395,9 @@ static void YGNodelayoutImpl( case YGAlignBaseline: { child->setLayoutPosition( currentLead + maxAscentForCurrentLine - YGBaseline(child) + - YGUnwrapFloatOptional(child->getLeadingPosition( - YGFlexDirectionColumn, availableInnerCrossDim)), + (child->getLeadingPosition( + YGFlexDirectionColumn, availableInnerCrossDim)) + .unwrap(), YGEdgeTop); break; @@ -3437,8 +3453,9 @@ static void YGNodelayoutImpl( YGFloatMax( YGFloatMin( availableInnerMainDim + paddingAndBorderAxisMain, - YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - node, mainAxis, maxLineMainDim, mainAxisownerSize))), + (YGNodeBoundAxisWithinMinAndMax( + node, mainAxis, maxLineMainDim, mainAxisownerSize)) + .unwrap()), paddingAndBorderAxisMain), dim[mainAxis]); } @@ -3464,11 +3481,12 @@ static void YGNodelayoutImpl( YGFloatMax( YGFloatMin( availableInnerCrossDim + paddingAndBorderAxisCross, - YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - node, - crossAxis, - totalLineCrossDim + paddingAndBorderAxisCross, - crossAxisownerSize))), + (YGNodeBoundAxisWithinMinAndMax( + node, + crossAxis, + totalLineCrossDim + paddingAndBorderAxisCross, + crossAxisownerSize)) + .unwrap()), paddingAndBorderAxisCross), dim[crossAxis]); } @@ -3768,10 +3786,10 @@ bool YGLayoutNodeInternal( // expensive to measure, so it's worth avoiding redundant measurements if at // all possible. if (node->getMeasure() != nullptr) { - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + const float marginAxisRow = + (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); + const float marginAxisColumn = + (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); // First, try to use the layout cache. if (YGNodeCanUseCachedMeasurement( @@ -4071,16 +4089,18 @@ void YGNodeCalculateLayout( float width = YGUndefined; YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow, ownerWidth)) { - width = YGUnwrapFloatOptional( - YGResolveValue( - node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) + - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + width = + (YGResolveValue( + node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) + + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)) + .unwrap(); widthMeasureMode = YGMeasureModeExactly; } else if (!YGResolveValue( node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth) .isUndefined()) { - width = YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)); + width = (YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) + .unwrap(); widthMeasureMode = YGMeasureModeAtMost; } else { width = ownerWidth; @@ -4091,18 +4111,20 @@ void YGNodeCalculateLayout( float height = YGUndefined; YGMeasureMode heightMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn, ownerHeight)) { - height = YGUnwrapFloatOptional( - YGResolveValue( - node->getResolvedDimension(dim[YGFlexDirectionColumn]), - ownerHeight) + - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + height = (YGResolveValue( + node->getResolvedDimension(dim[YGFlexDirectionColumn]), + ownerHeight) + + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)) + .unwrap(); heightMeasureMode = YGMeasureModeExactly; } else if (!YGResolveValue( node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) .isUndefined()) { - height = YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); + height = + (YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) + .unwrap(); heightMeasureMode = YGMeasureModeAtMost; } else { height = ownerHeight; From 5719132f5890e92573b203757298e1e17bc19734 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 119/189] `YGNodeBoundAxisWithinMinAndMax` accepts `YGFloatOptional` Summary: @public Saves some calls to `.unwrap()` Reviewed By: SidharthGuglani Differential Revision: D13209153 fbshipit-source-id: 5658586e91496085f39b3522db6364aaeafcfe2f --- yoga/Yoga.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index e000ab1d..b5320c63 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1209,7 +1209,7 @@ static inline bool YGNodeIsLayoutDimDefined( static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( const YGNodeRef node, const YGFlexDirection axis, - const float value, + const YGFloatOptional value, const float axisSize) { YGFloatOptional min; YGFloatOptional max; @@ -1226,15 +1226,15 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( node->getStyle().maxDimensions[YGDimensionWidth], axisSize); } - if (max >= YGFloatOptional{0} && YGFloatOptional{value} > max) { + if (max >= YGFloatOptional{0} && value > max) { return max; } - if (min >= YGFloatOptional{0} && YGFloatOptional{value} < min) { + if (min >= YGFloatOptional{0} && value < min) { return min; } - return YGFloatOptional{value}; + return value; } // Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't @@ -1246,7 +1246,9 @@ static inline float YGNodeBoundAxis( const float axisSize, const float widthSize) { return YGFloatMax( - (YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)).unwrap(), + (YGNodeBoundAxisWithinMinAndMax( + node, axis, YGFloatOptional{value}, axisSize)) + .unwrap(), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } @@ -2014,7 +2016,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( (YGNodeBoundAxisWithinMinAndMax( child, mainAxis, - (child->getLayout().computedFlexBasis).unwrap(), + child->getLayout().computedFlexBasis, mainAxisownerSize)) .unwrap(); @@ -2089,13 +2091,12 @@ static float YGDistributeFreeSpaceSecondPass( const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - childFlexBasis = - (YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - (currentRelativeChild->getLayout().computedFlexBasis).unwrap(), - mainAxisownerSize)) - .unwrap(); + childFlexBasis = (YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + currentRelativeChild->getLayout().computedFlexBasis, + mainAxisownerSize)) + .unwrap(); float updatedMainSize = childFlexBasis; if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && @@ -2273,7 +2274,7 @@ static void YGDistributeFreeSpaceFirstPass( (YGNodeBoundAxisWithinMinAndMax( currentRelativeChild, mainAxis, - (currentRelativeChild->getLayout().computedFlexBasis).unwrap(), + currentRelativeChild->getLayout().computedFlexBasis, mainAxisownerSize)) .unwrap(); @@ -3454,7 +3455,10 @@ static void YGNodelayoutImpl( YGFloatMin( availableInnerMainDim + paddingAndBorderAxisMain, (YGNodeBoundAxisWithinMinAndMax( - node, mainAxis, maxLineMainDim, mainAxisownerSize)) + node, + mainAxis, + YGFloatOptional{maxLineMainDim}, + mainAxisownerSize)) .unwrap()), paddingAndBorderAxisMain), dim[mainAxis]); @@ -3484,7 +3488,8 @@ static void YGNodelayoutImpl( (YGNodeBoundAxisWithinMinAndMax( node, crossAxis, - totalLineCrossDim + paddingAndBorderAxisCross, + YGFloatOptional{totalLineCrossDim + + paddingAndBorderAxisCross}, crossAxisownerSize)) .unwrap()), paddingAndBorderAxisCross), From 5a65261a55c4cb87f1a3bd891f16ab30a2dfee0e Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 120/189] Remove templates for setting/getting style properties Summary: @public Replaces the `StyleProp` template with a simple setter macro / inlined getter code. The template was introduced to replace more extensive macros that would generate function signatures, too. Here, we keep the spirit of that change by only generating function bodies. Reviewed By: SidharthGuglani Differential Revision: D13233687 fbshipit-source-id: 218a7d5edb489b43a66c8c9d6156f74feefd2227 --- yoga/Yoga.cpp | 63 ++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index b5320c63..5a5da8b0 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -591,19 +591,6 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { namespace { -template -struct StyleProp { - static T get(YGNodeRef node) { - return node->getStyle().*P; - } - static void set(YGNodeRef node, T newValue) { - if (node->getStyle().*P != newValue) { - node->getStyle().*P = newValue; - node->markDirtyAndPropogate(); - } - } -}; - struct Value { template static YGValue create(float value) { @@ -763,84 +750,88 @@ struct DimensionProp { return node->getLayout().instanceName[edge]; \ } -void YGNodeStyleSetDirection( - const YGNodeRef node, - const YGDirection direction) { - StyleProp::set(node, direction); +#define YG_NODE_STYLE_SET(node, property, value) \ + if (node->getStyle().property != value) { \ + node->getStyle().property = value; \ + node->markDirtyAndPropogate(); \ + } + +void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { + YG_NODE_STYLE_SET(node, direction, value); } YGDirection YGNodeStyleGetDirection(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().direction; } void YGNodeStyleSetFlexDirection( const YGNodeRef node, const YGFlexDirection flexDirection) { - StyleProp::set(node, flexDirection); + YG_NODE_STYLE_SET(node, flexDirection, flexDirection); } YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().flexDirection; } void YGNodeStyleSetJustifyContent( const YGNodeRef node, const YGJustify justifyContent) { - StyleProp::set(node, justifyContent); + YG_NODE_STYLE_SET(node, justifyContent, justifyContent); } YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().justifyContent; } void YGNodeStyleSetAlignContent( const YGNodeRef node, const YGAlign alignContent) { - StyleProp::set(node, alignContent); + YG_NODE_STYLE_SET(node, alignContent, alignContent); } YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().alignContent; } void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { - StyleProp::set(node, alignItems); + YG_NODE_STYLE_SET(node, alignItems, alignItems); } YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().alignItems; } void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { - StyleProp::set(node, alignSelf); + YG_NODE_STYLE_SET(node, alignSelf, alignSelf); } YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().alignSelf; } void YGNodeStyleSetPositionType( const YGNodeRef node, const YGPositionType positionType) { - StyleProp::set(node, positionType); + YG_NODE_STYLE_SET(node, positionType, positionType); } YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().positionType; } void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { - StyleProp::set(node, flexWrap); + YG_NODE_STYLE_SET(node, flexWrap, flexWrap); } YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().flexWrap; } void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { - StyleProp::set(node, overflow); + YG_NODE_STYLE_SET(node, overflow, overflow); } YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().overflow; } void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { - StyleProp::set(node, display); + YG_NODE_STYLE_SET(node, display, display); } YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().display; } // TODO(T26792433): Change the API to accept YGFloatOptional. From 4248fd9d4cd4278679b11c6193e8cba84fe6389d Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 121/189] Use bitfields for enum members of `YGStyle` Summary: @public Puts all enum fields of `YGStyle` into bitfields. This saves 36 bytes (> 3%) per node. Reviewed By: SidharthGuglani Differential Revision: D13233686 fbshipit-source-id: 3ef7e0d6913f0254806acb942d9a9f5b78a5af9c --- yoga/YGStyle.h | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index c3a01d44..c4f7e3c7 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -30,16 +30,16 @@ constexpr std::array kYGDefaultDimensionValuesUnit = { struct YGStyle { using Dimensions = std::array; - YGDirection direction = YGDirectionInherit; - YGFlexDirection flexDirection = YGFlexDirectionColumn; - YGJustify justifyContent = YGJustifyFlexStart; - YGAlign alignContent = YGAlignFlexStart; - YGAlign alignItems = YGAlignStretch; - YGAlign alignSelf = YGAlignAuto; - YGPositionType positionType = YGPositionTypeRelative; - YGWrap flexWrap = YGWrapNoWrap; - YGOverflow overflow = YGOverflowVisible; - YGDisplay display = YGDisplayFlex; + YGDirection direction : 2; + YGFlexDirection flexDirection : 2; + YGJustify justifyContent : 3; + YGAlign alignContent : 3; + YGAlign alignItems : 3; + YGAlign alignSelf : 3; + YGPositionType positionType : 1; + YGWrap flexWrap : 2; + YGOverflow overflow : 2; + YGDisplay display : 1; YGFloatOptional flex = {}; YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; @@ -54,7 +54,17 @@ struct YGStyle { // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio = {}; - YGStyle() = default; + YGStyle() + : direction(YGDirectionInherit), + flexDirection(YGFlexDirectionColumn), + justifyContent(YGJustifyFlexStart), + alignContent(YGAlignFlexStart), + alignItems(YGAlignStretch), + alignSelf(YGAlignAuto), + positionType(YGPositionTypeRelative), + flexWrap(YGWrapNoWrap), + overflow(YGOverflowVisible), + display(YGDisplayFlex) {} bool operator==(const YGStyle& style); bool operator!=(YGStyle style) { From 6b7f6980f939fa2702b313b5d9d17eced83e7fcb Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 6 Dec 2018 07:35:10 -0800 Subject: [PATCH 122/189] Don't pass `std::string` by pointer Summary: @public Pass strings by mutable ref rather than pointer. Reviewed By: SidharthGuglani Differential Revision: D13236159 fbshipit-source-id: 04fd35e8a9e106ba8cdd71cfab31e8d90edaac9e --- yoga/YGNodePrint.cpp | 26 +++++++++++++------------- yoga/YGNodePrint.h | 2 +- yoga/Yoga.cpp | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index c497996e..753a00b6 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -14,9 +14,9 @@ namespace facebook { namespace yoga { typedef std::string string; -static void indent(string* base, uint32_t level) { +static void indent(string& base, uint32_t level) { for (uint32_t i = 0; i < level; ++i) { - base->append(" "); + base.append(" "); } } @@ -25,7 +25,7 @@ static bool areFourValuesEqual(const std::array& four) { YGValueEqual(four[0], four[3]); } -static void appendFormatedString(string* str, const char* fmt, ...) { +static void appendFormatedString(string& str, const char* fmt, ...) { va_list args; va_start(args, fmt); va_list argsCopy; @@ -35,11 +35,11 @@ static void appendFormatedString(string* str, const char* fmt, ...) { vsnprintf(buf.data(), buf.size(), fmt, argsCopy); va_end(argsCopy); string result = string(buf.begin(), buf.end() - 1); - str->append(result); + str.append(result); } static void appendFloatOptionalIfDefined( - string* base, + string& base, const string key, const YGFloatOptional num) { if (!num.isUndefined()) { @@ -48,12 +48,12 @@ static void appendFloatOptionalIfDefined( } static void appendNumberIfNotUndefined( - string* base, + string& base, const string key, const YGValue number) { if (number.unit != YGUnitUndefined) { if (number.unit == YGUnitAuto) { - base->append(key + ": auto; "); + base.append(key + ": auto; "); } else { string unit = number.unit == YGUnitPoint ? "px" : "%%"; appendFormatedString( @@ -63,23 +63,23 @@ static void appendNumberIfNotUndefined( } static void -appendNumberIfNotAuto(string* base, const string& key, const YGValue number) { +appendNumberIfNotAuto(string& base, const string& key, const YGValue number) { if (number.unit != YGUnitAuto) { appendNumberIfNotUndefined(base, key, number); } } static void -appendNumberIfNotZero(string* base, const string& str, const YGValue number) { +appendNumberIfNotZero(string& base, const string& str, const YGValue number) { if (number.unit == YGUnitAuto) { - base->append(str + ": auto; "); + base.append(str + ": auto; "); } else if (!YGFloatsEqual(number.value, 0)) { appendNumberIfNotUndefined(base, str, number); } } static void appendEdges( - string* base, + string& base, const string& key, const std::array& edges) { if (areFourValuesEqual(edges)) { @@ -93,7 +93,7 @@ static void appendEdges( } static void appendEdgeIfNotUndefined( - string* base, + string& base, const string& str, const std::array& edges, const YGEdge edge) { @@ -102,7 +102,7 @@ static void appendEdgeIfNotUndefined( } void YGNodeToString( - std::string* str, + std::string& str, YGNodeRef node, YGPrintOptions options, uint32_t level) { diff --git a/yoga/YGNodePrint.h b/yoga/YGNodePrint.h index 9d36ba8d..9615bf8e 100644 --- a/yoga/YGNodePrint.h +++ b/yoga/YGNodePrint.h @@ -13,7 +13,7 @@ namespace facebook { namespace yoga { void YGNodeToString( - std::string* str, + std::string& str, YGNodeRef node, YGPrintOptions options, uint32_t level); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 5a5da8b0..f0327f87 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1057,7 +1057,7 @@ static void YGNodePrintInternal( const YGNodeRef node, const YGPrintOptions options) { std::string str; - facebook::yoga::YGNodeToString(&str, node, options, 0); + facebook::yoga::YGNodeToString(str, node, options, 0); YGLog(node, YGLogLevelDebug, str.c_str()); } From b26e637c815aa74d8772305c531b9ff18b2f08e7 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 7 Dec 2018 12:37:12 -0800 Subject: [PATCH 123/189] Back out Stack D13119110..D13236159 Summary: backout, causes failures Reviewed By: adityasharat Differential Revision: D13376210 fbshipit-source-id: 1fa8823f2dce601c47738f34ddb2674288197e79 --- csharp/Facebook.Yoga/YogaConstants.cs | 23 +- java/com/facebook/yoga/YogaConstants.java | 30 +- tests/YGFloatOptionalTest.cpp | 205 -------- tools/build_defs/oss/yoga_defs.bzl | 1 + yoga/Utils.cpp | 15 +- yoga/Utils.h | 36 +- yoga/YGFloatOptional.cpp | 83 ++++ yoga/YGFloatOptional.h | 78 +-- yoga/YGNode.cpp | 65 ++- yoga/YGNode.h | 2 +- yoga/YGNodePrint.cpp | 29 +- yoga/YGNodePrint.h | 2 +- yoga/YGStyle.cpp | 37 +- yoga/YGStyle.h | 32 +- yoga/YGValue.cpp | 11 - yoga/YGValue.h | 56 --- yoga/Yoga-internal.h | 10 +- yoga/Yoga.cpp | 569 +++++++++++----------- yoga/Yoga.h | 29 +- 19 files changed, 612 insertions(+), 701 deletions(-) delete mode 100644 tests/YGFloatOptionalTest.cpp create mode 100644 yoga/YGFloatOptional.cpp delete mode 100644 yoga/YGValue.cpp delete mode 100644 yoga/YGValue.h diff --git a/csharp/Facebook.Yoga/YogaConstants.cs b/csharp/Facebook.Yoga/YogaConstants.cs index 9e05cca3..a715b43c 100644 --- a/csharp/Facebook.Yoga/YogaConstants.cs +++ b/csharp/Facebook.Yoga/YogaConstants.cs @@ -1,4 +1,4 @@ -/** +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -9,11 +9,28 @@ namespace Facebook.Yoga { public static class YogaConstants { - public const float Undefined = float.NaN; + /** + * Large positive number signifies that the property(float) is undefined. Earlier we used to have + * YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as + * it assumes all floating-point calculation involve and result into finite numbers. For more + * information regarding -ffast-math compiler flag in clang, have a look at + * https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math + */ + public const float Undefined = 10E20F; public static bool IsUndefined(float value) { - return float.IsNaN(value); + // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN, + // the benefit of which + // was that if NAN is involved in any mathematical expression the result was NAN. But since we + // want to have `-ffast-math` + // flag being used by compiler which assumes that the floating point values are not NAN and Inf, + // we represent YGUndefined as 10.1E20. + // But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would + // change. + // So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it + // is undefined. + return value >= 10E8F || value <= -10E8; } public static bool IsUndefined(YogaValue value) diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index b04a7e53..61e212ef 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -1,17 +1,35 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. +/* + * 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. * - * 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 YogaConstants { - public static final float UNDEFINED = Float.NaN; + /** + * Large positive number signifies that the property(float) is undefined. Earlier we used to have + * YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as + * it assumes all floating-point calculation involve and result into finite numbers. For more + * information regarding -ffast-math compiler flag in clang, have a look at + * https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math + */ + public static final float UNDEFINED = (float) (10E20); public static boolean isUndefined(float value) { - return Float.compare(value, UNDEFINED) == 0; + // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN, + // the benefit of which + // was that if NAN is involved in any mathematical expression the result was NAN. But since we + // want to have `-ffast-math` + // flag being used by compiler which assumes that the floating point values are not NAN and Inf, + // we represent YGUndefined as 10.1E20. + // But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would + // change. + // So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it + // is undefined. + return (Float.compare(value, (float) 10E8) >= 0 || Float.compare(value, (float) -10E8) <= 0); } public static boolean isUndefined(YogaValue value) { diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp deleted file mode 100644 index cb4a35a7..00000000 --- a/tests/YGFloatOptionalTest.cpp +++ /dev/null @@ -1,205 +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 -#include -#include -#include - -constexpr auto empty = YGFloatOptional{}; -constexpr auto zero = YGFloatOptional{0.0f}; -constexpr auto one = YGFloatOptional{1.0f}; -constexpr auto positive = YGFloatOptional{1234.5f}; -constexpr auto negative = YGFloatOptional{-9876.5f}; - -TEST(YGFloatOptional, value) { - ASSERT_EQ(zero.unwrap(), 0.0f); - ASSERT_EQ(positive.unwrap(), 1234.5f); - ASSERT_EQ(negative.unwrap(), -9876.5f); - ASSERT_TRUE(YGFloatIsUndefined(empty.unwrap())); - - ASSERT_TRUE(empty.isUndefined()); - ASSERT_FALSE(zero.isUndefined()); - ASSERT_FALSE(negative.isUndefined()); -} - -TEST(YGFloatOptional, equality) { - ASSERT_TRUE(empty == empty); - ASSERT_TRUE(empty == YGUndefined); - ASSERT_FALSE(empty == zero); - ASSERT_FALSE(empty == negative); - ASSERT_FALSE(empty == 12.3f); - - ASSERT_TRUE(zero == zero); - ASSERT_TRUE(zero == 0.0f); - ASSERT_FALSE(zero == positive); - ASSERT_FALSE(zero == -5555.5f); - - ASSERT_TRUE(one == one); - ASSERT_TRUE(one == 1.0f); - ASSERT_FALSE(one == positive); - - ASSERT_TRUE(negative == negative); - ASSERT_TRUE(negative == negative.unwrap()); - ASSERT_FALSE(negative == zero); -} - -TEST(YGFloatOptional, inequality) { - ASSERT_FALSE(empty != empty); - ASSERT_FALSE(empty != YGUndefined); - ASSERT_TRUE(empty != zero); - ASSERT_TRUE(empty != negative); - ASSERT_TRUE(empty != 12.3f); - - ASSERT_FALSE(zero != zero); - ASSERT_FALSE(zero != 0.0f); - ASSERT_TRUE(zero != positive); - ASSERT_TRUE(zero != -5555.5f); - - ASSERT_FALSE(one != one); - ASSERT_FALSE(one != 1.0f); - ASSERT_TRUE(one != positive); - - ASSERT_FALSE(negative != negative); - ASSERT_FALSE(negative != negative.unwrap()); - ASSERT_TRUE(negative != zero); -} - -TEST(YGFloatOptional, greater) { - ASSERT_FALSE(empty > empty); - ASSERT_FALSE(empty > zero); - ASSERT_FALSE(empty > one); - ASSERT_FALSE(empty > positive); - ASSERT_FALSE(empty > negative); - ASSERT_FALSE(zero > empty); - ASSERT_FALSE(one > empty); - ASSERT_FALSE(positive > empty); - ASSERT_FALSE(negative > empty); - - ASSERT_TRUE(zero > negative); - ASSERT_FALSE(zero > zero); - ASSERT_FALSE(zero > positive); - ASSERT_FALSE(zero > one); - - ASSERT_TRUE(one > negative); - ASSERT_TRUE(one > zero); - ASSERT_FALSE(one > empty); - ASSERT_FALSE(one > positive); - - ASSERT_TRUE(negative > YGFloatOptional{-INFINITY}); - ASSERT_FALSE(negative > empty); -} - -TEST(YGFloatOptional, lower) { - ASSERT_FALSE(empty < empty); - ASSERT_FALSE(empty < zero); - ASSERT_FALSE(empty < one); - ASSERT_FALSE(empty < positive); - ASSERT_FALSE(empty < negative); - ASSERT_FALSE(zero < empty); - ASSERT_FALSE(one < empty); - ASSERT_FALSE(positive < empty); - ASSERT_FALSE(negative < empty); - - ASSERT_TRUE(negative < zero); - ASSERT_FALSE(zero < zero); - ASSERT_FALSE(positive < zero); - ASSERT_FALSE(one < zero); - - ASSERT_TRUE(negative < one); - ASSERT_TRUE(zero < one); - ASSERT_FALSE(empty < one); - ASSERT_FALSE(positive < one); - - ASSERT_TRUE(YGFloatOptional{-INFINITY} < negative); - ASSERT_FALSE(empty < negative); -} - -TEST(YGFloatOptional, greater_equals) { - ASSERT_TRUE(empty >= empty); - ASSERT_FALSE(empty >= zero); - ASSERT_FALSE(empty >= one); - ASSERT_FALSE(empty >= positive); - ASSERT_FALSE(empty >= negative); - - ASSERT_TRUE(zero >= negative); - ASSERT_TRUE(zero >= zero); - ASSERT_FALSE(zero >= positive); - ASSERT_FALSE(zero >= one); - - ASSERT_TRUE(one >= negative); - ASSERT_TRUE(one >= zero); - ASSERT_FALSE(one >= empty); - ASSERT_FALSE(one >= positive); - - ASSERT_TRUE(negative >= YGFloatOptional{-INFINITY}); - ASSERT_TRUE(negative >= negative); - ASSERT_FALSE(negative >= empty); -} - -TEST(YGFloatOptional, lower_equals) { - ASSERT_TRUE(empty <= empty); - ASSERT_FALSE(zero <= empty); - ASSERT_FALSE(one <= empty); - ASSERT_FALSE(positive <= empty); - ASSERT_FALSE(negative <= empty); - - ASSERT_TRUE(negative <= zero); - ASSERT_TRUE(zero <= zero); - ASSERT_FALSE(positive <= zero); - ASSERT_FALSE(one <= zero); - - ASSERT_TRUE(negative <= one); - ASSERT_TRUE(zero <= one); - ASSERT_FALSE(empty <= one); - ASSERT_FALSE(positive <= one); - - ASSERT_TRUE(YGFloatOptional{-INFINITY} <= negative); - ASSERT_TRUE(negative <= negative); - ASSERT_FALSE(empty <= negative); -} - -TEST(YGFloatOptional, addition) { - ASSERT_EQ(zero + one, one); - ASSERT_EQ( - negative + positive, - YGFloatOptional{negative.unwrap() + positive.unwrap()}); - ASSERT_EQ(empty + zero, empty); - ASSERT_EQ(empty + empty, empty); - ASSERT_EQ(negative + empty, empty); -} - -TEST(YGFloatOptional, subtraction) { - ASSERT_EQ(zero - one, YGFloatOptional{-1.0f}); - ASSERT_EQ( - negative - positive, - YGFloatOptional{negative.unwrap() - positive.unwrap()}); - ASSERT_EQ(empty - zero, empty); - ASSERT_EQ(empty - empty, empty); - ASSERT_EQ(negative - empty, empty); -} - -TEST(YGFloatOptional, unary_minus) { - ASSERT_EQ(-zero, zero); - ASSERT_EQ(-negative, YGFloatOptional{-negative.unwrap()}); - ASSERT_EQ(-positive, YGFloatOptional{-positive.unwrap()}); - ASSERT_EQ(-empty, empty); -} - -TEST(YGFloatOptional, orElse) { - ASSERT_EQ(empty.orElse(1.23f), 1.23f); - ASSERT_TRUE(YGFloatIsUndefined(empty.orElse(YGUndefined))); - ASSERT_EQ(one.orElse(1.23f), 1.0f); -} - -TEST(YGFloatOptional, orElseGet) { - auto x = empty.orElseGet([] { return 1.23f; }); - ASSERT_EQ(x, 1.23f); - ASSERT_TRUE(YGFloatIsUndefined(empty.orElseGet([] { return YGUndefined; }))); - - auto y = one.orElseGet([] { return 1.23f; }); - ASSERT_EQ(y, 1.0f); -} diff --git a/tools/build_defs/oss/yoga_defs.bzl b/tools/build_defs/oss/yoga_defs.bzl index 5a5872fe..7eca7b9b 100644 --- a/tools/build_defs/oss/yoga_defs.bzl +++ b/tools/build_defs/oss/yoga_defs.bzl @@ -58,6 +58,7 @@ BASE_COMPILER_FLAGS = [ "-Wall", "-Werror", "-O3", + "-ffast-math", ] LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [ diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index b246f943..74cc38c9 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -55,14 +55,15 @@ float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } +float YGUnwrapFloatOptional(const YGFloatOptional& op) { + return op.isUndefined() ? YGUndefined : op.getValue(); +} + YGFloatOptional YGFloatOptionalMax( - const YGFloatOptional op1, - const YGFloatOptional op2) { - if (op1 > op2) { - return op1; - } - if (op2 > op1) { - return op2; + const YGFloatOptional& op1, + const YGFloatOptional& op2) { + if (!op1.isUndefined() && !op2.isUndefined()) { + return op1.getValue() > op2.getValue() ? op1 : op2; } return op1.isUndefined() ? op2 : op1; } diff --git a/yoga/Utils.h b/yoga/Utils.h index a0d49235..d578511c 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -57,12 +57,22 @@ bool YGValueEqual(const YGValue a, const YGValue b); // difference between two floats is less than 0.0001f or both are undefined. bool YGFloatsEqual(const float a, const float b); +// We need custom max function, since we want that, if one argument is +// YGUndefined then the max funtion should return the other argument as the max +// value. We wouldn't have needed a custom max function if YGUndefined was NAN +// as fmax has the same behaviour, but with NAN we cannot use `-ffast-math` +// compiler flag. float YGFloatMax(const float a, const float b); YGFloatOptional YGFloatOptionalMax( - const YGFloatOptional op1, - const YGFloatOptional op2); + const YGFloatOptional& op1, + const YGFloatOptional& op2); +// We need custom min function, since we want that, if one argument is +// YGUndefined then the min funtion should return the other argument as the min +// value. We wouldn't have needed a custom min function if YGUndefined was NAN +// as fmin has the same behaviour, but with NAN we cannot use `-ffast-math` +// compiler flag. float YGFloatMin(const float a, const float b); // This custom float comparision function compares the array of float with @@ -82,6 +92,11 @@ bool YGFloatArrayEqual( // This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise float YGFloatSanitize(const float val); +// This function unwraps optional and returns YGUndefined if not defined or +// op.value otherwise +// TODO: Get rid off this function +float YGUnwrapFloatOptional(const YGFloatOptional& op); + YGFlexDirection YGFlexDirectionCross( const YGFlexDirection flexDirection, const YGDirection direction); @@ -91,17 +106,18 @@ inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) { flexDirection == YGFlexDirectionRowReverse; } -inline YGFloatOptional YGResolveValue( - const YGValue value, - const float ownerSize) { +inline YGFloatOptional YGResolveValue(const YGValue value, const float ownerSize) { switch (value.unit) { + case YGUnitUndefined: + case YGUnitAuto: + return YGFloatOptional(); case YGUnitPoint: - return YGFloatOptional{value.value}; + return YGFloatOptional(value.value); case YGUnitPercent: - return YGFloatOptional{value.value * ownerSize * 0.01f}; - default: - return YGFloatOptional{}; + return YGFloatOptional( + static_cast(value.value * ownerSize * 0.01)); } + return YGFloatOptional(); } inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) { @@ -123,7 +139,7 @@ inline YGFlexDirection YGResolveFlexDirection( return flexDirection; } -inline YGFloatOptional YGResolveValueMargin( +static inline YGFloatOptional YGResolveValueMargin( const YGValue value, const float ownerSize) { return value.unit == YGUnitAuto ? YGFloatOptional(0) diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp new file mode 100644 index 00000000..d023dccb --- /dev/null +++ b/yoga/YGFloatOptional.cpp @@ -0,0 +1,83 @@ +/** + * 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 "YGFloatOptional.h" +#include +#include +#include "Yoga.h" +#include "Yoga-internal.h" + +using namespace facebook; + +YGFloatOptional::YGFloatOptional(float value) { + if (yoga::isUndefined(value)) { + isUndefined_ = true; + value_ = 0; + } else { + value_ = value; + isUndefined_ = false; + } +} + +float YGFloatOptional::getValue() const { + if (isUndefined_) { + // Abort, accessing a value of an undefined float optional + std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; + std::exit(EXIT_FAILURE); + } + return value_; +} + +bool YGFloatOptional::operator==(const YGFloatOptional& op) const { + if (isUndefined_ == op.isUndefined()) { + return isUndefined_ || value_ == op.getValue(); + } + return false; +} + +bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { + return !(*this == op); +} + +bool YGFloatOptional::operator==(float val) const { + if (yoga::isUndefined(val) == isUndefined_) { + return isUndefined_ || val == value_; + } + return false; +} + +bool YGFloatOptional::operator!=(float val) const { + return !(*this == val); +} + +YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) { + if (!isUndefined_ && !op.isUndefined_) { + return YGFloatOptional(value_ + op.value_); + } + return YGFloatOptional(); +} + +bool YGFloatOptional::operator>(const YGFloatOptional& op) const { + if (isUndefined_ || op.isUndefined_) { + return false; + } + return value_ > op.value_; +} + +bool YGFloatOptional::operator<(const YGFloatOptional& op) const { + if (isUndefined_ || op.isUndefined_) { + return false; + } + return value_ < op.value_; +} + +bool YGFloatOptional::operator>=(const YGFloatOptional& op) const { + return *this == op || *this > op; +} + +bool YGFloatOptional::operator<=(const YGFloatOptional& op) const { + return *this == op || *this < op; +} diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 3dd3d5c9..07fbb64b 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -6,68 +6,38 @@ */ #pragma once -#include -#include "Yoga-internal.h" - struct YGFloatOptional { private: - float value_ = std::numeric_limits::quiet_NaN(); + float value_ = 0; + bool isUndefined_ = true; public: - explicit constexpr YGFloatOptional(float value) : value_(value) {} - constexpr YGFloatOptional() = default; + explicit YGFloatOptional(float value); + YGFloatOptional() = default; - // returns the wrapped value, or a value x with YGIsUndefined(x) == true - constexpr float unwrap() const { - return value_; + // Program will terminate if the value of an undefined is accessed. Please + // make sure to check if the optional is defined before calling this function. + // To check if float optional is defined, use `isUndefined()`. + float getValue() const; + + // Sets the value of float optional, and thus isUndefined is assigned false. + void setValue(float val) { + value_ = val; + isUndefined_ = false; } - constexpr bool isUndefined() const { - // std::isnan is not constexpr - return !(value_ == value_); + bool isUndefined() const { + return isUndefined_; } - constexpr float orElse(float other) const { - return isUndefined() ? other : value_; - } + YGFloatOptional operator+(const YGFloatOptional& op); + bool operator>(const YGFloatOptional& op) const; + bool operator<(const YGFloatOptional& op) const; + bool operator>=(const YGFloatOptional& op) const; + bool operator<=(const YGFloatOptional& op) const; + bool operator==(const YGFloatOptional& op) const; + bool operator!=(const YGFloatOptional& op) const; - template - constexpr float orElseGet(Factory&& f) const { - return isUndefined() ? f() : value_; - } - - YGFloatOptional operator-() const { - return YGFloatOptional{-value_}; - } - YGFloatOptional operator+(YGFloatOptional op) const { - return YGFloatOptional{value_ + op.value_}; - } - YGFloatOptional operator-(YGFloatOptional op) const { - return YGFloatOptional{value_ - op.value_}; - } - bool operator>(YGFloatOptional op) const { - return value_ > op.value_; - } - bool operator<(YGFloatOptional op) const { - return value_ < op.value_; - } - bool operator>=(YGFloatOptional op) const { - return *this > op || *this == op; - } - bool operator<=(YGFloatOptional op) const { - return *this < op || *this == op; - } - bool operator==(YGFloatOptional op) const { - return value_ == op.value_ || (isUndefined() && op.isUndefined()); - } - bool operator!=(YGFloatOptional op) const { - return !(*this == op); - } - - bool operator==(float val) const { - return value_ == val || (isUndefined() && yoga::isUndefined(val)); - } - bool operator!=(float val) const { - return !(*this == val); - } + bool operator==(float val) const; + bool operator!=(float val) const; }; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 9ae03b01..1694692c 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -175,7 +175,7 @@ void YGNode::setLayoutLastOwnerDirection(YGDirection direction) { } void YGNode::setLayoutComputedFlexBasis( - const YGFloatOptional computedFlexBasis) { + const YGFloatOptional& computedFlexBasis) { layout_.computedFlexBasis = computedFlexBasis; } @@ -209,7 +209,11 @@ YGFloatOptional YGNode::relativePosition( return getLeadingPosition(axis, axisSize); } - return -getTrailingPosition(axis, axisSize); + YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize); + if (!trailingPosition.isUndefined()) { + trailingPosition.setValue(-1 * trailingPosition.getValue()); + } + return trailingPosition; } void YGNode::setPosition( @@ -232,18 +236,20 @@ void YGNode::setPosition( relativePosition(crossAxis, crossSize); setLayoutPosition( - (getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), + YGUnwrapFloatOptional( + getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain), leading[mainAxis]); setLayoutPosition( - (getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), + YGUnwrapFloatOptional( + getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain), trailing[mainAxis]); setLayoutPosition( - (getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross) - .unwrap(), + YGUnwrapFloatOptional( + getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross), leading[crossAxis]); setLayoutPosition( - (getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross) - .unwrap(), + YGUnwrapFloatOptional( + getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross), trailing[crossAxis]); } @@ -298,7 +304,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) { return flexBasis; } - if (style_.flex > YGFloatOptional{0.0f}) { + if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) { return config_->useWebDefaults ? YGValueAuto : YGValueZero; } return YGValueAuto; @@ -388,23 +394,27 @@ float YGNode::resolveFlexGrow() { if (owner_ == nullptr) { return 0.0; } - - return style_.flexGrow.orElseGet( - [this] { return style_.flex.orElse(kDefaultFlexGrow); }); + if (!style_.flexGrow.isUndefined()) { + return style_.flexGrow.getValue(); + } + if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) { + return style_.flex.getValue(); + } + return kDefaultFlexGrow; } float YGNode::resolveFlexShrink() { if (owner_ == nullptr) { return 0.0; } - return style_.flexShrink.orElseGet([this] { - if (style_.flex < YGFloatOptional{0.0f} && !config_->useWebDefaults) { - return -style_.flex.unwrap(); - } else { - return config_->useWebDefaults ? kWebDefaultFlexShrink - : kDefaultFlexShrink; - } - }); + if (!style_.flexShrink.isUndefined()) { + return style_.flexShrink.getValue(); + } + if (!config_->useWebDefaults && !style_.flex.isUndefined() && + style_.flex.getValue() < 0.0f) { + return -style_.flex.getValue(); + } + return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink; } bool YGNode::isNodeFlexible() { @@ -443,9 +453,11 @@ float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { YGFloatOptional YGNode::getLeadingPadding( const YGFlexDirection axis, const float widthSize) const { - const YGFloatOptional paddingEdgeStart = + const YGFloatOptional& paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); - if (YGFlexDirectionIsRow(axis) && paddingEdgeStart >= YGFloatOptional{0.0f}) { + if (YGFlexDirectionIsRow(axis) && + style_.padding[YGEdgeStart].unit != YGUnitUndefined && + !paddingEdgeStart.isUndefined() && paddingEdgeStart.getValue() >= 0.0f) { return paddingEdgeStart; } @@ -458,10 +470,11 @@ YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getTrailingPadding( const YGFlexDirection axis, const float widthSize) const { - const YGFloatOptional paddingEdgeEnd = - YGResolveValue(style_.padding[YGEdgeEnd], widthSize); - if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) { - return paddingEdgeEnd; + if (YGFlexDirectionIsRow(axis) && + style_.padding[YGEdgeEnd].unit != YGUnitUndefined && + !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() && + YGResolveValue(style_.padding[YGEdgeEnd], widthSize).getValue() >= 0.0f) { + return YGResolveValue(style_.padding[YGEdgeEnd], widthSize); } YGFloatOptional resolvedValue = YGResolveValue( diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 57312812..719eb2ea 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -235,7 +235,7 @@ struct YGNode { void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); - void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis); + void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis); void setLayoutComputedFlexBasisGeneration( uint32_t computedFlexBasisGeneration); void setLayoutMeasuredDimension(float measuredDimension, int index); diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 753a00b6..541a6fef 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -14,9 +14,9 @@ namespace facebook { namespace yoga { typedef std::string string; -static void indent(string& base, uint32_t level) { +static void indent(string* base, uint32_t level) { for (uint32_t i = 0; i < level; ++i) { - base.append(" "); + base->append(" "); } } @@ -25,7 +25,7 @@ static bool areFourValuesEqual(const std::array& four) { YGValueEqual(four[0], four[3]); } -static void appendFormatedString(string& str, const char* fmt, ...) { +static void appendFormatedString(string* str, const char* fmt, ...) { va_list args; va_start(args, fmt); va_list argsCopy; @@ -35,25 +35,25 @@ static void appendFormatedString(string& str, const char* fmt, ...) { vsnprintf(buf.data(), buf.size(), fmt, argsCopy); va_end(argsCopy); string result = string(buf.begin(), buf.end() - 1); - str.append(result); + str->append(result); } static void appendFloatOptionalIfDefined( - string& base, + string* base, const string key, const YGFloatOptional num) { if (!num.isUndefined()) { - appendFormatedString(base, "%s: %g; ", key.c_str(), num.unwrap()); + appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue()); } } static void appendNumberIfNotUndefined( - string& base, + string* base, const string key, const YGValue number) { if (number.unit != YGUnitUndefined) { if (number.unit == YGUnitAuto) { - base.append(key + ": auto; "); + base->append(key + ": auto; "); } else { string unit = number.unit == YGUnitPoint ? "px" : "%%"; appendFormatedString( @@ -63,23 +63,24 @@ static void appendNumberIfNotUndefined( } static void -appendNumberIfNotAuto(string& base, const string& key, const YGValue number) { +appendNumberIfNotAuto(string* base, const string& key, const YGValue number) { if (number.unit != YGUnitAuto) { appendNumberIfNotUndefined(base, key, number); } } static void -appendNumberIfNotZero(string& base, const string& str, const YGValue number) { +appendNumberIfNotZero(string* base, const string& str, const YGValue number) { + if (number.unit == YGUnitAuto) { - base.append(str + ": auto; "); + base->append(str + ": auto; "); } else if (!YGFloatsEqual(number.value, 0)) { appendNumberIfNotUndefined(base, str, number); } } static void appendEdges( - string& base, + string* base, const string& key, const std::array& edges) { if (areFourValuesEqual(edges)) { @@ -93,7 +94,7 @@ static void appendEdges( } static void appendEdgeIfNotUndefined( - string& base, + string* base, const string& str, const std::array& edges, const YGEdge edge) { @@ -102,7 +103,7 @@ static void appendEdgeIfNotUndefined( } void YGNodeToString( - std::string& str, + std::string* str, YGNodeRef node, YGPrintOptions options, uint32_t level) { diff --git a/yoga/YGNodePrint.h b/yoga/YGNodePrint.h index 9615bf8e..9d36ba8d 100644 --- a/yoga/YGNodePrint.h +++ b/yoga/YGNodePrint.h @@ -13,7 +13,7 @@ namespace facebook { namespace yoga { void YGNodeToString( - std::string& str, + std::string* str, YGNodeRef node, YGPrintOptions options, uint32_t level); diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index a2f4a17e..bc90463e 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -8,8 +8,8 @@ // Yoga specific properties, not compatible with flexbox specification bool YGStyle::operator==(const YGStyle& style) { - return ( - direction == style.direction && flexDirection == style.flexDirection && + bool areNonFloatValuesEqual = direction == style.direction && + flexDirection == style.flexDirection && justifyContent == style.justifyContent && alignContent == style.alignContent && alignItems == style.alignItems && alignSelf == style.alignSelf && positionType == style.positionType && @@ -21,7 +21,34 @@ bool YGStyle::operator==(const YGStyle& style) { YGValueArrayEqual(border, style.border) && YGValueArrayEqual(dimensions, style.dimensions) && YGValueArrayEqual(minDimensions, style.minDimensions) && - YGValueArrayEqual(maxDimensions, style.maxDimensions) && - flex == style.flex && flexGrow == style.flexGrow && - flexShrink == style.flexShrink && aspectRatio == style.aspectRatio); + YGValueArrayEqual(maxDimensions, style.maxDimensions); + + areNonFloatValuesEqual = + areNonFloatValuesEqual && flex.isUndefined() == style.flex.isUndefined(); + if (areNonFloatValuesEqual && !flex.isUndefined() && + !style.flex.isUndefined()) { + areNonFloatValuesEqual = + areNonFloatValuesEqual && flex.getValue() == style.flex.getValue(); + } + + areNonFloatValuesEqual = areNonFloatValuesEqual && + flexGrow.isUndefined() == style.flexGrow.isUndefined(); + if (areNonFloatValuesEqual && !flexGrow.isUndefined()) { + areNonFloatValuesEqual = areNonFloatValuesEqual && + flexGrow.getValue() == style.flexGrow.getValue(); + } + + areNonFloatValuesEqual = areNonFloatValuesEqual && + flexShrink.isUndefined() == style.flexShrink.isUndefined(); + if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) { + areNonFloatValuesEqual = areNonFloatValuesEqual && + flexShrink.getValue() == style.flexShrink.getValue(); + } + + if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) { + areNonFloatValuesEqual = areNonFloatValuesEqual && + aspectRatio.getValue() == style.aspectRatio.getValue(); + } + + return areNonFloatValuesEqual; } diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index c4f7e3c7..c3a01d44 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -30,16 +30,16 @@ constexpr std::array kYGDefaultDimensionValuesUnit = { struct YGStyle { using Dimensions = std::array; - YGDirection direction : 2; - YGFlexDirection flexDirection : 2; - YGJustify justifyContent : 3; - YGAlign alignContent : 3; - YGAlign alignItems : 3; - YGAlign alignSelf : 3; - YGPositionType positionType : 1; - YGWrap flexWrap : 2; - YGOverflow overflow : 2; - YGDisplay display : 1; + YGDirection direction = YGDirectionInherit; + YGFlexDirection flexDirection = YGFlexDirectionColumn; + YGJustify justifyContent = YGJustifyFlexStart; + YGAlign alignContent = YGAlignFlexStart; + YGAlign alignItems = YGAlignStretch; + YGAlign alignSelf = YGAlignAuto; + YGPositionType positionType = YGPositionTypeRelative; + YGWrap flexWrap = YGWrapNoWrap; + YGOverflow overflow = YGOverflowVisible; + YGDisplay display = YGDisplayFlex; YGFloatOptional flex = {}; YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; @@ -54,17 +54,7 @@ struct YGStyle { // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio = {}; - YGStyle() - : direction(YGDirectionInherit), - flexDirection(YGFlexDirectionColumn), - justifyContent(YGJustifyFlexStart), - alignContent(YGAlignFlexStart), - alignItems(YGAlignStretch), - alignSelf(YGAlignAuto), - positionType(YGPositionTypeRelative), - flexWrap(YGWrapNoWrap), - overflow(YGOverflowVisible), - display(YGDisplayFlex) {} + YGStyle() = default; bool operator==(const YGStyle& style); bool operator!=(YGStyle style) { diff --git a/yoga/YGValue.cpp b/yoga/YGValue.cpp deleted file mode 100644 index fcdd0c69..00000000 --- a/yoga/YGValue.cpp +++ /dev/null @@ -1,11 +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 "YGValue.h" - -const YGValue YGValueZero = {0, YGUnitPoint}; -const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; -const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; diff --git a/yoga/YGValue.h b/yoga/YGValue.h deleted file mode 100644 index 4e43f7b2..00000000 --- a/yoga/YGValue.h +++ /dev/null @@ -1,56 +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 -#include "YGEnums.h" -#include "YGMacros.h" - -YG_EXTERN_C_BEGIN - -// Not defined in MSVC++ -#ifndef NAN -static const uint32_t __nan = 0x7fc00000; -#define NAN (*(const float*)__nan) -#endif - -#define YGUndefined NAN - -typedef struct YGValue { - float value; - YGUnit unit; -} YGValue; - -extern const YGValue YGValueAuto; -extern const YGValue YGValueUndefined; -extern const YGValue YGValueZero; - -YG_EXTERN_C_END - -#ifdef __cplusplus - -inline bool operator==(const YGValue& lhs, const YGValue& rhs) { - if (lhs.unit != rhs.unit) { - return false; - } - - switch (lhs.unit) { - case YGUnitUndefined: - case YGUnitAuto: - return true; - case YGUnitPoint: - case YGUnitPercent: - default: - return lhs.value == rhs.value; - } -} - -inline bool operator!=(const YGValue& lhs, const YGValue& rhs) { - return !(lhs == rhs); -} - -#endif diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index ef5e5d8c..1e9a1aaf 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -27,7 +27,15 @@ namespace facebook { namespace yoga { inline bool isUndefined(float value) { - return std::isnan(value); + // Value of a float in the case of it being not defined is 10.1E20. Earlier + // it used to be NAN, the benefit of which was that if NAN is involved in any + // mathematical expression the result was NAN. But since we want to have + // `-ffast-math` flag being used by compiler which assumes that the floating + // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But + // now if YGUndefined is involved in any mathematical operations this + // value(10.1E20) would change. So the following check makes sure that if the + // value is outside a range (-10E8, 10E8) then it is undefined. + return value >= 10E8 || value <= -10E8; } } // namespace yoga diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index f0327f87..6abfb7d3 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -18,7 +18,10 @@ /* define fmaxf if < VC12 */ #if _MSC_VER < 1800 __forceinline const float fmaxf(const float a, const float b) { - return (a > b) ? a : b; + if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + return (a > b) ? a : b; + } + return YGFloatIsUndefined(a) ? b : a; } #endif #endif @@ -39,6 +42,23 @@ static int YGDefaultLog( va_list args); #endif +const YGValue YGValueZero = {0, YGUnitPoint}; +const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; +const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; + +bool operator==(const YGValue& lhs, const YGValue& rhs) { + if ((lhs.unit == YGUnitUndefined && rhs.unit == YGUnitUndefined) || + (lhs.unit == YGUnitAuto && rhs.unit == YGUnitAuto)) { + return true; + } + + return lhs.unit == rhs.unit && lhs.value == rhs.value; +} + +bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} + #ifdef ANDROID #include static int YGAndroidLog( @@ -579,18 +599,33 @@ void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) { } float YGNodeStyleGetFlexGrow(const YGNodeRef node) { - return node->getStyle().flexGrow.orElse(kDefaultFlexGrow); + return node->getStyle().flexGrow.isUndefined() + ? kDefaultFlexGrow + : node->getStyle().flexGrow.getValue(); } float YGNodeStyleGetFlexShrink(const YGNodeRef node) { - return node->getStyle().flexShrink.orElseGet([node] { - return node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink - : kDefaultFlexShrink; - }); + return node->getStyle().flexShrink.isUndefined() + ? (node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink + : kDefaultFlexShrink) + : node->getStyle().flexShrink.getValue(); } namespace { +template +struct StyleProp { + static T get(YGNodeRef node) { + return node->getStyle().*P; + } + static void set(YGNodeRef node, T newValue) { + if (node->getStyle().*P != newValue) { + node->getStyle().*P = newValue; + node->markDirtyAndPropogate(); + } + } +}; + struct Value { template static YGValue create(float value) { @@ -750,88 +785,84 @@ struct DimensionProp { return node->getLayout().instanceName[edge]; \ } -#define YG_NODE_STYLE_SET(node, property, value) \ - if (node->getStyle().property != value) { \ - node->getStyle().property = value; \ - node->markDirtyAndPropogate(); \ - } - -void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { - YG_NODE_STYLE_SET(node, direction, value); +void YGNodeStyleSetDirection( + const YGNodeRef node, + const YGDirection direction) { + StyleProp::set(node, direction); } YGDirection YGNodeStyleGetDirection(const YGNodeRef node) { - return node->getStyle().direction; + return StyleProp::get(node); } void YGNodeStyleSetFlexDirection( const YGNodeRef node, const YGFlexDirection flexDirection) { - YG_NODE_STYLE_SET(node, flexDirection, flexDirection); + StyleProp::set(node, flexDirection); } YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node) { - return node->getStyle().flexDirection; + return StyleProp::get(node); } void YGNodeStyleSetJustifyContent( const YGNodeRef node, const YGJustify justifyContent) { - YG_NODE_STYLE_SET(node, justifyContent, justifyContent); + StyleProp::set(node, justifyContent); } YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node) { - return node->getStyle().justifyContent; + return StyleProp::get(node); } void YGNodeStyleSetAlignContent( const YGNodeRef node, const YGAlign alignContent) { - YG_NODE_STYLE_SET(node, alignContent, alignContent); + StyleProp::set(node, alignContent); } YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node) { - return node->getStyle().alignContent; + return StyleProp::get(node); } void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { - YG_NODE_STYLE_SET(node, alignItems, alignItems); + StyleProp::set(node, alignItems); } YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node) { - return node->getStyle().alignItems; + return StyleProp::get(node); } void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { - YG_NODE_STYLE_SET(node, alignSelf, alignSelf); + StyleProp::set(node, alignSelf); } YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node) { - return node->getStyle().alignSelf; + return StyleProp::get(node); } void YGNodeStyleSetPositionType( const YGNodeRef node, const YGPositionType positionType) { - YG_NODE_STYLE_SET(node, positionType, positionType); + StyleProp::set(node, positionType); } YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node) { - return node->getStyle().positionType; + return StyleProp::get(node); } void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { - YG_NODE_STYLE_SET(node, flexWrap, flexWrap); + StyleProp::set(node, flexWrap); } YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node) { - return node->getStyle().flexWrap; + return StyleProp::get(node); } void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { - YG_NODE_STYLE_SET(node, overflow, overflow); + StyleProp::set(node, overflow); } YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node) { - return node->getStyle().overflow; + return StyleProp::get(node); } void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { - YG_NODE_STYLE_SET(node, display, display); + StyleProp::set(node, display); } YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) { - return node->getStyle().display; + return StyleProp::get(node); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -845,7 +876,8 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { // TODO(T26792433): Change the API to accept YGFloatOptional. float YGNodeStyleGetFlex(const YGNodeRef node) { - return node->getStyle().flex.orElse(YGUndefined); + return node->getStyle().flex.isUndefined() ? YGUndefined + : node->getStyle().flex.getValue(); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -947,7 +979,7 @@ float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) { // TODO(T26792433): Change the API to accept YGFloatOptional. float YGNodeStyleGetAspectRatio(const YGNodeRef node) { const YGFloatOptional op = node->getStyle().aspectRatio; - return op.orElse(YGUndefined); + return op.isUndefined() ? YGUndefined : op.getValue(); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -1057,7 +1089,7 @@ static void YGNodePrintInternal( const YGNodeRef node, const YGPrintOptions options) { std::string str; - facebook::yoga::YGNodeToString(str, node, options, 0); + facebook::yoga::YGNodeToString(&str, node, options, 0); YGLog(node, YGLogLevelDebug, str.c_str()); } @@ -1084,9 +1116,9 @@ static inline float YGNodePaddingAndBorderForAxis( const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return (node->getLeadingPaddingAndBorder(axis, widthSize) + - node->getTrailingPaddingAndBorder(axis, widthSize)) - .unwrap(); + return YGUnwrapFloatOptional( + node->getLeadingPaddingAndBorder(axis, widthSize) + + node->getTrailingPaddingAndBorder(axis, widthSize)); } static inline YGAlign YGNodeAlignItem( @@ -1168,9 +1200,9 @@ static inline float YGNodeDimWithMargin( const YGFlexDirection axis, const float widthSize) { return node->getLayout().measuredDimensions[dim[axis]] + - (node->getLeadingMargin(axis, widthSize) + - node->getTrailingMargin(axis, widthSize)) - .unwrap(); + YGUnwrapFloatOptional( + node->getLeadingMargin(axis, widthSize) + + node->getTrailingMargin(axis, widthSize)); } static inline bool YGNodeIsStyleDimDefined( @@ -1200,7 +1232,7 @@ static inline bool YGNodeIsLayoutDimDefined( static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( const YGNodeRef node, const YGFlexDirection axis, - const YGFloatOptional value, + const float value, const float axisSize) { YGFloatOptional min; YGFloatOptional max; @@ -1217,15 +1249,15 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( node->getStyle().maxDimensions[YGDimensionWidth], axisSize); } - if (max >= YGFloatOptional{0} && value > max) { + if (!max.isUndefined() && max.getValue() >= 0 && value > max.getValue()) { return max; } - if (min >= YGFloatOptional{0} && value < min) { + if (!min.isUndefined() && min.getValue() >= 0 && value < min.getValue()) { return min; } - return value; + return YGFloatOptional(value); } // Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't @@ -1237,9 +1269,8 @@ static inline float YGNodeBoundAxis( const float axisSize, const float widthSize) { return YGFloatMax( - (YGNodeBoundAxisWithinMinAndMax( - node, axis, YGFloatOptional{value}, axisSize)) - .unwrap(), + YGUnwrapFloatOptional( + YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } @@ -1267,14 +1298,14 @@ static void YGConstrainMaxSizeForMode( switch (*mode) { case YGMeasureModeExactly: case YGMeasureModeAtMost: - if (YGFloatOptional{*size} > maxSize) { - *size = maxSize.unwrap(); - } + *size = (maxSize.isUndefined() || *size < maxSize.getValue()) + ? *size + : maxSize.getValue(); break; case YGMeasureModeUndefined: if (!maxSize.isUndefined()) { *mode = YGMeasureModeAtMost; - *size = maxSize.unwrap(); + *size = maxSize.getValue(); } break; } @@ -1315,14 +1346,14 @@ static void YGNodeComputeFlexBasisForChild( child->getConfig(), YGExperimentalFeatureWebFlexBasis) && child->getLayout().computedFlexBasisGeneration != gCurrentGenerationCount)) { - const YGFloatOptional paddingAndBorder = YGFloatOptional( + const YGFloatOptional& paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)); child->setLayoutComputedFlexBasis( YGFloatOptionalMax(resolvedFlexBasis, paddingAndBorder)); } } else if (isMainAxisRow && isRowStyleDimDefined) { // The width is definite, so use that as the flex basis. - const YGFloatOptional paddingAndBorder = YGFloatOptional( + const YGFloatOptional& paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, ownerWidth)); child->setLayoutComputedFlexBasis(YGFloatOptionalMax( @@ -1331,7 +1362,7 @@ static void YGNodeComputeFlexBasisForChild( paddingAndBorder)); } else if (!isMainAxisRow && isColumnStyleDimDefined) { // The height is definite, so use that as the flex basis. - const YGFloatOptional paddingAndBorder = + const YGFloatOptional& paddingAndBorder = YGFloatOptional(YGNodePaddingAndBorderForAxis( child, YGFlexDirectionColumn, ownerWidth)); child->setLayoutComputedFlexBasis(YGFloatOptionalMax( @@ -1346,24 +1377,22 @@ static void YGNodeComputeFlexBasisForChild( childWidthMeasureMode = YGMeasureModeUndefined; childHeightMeasureMode = YGMeasureModeUndefined; - auto marginRow = - (child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); - auto marginColumn = - (child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); + auto marginRow = YGUnwrapFloatOptional( + child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + auto marginColumn = YGUnwrapFloatOptional( + child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); if (isRowStyleDimDefined) { childWidth = - (YGResolveValue( - child->getResolvedDimension(YGDimensionWidth), ownerWidth)) - .unwrap() + + YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionWidth), ownerWidth)) + marginRow; childWidthMeasureMode = YGMeasureModeExactly; } if (isColumnStyleDimDefined) { childHeight = - (YGResolveValue( - child->getResolvedDimension(YGDimensionHeight), ownerHeight)) - .unwrap() + + YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionHeight), ownerHeight)) + marginColumn; childHeightMeasureMode = YGMeasureModeExactly; } @@ -1386,15 +1415,16 @@ static void YGNodeComputeFlexBasisForChild( } } - auto hasAspectRatio = !child->getStyle().aspectRatio.isUndefined(); - auto aspectRatio = child->getStyle().aspectRatio.unwrap(); - if (hasAspectRatio) { + if (!child->getStyle().aspectRatio.isUndefined()) { if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) { - childHeight = marginColumn + (childWidth - marginRow) / aspectRatio; + childHeight = marginColumn + + (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); childHeightMeasureMode = YGMeasureModeExactly; } else if ( isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { - childWidth = marginRow + (childHeight - marginColumn) * aspectRatio; + childWidth = marginRow + + (childHeight - marginColumn) * + child->getStyle().aspectRatio.getValue(); childWidthMeasureMode = YGMeasureModeExactly; } } @@ -1412,8 +1442,9 @@ static void YGNodeComputeFlexBasisForChild( childWidthStretch) { childWidth = width; childWidthMeasureMode = YGMeasureModeExactly; - if (hasAspectRatio) { - childHeight = (childWidth - marginRow) / aspectRatio; + if (!child->getStyle().aspectRatio.isUndefined()) { + childHeight = + (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); childHeightMeasureMode = YGMeasureModeExactly; } } @@ -1428,8 +1459,9 @@ static void YGNodeComputeFlexBasisForChild( childHeight = height; childHeightMeasureMode = YGMeasureModeExactly; - if (hasAspectRatio) { - childWidth = (childHeight - marginColumn) * aspectRatio; + if (!child->getStyle().aspectRatio.isUndefined()) { + childWidth = (childHeight - marginColumn) * + child->getStyle().aspectRatio.getValue(); childWidthMeasureMode = YGMeasureModeExactly; } } @@ -1489,14 +1521,13 @@ static void YGNodeAbsoluteLayoutChild( YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; auto marginRow = - (child->getMarginForAxis(YGFlexDirectionRow, width)).unwrap(); - auto marginColumn = - (child->getMarginForAxis(YGFlexDirectionColumn, width)).unwrap(); + YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width)); + auto marginColumn = YGUnwrapFloatOptional( + child->getMarginForAxis(YGFlexDirectionColumn, width)); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { - childWidth = - (YGResolveValue(child->getResolvedDimension(YGDimensionWidth), width)) - .unwrap() + + childWidth = YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionWidth), width)) + marginRow; } else { // If the child doesn't have a specified width, compute the width based @@ -1507,18 +1538,17 @@ static void YGNodeAbsoluteLayoutChild( childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] - (node->getLeadingBorder(YGFlexDirectionRow) + node->getTrailingBorder(YGFlexDirectionRow)) - - (child->getLeadingPosition(YGFlexDirectionRow, width) + - child->getTrailingPosition(YGFlexDirectionRow, width)) - .unwrap(); + YGUnwrapFloatOptional( + child->getLeadingPosition(YGFlexDirectionRow, width) + + child->getTrailingPosition(YGFlexDirectionRow, width)); childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) { - childHeight = - (YGResolveValue(child->getResolvedDimension(YGDimensionHeight), height)) - .unwrap() + + childHeight = YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionHeight), height)) + marginColumn; } else { // If the child doesn't have a specified height, compute the height @@ -1526,12 +1556,13 @@ static void YGNodeAbsoluteLayoutChild( // offsets if they're defined. if (child->isLeadingPositionDefined(YGFlexDirectionColumn) && child->isTrailingPosDefined(YGFlexDirectionColumn)) { - childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] - + childHeight = + node->getLayout().measuredDimensions[YGDimensionHeight] - (node->getLeadingBorder(YGFlexDirectionColumn) + node->getTrailingBorder(YGFlexDirectionColumn)) - - (child->getLeadingPosition(YGFlexDirectionColumn, height) + - child->getTrailingPosition(YGFlexDirectionColumn, height)) - .unwrap(); + YGUnwrapFloatOptional( + child->getLeadingPosition(YGFlexDirectionColumn, height) + + child->getTrailingPosition(YGFlexDirectionColumn, height)); childHeight = YGNodeBoundAxis( child, YGFlexDirectionColumn, childHeight, height, width); } @@ -1542,11 +1573,13 @@ static void YGNodeAbsoluteLayoutChild( // flexible. if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) { if (!child->getStyle().aspectRatio.isUndefined()) { - auto aspectRatio = child->getStyle().aspectRatio.unwrap(); if (YGFloatIsUndefined(childWidth)) { - childWidth = marginRow + (childHeight - marginColumn) * aspectRatio; + childWidth = marginRow + + (childHeight - marginColumn) * + child->getStyle().aspectRatio.getValue(); } else if (YGFloatIsUndefined(childHeight)) { - childHeight = marginColumn + (childWidth - marginRow) / aspectRatio; + childHeight = marginColumn + + (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); } } } @@ -1584,9 +1617,11 @@ static void YGNodeAbsoluteLayoutChild( "abs-measure", config); childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + - (child->getMarginForAxis(YGFlexDirectionRow, width)).unwrap(); + YGUnwrapFloatOptional( + child->getMarginForAxis(YGFlexDirectionRow, width)); childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] + - (child->getMarginForAxis(YGFlexDirectionColumn, width)).unwrap(); + YGUnwrapFloatOptional( + child->getMarginForAxis(YGFlexDirectionColumn, width)); } YGLayoutNodeInternal( @@ -1608,10 +1643,9 @@ static void YGNodeAbsoluteLayoutChild( node->getLayout().measuredDimensions[dim[mainAxis]] - child->getLayout().measuredDimensions[dim[mainAxis]] - node->getTrailingBorder(mainAxis) - - (child->getTrailingMargin(mainAxis, width)).unwrap() - - (child->getTrailingPosition( - mainAxis, isMainAxisRow ? width : height)) - .unwrap(), + YGUnwrapFloatOptional(child->getTrailingMargin(mainAxis, width)) - + YGUnwrapFloatOptional(child->getTrailingPosition( + mainAxis, isMainAxisRow ? width : height)), leading[mainAxis]); } else if ( !child->isLeadingPositionDefined(mainAxis) && @@ -1636,10 +1670,9 @@ static void YGNodeAbsoluteLayoutChild( node->getLayout().measuredDimensions[dim[crossAxis]] - child->getLayout().measuredDimensions[dim[crossAxis]] - node->getTrailingBorder(crossAxis) - - (child->getTrailingMargin(crossAxis, width)).unwrap() - - (child->getTrailingPosition( - crossAxis, isMainAxisRow ? height : width)) - .unwrap(), + YGUnwrapFloatOptional(child->getTrailingMargin(crossAxis, width)) - + YGUnwrapFloatOptional(child->getTrailingPosition( + crossAxis, isMainAxisRow ? height : width)), leading[crossAxis]); } else if ( @@ -1678,10 +1711,10 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis( node, YGFlexDirectionColumn, availableWidth); - const float marginAxisRow = - (node->getMarginForAxis(YGFlexDirectionRow, availableWidth)).unwrap(); - const float marginAxisColumn = - (node->getMarginForAxis(YGFlexDirectionColumn, availableWidth)).unwrap(); + const float marginAxisRow = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionRow, availableWidth)); + const float marginAxisColumn = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionColumn, availableWidth)); // We want to make sure we don't call measure with negative size const float innerWidth = YGFloatIsUndefined(availableWidth) @@ -1756,10 +1789,10 @@ static void YGNodeEmptyContainerSetMeasuredDimensions( YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, ownerWidth); - const float marginAxisRow = - (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); - const float marginAxisColumn = - (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); + const float marginAxisRow = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + const float marginAxisColumn = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); node->setLayoutMeasuredDimension( YGNodeBoundAxis( @@ -1800,10 +1833,10 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { - auto marginAxisColumn = - (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); - auto marginAxisRow = - (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); + auto marginAxisColumn = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + auto marginAxisRow = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); node->setLayoutMeasuredDimension( YGNodeBoundAxis( @@ -1859,7 +1892,8 @@ static float YGNodeCalculateAvailableInnerDim( YGDimension dimension = YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight; - const float margin = (node->getMarginForAxis(direction, ownerDim)).unwrap(); + const float margin = + YGUnwrapFloatOptional(node->getMarginForAxis(direction, ownerDim)); const float paddingAndBorder = YGNodePaddingAndBorderForAxis(node, direction, ownerDim); @@ -1871,15 +1905,16 @@ static float YGNodeCalculateAvailableInnerDim( // constraints const YGFloatOptional minDimensionOptional = YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); - const float minInnerDim = - (minDimensionOptional - YGFloatOptional{paddingAndBorder}).orElse(0.0f); + const float minInnerDim = minDimensionOptional.isUndefined() + ? 0.0f + : minDimensionOptional.getValue() - paddingAndBorder; const YGFloatOptional maxDimensionOptional = YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim); - const float maxInnerDim = - (maxDimensionOptional - YGFloatOptional{paddingAndBorder}) - .orElse(FLT_MAX); + const float maxInnerDim = maxDimensionOptional.isUndefined() + ? FLT_MAX + : maxDimensionOptional.getValue() - paddingAndBorder; availableInnerDim = YGFloatMax(YGFloatMin(availableInnerDim, maxInnerDim), minInnerDim); } @@ -1963,10 +1998,9 @@ static float YGNodeComputeFlexBasisForChildren( config); } - totalOuterFlexBasis += - (child->getLayout().computedFlexBasis + - child->getMarginForAxis(mainAxis, availableInnerWidth)) - .unwrap(); + totalOuterFlexBasis += YGUnwrapFloatOptional( + child->getLayout().computedFlexBasis + + child->getMarginForAxis(mainAxis, availableInnerWidth)); } return totalOuterFlexBasis; @@ -2001,15 +2035,14 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( continue; } child->setLineIndex(lineCount); - const float childMarginMainAxis = - (child->getMarginForAxis(mainAxis, availableInnerWidth)).unwrap(); + const float childMarginMainAxis = YGUnwrapFloatOptional( + child->getMarginForAxis(mainAxis, availableInnerWidth)); const float flexBasisWithMinAndMaxConstraints = - (YGNodeBoundAxisWithinMinAndMax( - child, - mainAxis, - child->getLayout().computedFlexBasis, - mainAxisownerSize)) - .unwrap(); + YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + child, + mainAxis, + YGUnwrapFloatOptional(child->getLayout().computedFlexBasis), + mainAxisownerSize)); // If this is a multi-line flow and this item pushes us over the // available size, we've @@ -2035,7 +2068,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( // child dimension. flexAlgoRowMeasurement.totalFlexShrinkScaledFactors += -child->resolveFlexShrink() * - (child->getLayout().computedFlexBasis).unwrap(); + YGUnwrapFloatOptional(child->getLayout().computedFlexBasis); } flexAlgoRowMeasurement.relativeChildren.push_back(child); @@ -2082,12 +2115,12 @@ static float YGDistributeFreeSpaceSecondPass( const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - childFlexBasis = (YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - currentRelativeChild->getLayout().computedFlexBasis, - mainAxisownerSize)) - .unwrap(); + childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + YGUnwrapFloatOptional( + currentRelativeChild->getLayout().computedFlexBasis), + mainAxisownerSize)); float updatedMainSize = childFlexBasis; if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && @@ -2137,12 +2170,10 @@ static float YGDistributeFreeSpaceSecondPass( deltaFreeSpace += updatedMainSize - childFlexBasis; - const float marginMain = - (currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth)) - .unwrap(); - const float marginCross = - (currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth)) - .unwrap(); + const float marginMain = YGUnwrapFloatOptional( + currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth)); + const float marginCross = YGUnwrapFloatOptional( + currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth)); float childCrossSize; float childMainSize = updatedMainSize + marginMain; @@ -2151,9 +2182,9 @@ static float YGDistributeFreeSpaceSecondPass( if (!currentRelativeChild->getStyle().aspectRatio.isUndefined()) { childCrossSize = isMainAxisRow ? (childMainSize - marginMain) / - currentRelativeChild->getStyle().aspectRatio.unwrap() + currentRelativeChild->getStyle().aspectRatio.getValue() : (childMainSize - marginMain) * - currentRelativeChild->getStyle().aspectRatio.unwrap(); + currentRelativeChild->getStyle().aspectRatio.getValue(); childCrossMeasureMode = YGMeasureModeExactly; childCrossSize += marginCross; @@ -2178,10 +2209,9 @@ static float YGDistributeFreeSpaceSecondPass( : YGMeasureModeAtMost; } else { childCrossSize = - (YGResolveValue( - currentRelativeChild->getResolvedDimension(dim[crossAxis]), - availableInnerCrossDim)) - .unwrap() + + YGUnwrapFloatOptional(YGResolveValue( + currentRelativeChild->getResolvedDimension(dim[crossAxis]), + availableInnerCrossDim)) + marginCross; const bool isLoosePercentageMeasurement = currentRelativeChild->getResolvedDimension(dim[crossAxis]).unit == @@ -2261,13 +2291,12 @@ static void YGDistributeFreeSpaceFirstPass( float deltaFreeSpace = 0; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - float childFlexBasis = - (YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - currentRelativeChild->getLayout().computedFlexBasis, - mainAxisownerSize)) - .unwrap(); + float childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + YGUnwrapFloatOptional( + currentRelativeChild->getLayout().computedFlexBasis), + mainAxisownerSize)); if (collectedFlexItemsValues.remainingFreeSpace < 0) { flexShrinkScaledFactor = @@ -2418,10 +2447,10 @@ static void YGJustifyMainAxis( const float availableInnerWidth, const bool performLayout) { const YGStyle& style = node->getStyle(); - const float leadingPaddingAndBorderMain = - (node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)).unwrap(); - const float trailingPaddingAndBorderMain = - (node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)).unwrap(); + const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( + node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); + const float trailingPaddingAndBorderMain = YGUnwrapFloatOptional( + node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)); // If we are using "at most" rules in the main axis, make sure that // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && @@ -2437,9 +2466,8 @@ static void YGJustifyMainAxis( // `minAvailableMainDim` denotes minimum available space in which child // can be laid out, it will exclude space consumed by padding and border. const float minAvailableMainDim = - (YGResolveValue( - style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - .unwrap() - + YGUnwrapFloatOptional(YGResolveValue( + style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - leadingPaddingAndBorderMain - trailingPaddingAndBorderMain; const float occupiedSpaceByChildNodes = availableInnerMainDim - collectedFlexItemsValues.remainingFreeSpace; @@ -2529,11 +2557,11 @@ static void YGJustifyMainAxis( // defined, we override the position to whatever the user said // (and margin/border). child->setLayoutPosition( - (child->getLeadingPosition(mainAxis, availableInnerMainDim)) - .unwrap() + + YGUnwrapFloatOptional( + child->getLeadingPosition(mainAxis, availableInnerMainDim)) + node->getLeadingBorder(mainAxis) + - (child->getLeadingMargin(mainAxis, availableInnerWidth)) - .unwrap(), + YGUnwrapFloatOptional( + child->getLeadingMargin(mainAxis, availableInnerWidth)), pos[mainAxis]); } } else { @@ -2567,9 +2595,9 @@ static void YGJustifyMainAxis( // they weren't computed. This means we can't call // YGNodeDimWithMargin. collectedFlexItemsValues.mainDim += betweenMainDim + - (child->getMarginForAxis(mainAxis, availableInnerWidth)) - .unwrap() + - (childLayout.computedFlexBasis).unwrap(); + YGUnwrapFloatOptional(child->getMarginForAxis( + mainAxis, availableInnerWidth)) + + YGUnwrapFloatOptional(childLayout.computedFlexBasis); collectedFlexItemsValues.crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus @@ -2581,14 +2609,12 @@ static void YGJustifyMainAxis( // If the child is baseline aligned then the cross dimension is // calculated by adding maxAscent and maxDescent from the baseline. const float ascent = YGBaseline(child) + - (child->getLeadingMargin( - YGFlexDirectionColumn, availableInnerWidth)) - .unwrap(); + YGUnwrapFloatOptional(child->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth)); const float descent = child->getLayout().measuredDimensions[YGDimensionHeight] + - (child->getMarginForAxis( - YGFlexDirectionColumn, availableInnerWidth)) - .unwrap() - + YGUnwrapFloatOptional(child->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth)) - ascent; maxAscentForCurrentLine = @@ -2741,16 +2767,20 @@ static void YGNodelayoutImpl( YGResolveFlexDirection(YGFlexDirectionColumn, direction); node->setLayoutMargin( - (node->getLeadingMargin(flexRowDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getLeadingMargin(flexRowDirection, ownerWidth)), YGEdgeStart); node->setLayoutMargin( - (node->getTrailingMargin(flexRowDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getTrailingMargin(flexRowDirection, ownerWidth)), YGEdgeEnd); node->setLayoutMargin( - (node->getLeadingMargin(flexColumnDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getLeadingMargin(flexColumnDirection, ownerWidth)), YGEdgeTop); node->setLayoutMargin( - (node->getTrailingMargin(flexColumnDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getTrailingMargin(flexColumnDirection, ownerWidth)), YGEdgeBottom); node->setLayoutBorder(node->getLeadingBorder(flexRowDirection), YGEdgeStart); @@ -2760,16 +2790,20 @@ static void YGNodelayoutImpl( node->getTrailingBorder(flexColumnDirection), YGEdgeBottom); node->setLayoutPadding( - (node->getLeadingPadding(flexRowDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getLeadingPadding(flexRowDirection, ownerWidth)), YGEdgeStart); node->setLayoutPadding( - (node->getTrailingPadding(flexRowDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getTrailingPadding(flexRowDirection, ownerWidth)), YGEdgeEnd); node->setLayoutPadding( - (node->getLeadingPadding(flexColumnDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getLeadingPadding(flexColumnDirection, ownerWidth)), YGEdgeTop); node->setLayoutPadding( - (node->getTrailingPadding(flexColumnDirection, ownerWidth)).unwrap(), + YGUnwrapFloatOptional( + node->getTrailingPadding(flexColumnDirection, ownerWidth)), YGEdgeBottom); if (node->getMeasure() != nullptr) { @@ -2827,8 +2861,8 @@ static void YGNodelayoutImpl( const float mainAxisownerSize = isMainAxisRow ? ownerWidth : ownerHeight; const float crossAxisownerSize = isMainAxisRow ? ownerHeight : ownerWidth; - const float leadingPaddingAndBorderCross = - (node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)).unwrap(); + const float leadingPaddingAndBorderCross = YGUnwrapFloatOptional( + node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)); const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); const float paddingAndBorderAxisCross = @@ -2844,30 +2878,26 @@ static void YGNodelayoutImpl( const float paddingAndBorderAxisColumn = isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain; - const float marginAxisRow = - (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); - const float marginAxisColumn = - (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); + const float marginAxisRow = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + const float marginAxisColumn = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); const float minInnerWidth = - (YGResolveValue( - node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - .unwrap() - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - paddingAndBorderAxisRow; const float maxInnerWidth = - (YGResolveValue( - node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - .unwrap() - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - paddingAndBorderAxisRow; const float minInnerHeight = - (YGResolveValue( - node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - .unwrap() - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - paddingAndBorderAxisColumn; const float maxInnerHeight = - (YGResolveValue( - node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) - .unwrap() - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) - paddingAndBorderAxisColumn; const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; @@ -3078,11 +3108,11 @@ static void YGNodelayoutImpl( child->isLeadingPositionDefined(crossAxis); if (isChildLeadingPosDefined) { child->setLayoutPosition( - (child->getLeadingPosition(crossAxis, availableInnerCrossDim)) - .unwrap() + + YGUnwrapFloatOptional(child->getLeadingPosition( + crossAxis, availableInnerCrossDim)) + node->getLeadingBorder(crossAxis) + - (child->getLeadingMargin(crossAxis, availableInnerWidth)) - .unwrap(), + YGUnwrapFloatOptional(child->getLeadingMargin( + crossAxis, availableInnerWidth)), pos[crossAxis]); } // If leading position is not defined or calculations result in Nan, @@ -3091,8 +3121,8 @@ static void YGNodelayoutImpl( YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( node->getLeadingBorder(crossAxis) + - (child->getLeadingMargin(crossAxis, availableInnerWidth)) - .unwrap(), + YGUnwrapFloatOptional(child->getLeadingMargin( + crossAxis, availableInnerWidth)), pos[crossAxis]); } } else { @@ -3118,17 +3148,16 @@ static void YGNodelayoutImpl( child->getLayout().measuredDimensions[dim[mainAxis]]; float childCrossSize = !child->getStyle().aspectRatio.isUndefined() - ? (((child->getMarginForAxis(crossAxis, availableInnerWidth)) - .unwrap() + + ? ((YGUnwrapFloatOptional(child->getMarginForAxis( + crossAxis, availableInnerWidth)) + (isMainAxisRow ? childMainSize / - child->getStyle().aspectRatio.unwrap() + child->getStyle().aspectRatio.getValue() : childMainSize * - child->getStyle().aspectRatio.unwrap()))) + child->getStyle().aspectRatio.getValue()))) : collectedFlexItemsValues.crossDim; - childMainSize += - (child->getMarginForAxis(mainAxis, availableInnerWidth)) - .unwrap(); + childMainSize += YGUnwrapFloatOptional( + child->getMarginForAxis(mainAxis, availableInnerWidth)); YGMeasureMode childMainMeasureMode = YGMeasureModeExactly; YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly; @@ -3270,19 +3299,17 @@ static void YGNodelayoutImpl( lineHeight = YGFloatMax( lineHeight, child->getLayout().measuredDimensions[dim[crossAxis]] + - (child->getMarginForAxis(crossAxis, availableInnerWidth)) - .unwrap()); + YGUnwrapFloatOptional(child->getMarginForAxis( + crossAxis, availableInnerWidth))); } if (YGNodeAlignItem(node, child) == YGAlignBaseline) { const float ascent = YGBaseline(child) + - (child->getLeadingMargin( - YGFlexDirectionColumn, availableInnerWidth)) - .unwrap(); + YGUnwrapFloatOptional(child->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth)); const float descent = child->getLayout().measuredDimensions[YGDimensionHeight] + - (child->getMarginForAxis( - YGFlexDirectionColumn, availableInnerWidth)) - .unwrap() - + YGUnwrapFloatOptional(child->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth)) - ascent; maxAscentForCurrentLine = YGFloatMax(maxAscentForCurrentLine, ascent); @@ -3307,18 +3334,16 @@ static void YGNodelayoutImpl( case YGAlignFlexStart: { child->setLayoutPosition( currentLead + - (child->getLeadingMargin( - crossAxis, availableInnerWidth)) - .unwrap(), + YGUnwrapFloatOptional(child->getLeadingMargin( + crossAxis, availableInnerWidth)), pos[crossAxis]); break; } case YGAlignFlexEnd: { child->setLayoutPosition( currentLead + lineHeight - - (child->getTrailingMargin( - crossAxis, availableInnerWidth)) - .unwrap() - + YGUnwrapFloatOptional(child->getTrailingMargin( + crossAxis, availableInnerWidth)) - child->getLayout().measuredDimensions[dim[crossAxis]], pos[crossAxis]); break; @@ -3335,9 +3360,8 @@ static void YGNodelayoutImpl( case YGAlignStretch: { child->setLayoutPosition( currentLead + - (child->getLeadingMargin( - crossAxis, availableInnerWidth)) - .unwrap(), + YGUnwrapFloatOptional(child->getLeadingMargin( + crossAxis, availableInnerWidth)), pos[crossAxis]); // Remeasure child with the line height as it as been only @@ -3347,17 +3371,15 @@ static void YGNodelayoutImpl( const float childWidth = isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionWidth] + - (child->getMarginForAxis( - mainAxis, availableInnerWidth)) - .unwrap()) + YGUnwrapFloatOptional(child->getMarginForAxis( + mainAxis, availableInnerWidth))) : lineHeight; const float childHeight = !isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionHeight] + - (child->getMarginForAxis( - crossAxis, availableInnerWidth)) - .unwrap()) + YGUnwrapFloatOptional(child->getMarginForAxis( + crossAxis, availableInnerWidth))) : lineHeight; if (!(YGFloatsEqual( @@ -3387,9 +3409,8 @@ static void YGNodelayoutImpl( case YGAlignBaseline: { child->setLayoutPosition( currentLead + maxAscentForCurrentLine - YGBaseline(child) + - (child->getLeadingPosition( - YGFlexDirectionColumn, availableInnerCrossDim)) - .unwrap(), + YGUnwrapFloatOptional(child->getLeadingPosition( + YGFlexDirectionColumn, availableInnerCrossDim)), YGEdgeTop); break; @@ -3445,12 +3466,8 @@ static void YGNodelayoutImpl( YGFloatMax( YGFloatMin( availableInnerMainDim + paddingAndBorderAxisMain, - (YGNodeBoundAxisWithinMinAndMax( - node, - mainAxis, - YGFloatOptional{maxLineMainDim}, - mainAxisownerSize)) - .unwrap()), + YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + node, mainAxis, maxLineMainDim, mainAxisownerSize))), paddingAndBorderAxisMain), dim[mainAxis]); } @@ -3476,13 +3493,11 @@ static void YGNodelayoutImpl( YGFloatMax( YGFloatMin( availableInnerCrossDim + paddingAndBorderAxisCross, - (YGNodeBoundAxisWithinMinAndMax( - node, - crossAxis, - YGFloatOptional{totalLineCrossDim + - paddingAndBorderAxisCross}, - crossAxisownerSize)) - .unwrap()), + YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + node, + crossAxis, + totalLineCrossDim + paddingAndBorderAxisCross, + crossAxisownerSize))), paddingAndBorderAxisCross), dim[crossAxis]); } @@ -3782,10 +3797,10 @@ bool YGLayoutNodeInternal( // expensive to measure, so it's worth avoiding redundant measurements if at // all possible. if (node->getMeasure() != nullptr) { - const float marginAxisRow = - (node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)).unwrap(); - const float marginAxisColumn = - (node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)).unwrap(); + const float marginAxisRow = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + const float marginAxisColumn = YGUnwrapFloatOptional( + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); // First, try to use the layout cache. if (YGNodeCanUseCachedMeasurement( @@ -4085,18 +4100,16 @@ void YGNodeCalculateLayout( float width = YGUndefined; YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow, ownerWidth)) { - width = - (YGResolveValue( - node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) + - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)) - .unwrap(); + width = YGUnwrapFloatOptional( + YGResolveValue( + node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) + + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); widthMeasureMode = YGMeasureModeExactly; } else if (!YGResolveValue( node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth) .isUndefined()) { - width = (YGResolveValue( - node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - .unwrap(); + width = YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)); widthMeasureMode = YGMeasureModeAtMost; } else { width = ownerWidth; @@ -4107,20 +4120,18 @@ void YGNodeCalculateLayout( float height = YGUndefined; YGMeasureMode heightMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn, ownerHeight)) { - height = (YGResolveValue( - node->getResolvedDimension(dim[YGFlexDirectionColumn]), - ownerHeight) + - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)) - .unwrap(); + height = YGUnwrapFloatOptional( + YGResolveValue( + node->getResolvedDimension(dim[YGFlexDirectionColumn]), + ownerHeight) + + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); heightMeasureMode = YGMeasureModeExactly; } else if (!YGResolveValue( node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) .isUndefined()) { - height = - (YGResolveValue( - node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) - .unwrap(); + height = YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); heightMeasureMode = YGMeasureModeAtMost; } else { height = ownerHeight; diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 787af6df..96e71dc7 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -17,9 +17,17 @@ #include #endif +/** Large positive number signifies that the property(float) is undefined. + *Earlier we used to have YGundefined as NAN, but the downside of this is that + *we can't use -ffast-math compiler flag as it assumes all floating-point + *calculation involve and result into finite numbers. For more information + *regarding -ffast-math compiler flag in clang, have a look at + *https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math + **/ +#define YGUndefined 10E20F + #include "YGEnums.h" #include "YGMacros.h" -#include "YGValue.h" YG_EXTERN_C_BEGIN @@ -28,6 +36,25 @@ typedef struct YGSize { float height; } YGSize; +typedef struct YGValue { + float value; + YGUnit unit; +} YGValue; + +extern const YGValue YGValueUndefined; +extern const YGValue YGValueAuto; + +#ifdef __cplusplus + +YG_EXTERN_C_END + +extern bool operator==(const YGValue& lhs, const YGValue& rhs); +extern bool operator!=(const YGValue& lhs, const YGValue& rhs); + +YG_EXTERN_C_BEGIN + +#endif + typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; From e522b2dee4630e79b11b3209e11dd9fba85fcb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Sj=C3=B6lander?= Date: Mon, 10 Dec 2018 09:20:32 -0800 Subject: [PATCH 124/189] Fix aspect ratio when stretching with main axis margin (#834) Summary: I've noticed that when a child's size is determined by `align-items: stretch` in combination with `aspect-ratio` its size is wrongly calculated to account for margin in the main axis when there is more than enough space. See playground: https://goo.gl/tgW6cD I've yet to figure out exactly how to solve this but i've started by writing a failing test when can be seen in the first commit here. I assumed I had found the bug here https://github.com/facebook/yoga/blob/master/yoga/Yoga.cpp#L1838 where margin is being subtracted from the desired width even though the measure mode tells it to measure to exactly that size. However, if we don't remove this margin from the available width then 15 tests fail (including the one I just added) not quite figured out why yet. I'm also a bit confused at to why this would only happen for nodes with `aspect-ratio` and not for nodes where an explicit height and width is set. Pull Request resolved: https://github.com/facebook/yoga/pull/834 Reviewed By: astreet Differential Revision: D13223579 Pulled By: davidaurelio fbshipit-source-id: 6970e6072e79f3bb6f9097355ab6e441441bfd88 --- tests/YGAspectRatioTest.cpp | 23 +++++++++++++++++++++++ yoga/Yoga.cpp | 10 ++++++++++ 2 files changed, 33 insertions(+) diff --git a/tests/YGAspectRatioTest.cpp b/tests/YGAspectRatioTest.cpp index 9d99569b..c3e5154f 100644 --- a/tests/YGAspectRatioTest.cpp +++ b/tests/YGAspectRatioTest.cpp @@ -895,3 +895,26 @@ TEST(YogaTest, aspect_ratio_should_prefer_flexed_dimension) { YGNodeFreeRecursive(root); } + +TEST( + YogaTest, + aspect_ratio_defined_by_cross_stretch_should_not_be_effected_by_margin_on_main_axis) { + const YGConfigRef config = YGConfigNew(); + YGConfigSetUseWebDefaults(config, true); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetMargin(root_child0, YGEdgeStart, 50); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6abfb7d3..6bc264a1 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1382,6 +1382,16 @@ static void YGNodeComputeFlexBasisForChild( auto marginColumn = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + if (YGNodeAlignItem(node, child) == YGAlignStretch) { + if (isMainAxisRow && !YGFloatIsUndefined(height)) { + childHeight = height; + childHeightMeasureMode = YGMeasureModeExactly; + } else if (!isMainAxisRow && !YGFloatIsUndefined(width)) { + childWidth = width; + childWidthMeasureMode = YGMeasureModeExactly; + } + } + if (isRowStyleDimDefined) { childWidth = YGUnwrapFloatOptional(YGResolveValue( From 440c7191906250cdca864a418926f40dcd0e09b2 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Wed, 12 Dec 2018 05:55:30 -0800 Subject: [PATCH 125/189] added baseline and setIsReferenceBaseline doc in yoga website Summary: Added docs for align-items BASELINE property and yoga node setIsReferenceBaseline property in yoga website Reviewed By: davidaurelio Differential Revision: D13359436 fbshipit-source-id: 34cbb1087c70d44ec6462048cc2a819daf5951e0 --- website/contents/properties/align-items.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/contents/properties/align-items.md b/website/contents/properties/align-items.md index 9fe02d41..955b89f4 100644 --- a/website/contents/properties/align-items.md +++ b/website/contents/properties/align-items.md @@ -18,6 +18,8 @@ applying to the main axis, `align items` applies to the cross axis. **CENTER** Align children of a container in the center of the container's cross axis. +**BASELINE** Align children of a container along a common baseline. Individual children can be set to be the reference baseline for their parents. + ## Align Self From 8ab01fde6eccc7babef8ce09fc6fcc395adb7617 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 12 Dec 2018 16:11:46 -0800 Subject: [PATCH 126/189] Back out "[yoga][PR] Fix aspect ratio when stretching with main axis margin" Summary: Original commit changeset: 6970e6072e79 Reviewed By: mdvacca Differential Revision: D13437552 fbshipit-source-id: 65a55d716da6b6582e38efa906d3f540e58418bf --- tests/YGAspectRatioTest.cpp | 23 ----------------------- yoga/Yoga.cpp | 10 ---------- 2 files changed, 33 deletions(-) diff --git a/tests/YGAspectRatioTest.cpp b/tests/YGAspectRatioTest.cpp index c3e5154f..9d99569b 100644 --- a/tests/YGAspectRatioTest.cpp +++ b/tests/YGAspectRatioTest.cpp @@ -895,26 +895,3 @@ TEST(YogaTest, aspect_ratio_should_prefer_flexed_dimension) { YGNodeFreeRecursive(root); } - -TEST( - YogaTest, - aspect_ratio_defined_by_cross_stretch_should_not_be_effected_by_margin_on_main_axis) { - const YGConfigRef config = YGConfigNew(); - YGConfigSetUseWebDefaults(config, true); - - const YGNodeRef root = YGNodeNewWithConfig(config); - YGNodeStyleSetWidth(root, 200); - YGNodeStyleSetHeight(root, 100); - - const YGNodeRef root_child0 = YGNodeNewWithConfig(config); - YGNodeStyleSetMargin(root_child0, YGEdgeStart, 50); - YGNodeStyleSetAspectRatio(root_child0, 1); - YGNodeInsertChild(root, root_child0, 0); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); - - ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0)); - ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0)); - - YGNodeFreeRecursive(root); -} diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6bc264a1..6abfb7d3 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1382,16 +1382,6 @@ static void YGNodeComputeFlexBasisForChild( auto marginColumn = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); - if (YGNodeAlignItem(node, child) == YGAlignStretch) { - if (isMainAxisRow && !YGFloatIsUndefined(height)) { - childHeight = height; - childHeightMeasureMode = YGMeasureModeExactly; - } else if (!isMainAxisRow && !YGFloatIsUndefined(width)) { - childWidth = width; - childWidthMeasureMode = YGMeasureModeExactly; - } - } - if (isRowStyleDimDefined) { childWidth = YGUnwrapFloatOptional(YGResolveValue( From 9ddda3c6302d79d8174cfd336a61d84b5705d75b Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:28 -0800 Subject: [PATCH 127/189] Roll back `-ffast-math` Summary: @public `-ffast-math` does not have measurable performance benefits. By using `NaN` for *undefined* values again, we can squeeze `YGFloatOptional` into 32 bits. This will also enable us to store `YGValue` (or a variant of it) in 32 bits. Reviewed By: astreet Differential Revision: D13403925 fbshipit-source-id: b13d026bf556f24ab4699e65fb450af13a70961b --- csharp/Facebook.Yoga/YogaConstants.cs | 23 +++-------------- java/com/facebook/yoga/YogaConstants.java | 30 +++++------------------ tools/build_defs/oss/yoga_defs.bzl | 1 - yoga/Utils.h | 14 +++-------- yoga/Yoga-internal.h | 10 +------- yoga/Yoga.cpp | 5 +--- yoga/Yoga.h | 15 ++++++------ 7 files changed, 21 insertions(+), 77 deletions(-) diff --git a/csharp/Facebook.Yoga/YogaConstants.cs b/csharp/Facebook.Yoga/YogaConstants.cs index a715b43c..9e05cca3 100644 --- a/csharp/Facebook.Yoga/YogaConstants.cs +++ b/csharp/Facebook.Yoga/YogaConstants.cs @@ -1,4 +1,4 @@ -/** +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -9,28 +9,11 @@ namespace Facebook.Yoga { public static class YogaConstants { - /** - * Large positive number signifies that the property(float) is undefined. Earlier we used to have - * YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as - * it assumes all floating-point calculation involve and result into finite numbers. For more - * information regarding -ffast-math compiler flag in clang, have a look at - * https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math - */ - public const float Undefined = 10E20F; + public const float Undefined = float.NaN; public static bool IsUndefined(float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN, - // the benefit of which - // was that if NAN is involved in any mathematical expression the result was NAN. But since we - // want to have `-ffast-math` - // flag being used by compiler which assumes that the floating point values are not NAN and Inf, - // we represent YGUndefined as 10.1E20. - // But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would - // change. - // So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it - // is undefined. - return value >= 10E8F || value <= -10E8; + return float.IsNaN(value); } public static bool IsUndefined(YogaValue value) diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index 61e212ef..b04a7e53 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -1,35 +1,17 @@ -/* - * 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. +/** + * 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 YogaConstants { - /** - * Large positive number signifies that the property(float) is undefined. Earlier we used to have - * YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as - * it assumes all floating-point calculation involve and result into finite numbers. For more - * information regarding -ffast-math compiler flag in clang, have a look at - * https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math - */ - public static final float UNDEFINED = (float) (10E20); + public static final float UNDEFINED = Float.NaN; public static boolean isUndefined(float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN, - // the benefit of which - // was that if NAN is involved in any mathematical expression the result was NAN. But since we - // want to have `-ffast-math` - // flag being used by compiler which assumes that the floating point values are not NAN and Inf, - // we represent YGUndefined as 10.1E20. - // But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would - // change. - // So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it - // is undefined. - return (Float.compare(value, (float) 10E8) >= 0 || Float.compare(value, (float) -10E8) <= 0); + return Float.compare(value, UNDEFINED) == 0; } public static boolean isUndefined(YogaValue value) { diff --git a/tools/build_defs/oss/yoga_defs.bzl b/tools/build_defs/oss/yoga_defs.bzl index 7eca7b9b..5a5872fe 100644 --- a/tools/build_defs/oss/yoga_defs.bzl +++ b/tools/build_defs/oss/yoga_defs.bzl @@ -58,7 +58,6 @@ BASE_COMPILER_FLAGS = [ "-Wall", "-Werror", "-O3", - "-ffast-math", ] LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [ diff --git a/yoga/Utils.h b/yoga/Utils.h index d578511c..d007ff54 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -57,22 +57,12 @@ bool YGValueEqual(const YGValue a, const YGValue b); // difference between two floats is less than 0.0001f or both are undefined. bool YGFloatsEqual(const float a, const float b); -// We need custom max function, since we want that, if one argument is -// YGUndefined then the max funtion should return the other argument as the max -// value. We wouldn't have needed a custom max function if YGUndefined was NAN -// as fmax has the same behaviour, but with NAN we cannot use `-ffast-math` -// compiler flag. float YGFloatMax(const float a, const float b); YGFloatOptional YGFloatOptionalMax( const YGFloatOptional& op1, const YGFloatOptional& op2); -// We need custom min function, since we want that, if one argument is -// YGUndefined then the min funtion should return the other argument as the min -// value. We wouldn't have needed a custom min function if YGUndefined was NAN -// as fmin has the same behaviour, but with NAN we cannot use `-ffast-math` -// compiler flag. float YGFloatMin(const float a, const float b); // This custom float comparision function compares the array of float with @@ -106,7 +96,9 @@ inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) { flexDirection == YGFlexDirectionRowReverse; } -inline YGFloatOptional YGResolveValue(const YGValue value, const float ownerSize) { +inline YGFloatOptional YGResolveValue( + const YGValue value, + const float ownerSize) { switch (value.unit) { case YGUnitUndefined: case YGUnitAuto: diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 1e9a1aaf..ef5e5d8c 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -27,15 +27,7 @@ namespace facebook { namespace yoga { inline bool isUndefined(float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier - // it used to be NAN, the benefit of which was that if NAN is involved in any - // mathematical expression the result was NAN. But since we want to have - // `-ffast-math` flag being used by compiler which assumes that the floating - // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But - // now if YGUndefined is involved in any mathematical operations this - // value(10.1E20) would change. So the following check makes sure that if the - // value is outside a range (-10E8, 10E8) then it is undefined. - return value >= 10E8 || value <= -10E8; + return std::isnan(value); } } // namespace yoga diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6abfb7d3..d5fc12ef 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -18,10 +18,7 @@ /* define fmaxf if < VC12 */ #if _MSC_VER < 1800 __forceinline const float fmaxf(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { - return (a > b) ? a : b; - } - return YGFloatIsUndefined(a) ? b : a; + return (a > b) ? a : b; } #endif #endif diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 96e71dc7..61aae0fe 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -17,14 +17,13 @@ #include #endif -/** Large positive number signifies that the property(float) is undefined. - *Earlier we used to have YGundefined as NAN, but the downside of this is that - *we can't use -ffast-math compiler flag as it assumes all floating-point - *calculation involve and result into finite numbers. For more information - *regarding -ffast-math compiler flag in clang, have a look at - *https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math - **/ -#define YGUndefined 10E20F +// Not defined in MSVC++ +#ifndef NAN +static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; +#define NAN (*(const float*)__nan) +#endif + +#define YGUndefined NAN #include "YGEnums.h" #include "YGMacros.h" From f23a669ed0dcb5b0b9b9922e5f1fdd911b7ee962 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:28 -0800 Subject: [PATCH 128/189] Move out `YGValue` Summary: @public Creates a single header file for `YGValue`. This is in preparation of a more compact representation of `YGValue` within `YGStyle`. Also fixes the incorrect definition of NAN. Reviewed By: SidharthGuglani Differential Revision: D13439602 fbshipit-source-id: 68eef2c391b6c9810f3c995b86fff7204ebe6511 --- yoga/YGValue.cpp | 29 +++++++++++++++++++++++++++++ yoga/YGValue.h | 40 ++++++++++++++++++++++++++++++++++++++++ yoga/Yoga.cpp | 17 ----------------- yoga/Yoga.h | 28 +--------------------------- 4 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 yoga/YGValue.cpp create mode 100644 yoga/YGValue.h diff --git a/yoga/YGValue.cpp b/yoga/YGValue.cpp new file mode 100644 index 00000000..4bfe083d --- /dev/null +++ b/yoga/YGValue.cpp @@ -0,0 +1,29 @@ +/** + * 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 "YGValue.h" + +const YGValue YGValueZero = {0, YGUnitPoint}; +const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; +const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; + +bool operator==(const YGValue& lhs, const YGValue& rhs) { + if (lhs.unit != rhs.unit) { + return false; + } + + switch (lhs.unit) { + case YGUnitUndefined: + case YGUnitAuto: + return true; + default: + return lhs.value == rhs.value; + } +} + +bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} diff --git a/yoga/YGValue.h b/yoga/YGValue.h new file mode 100644 index 00000000..803b8e78 --- /dev/null +++ b/yoga/YGValue.h @@ -0,0 +1,40 @@ +/** + * 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 +#include "YGEnums.h" +#include "YGMacros.h" + +YG_EXTERN_C_BEGIN + +// Not defined in MSVC++ +#ifndef NAN +static const uint32_t __nan = 0x7fc00000; +#define NAN (*(const float*)__nan) +#endif + +#define YGUndefined NAN + +typedef struct YGValue { + float value; + YGUnit unit; +} YGValue; + +extern const YGValue YGValueAuto; +extern const YGValue YGValueUndefined; +extern const YGValue YGValueZero; + +YG_EXTERN_C_END + +#ifdef __cplusplus + +bool operator==(const YGValue& lhs, const YGValue& rhs); + +bool operator!=(const YGValue& lhs, const YGValue& rhs); + +#endif diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index d5fc12ef..246e0f41 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -39,23 +39,6 @@ static int YGDefaultLog( va_list args); #endif -const YGValue YGValueZero = {0, YGUnitPoint}; -const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; -const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; - -bool operator==(const YGValue& lhs, const YGValue& rhs) { - if ((lhs.unit == YGUnitUndefined && rhs.unit == YGUnitUndefined) || - (lhs.unit == YGUnitAuto && rhs.unit == YGUnitAuto)) { - return true; - } - - return lhs.unit == rhs.unit && lhs.value == rhs.value; -} - -bool operator!=(const YGValue& lhs, const YGValue& rhs) { - return !(lhs == rhs); -} - #ifdef ANDROID #include static int YGAndroidLog( diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 61aae0fe..787af6df 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -17,16 +17,9 @@ #include #endif -// Not defined in MSVC++ -#ifndef NAN -static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; -#define NAN (*(const float*)__nan) -#endif - -#define YGUndefined NAN - #include "YGEnums.h" #include "YGMacros.h" +#include "YGValue.h" YG_EXTERN_C_BEGIN @@ -35,25 +28,6 @@ typedef struct YGSize { float height; } YGSize; -typedef struct YGValue { - float value; - YGUnit unit; -} YGValue; - -extern const YGValue YGValueUndefined; -extern const YGValue YGValueAuto; - -#ifdef __cplusplus - -YG_EXTERN_C_END - -extern bool operator==(const YGValue& lhs, const YGValue& rhs); -extern bool operator!=(const YGValue& lhs, const YGValue& rhs); - -YG_EXTERN_C_BEGIN - -#endif - typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; From e9078374c98a471335a365595b2c3fbc86f19958 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:29 -0800 Subject: [PATCH 129/189] Make equality operator for `YGValue` inlineable Summary: @public Makes `operator==` for `YGValue` an inline function. Reviewed By: SidharthGuglani Differential Revision: D13439601 fbshipit-source-id: c5dd1f35c40f0ffa8224ee2f40ac7cc3cd8e3cf9 --- yoga/YGValue.cpp | 18 ------------------ yoga/YGValue.h | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/yoga/YGValue.cpp b/yoga/YGValue.cpp index 4bfe083d..fcdd0c69 100644 --- a/yoga/YGValue.cpp +++ b/yoga/YGValue.cpp @@ -9,21 +9,3 @@ const YGValue YGValueZero = {0, YGUnitPoint}; const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; - -bool operator==(const YGValue& lhs, const YGValue& rhs) { - if (lhs.unit != rhs.unit) { - return false; - } - - switch (lhs.unit) { - case YGUnitUndefined: - case YGUnitAuto: - return true; - default: - return lhs.value == rhs.value; - } -} - -bool operator!=(const YGValue& lhs, const YGValue& rhs) { - return !(lhs == rhs); -} diff --git a/yoga/YGValue.h b/yoga/YGValue.h index 803b8e78..4e43f7b2 100644 --- a/yoga/YGValue.h +++ b/yoga/YGValue.h @@ -33,8 +33,24 @@ YG_EXTERN_C_END #ifdef __cplusplus -bool operator==(const YGValue& lhs, const YGValue& rhs); +inline bool operator==(const YGValue& lhs, const YGValue& rhs) { + if (lhs.unit != rhs.unit) { + return false; + } -bool operator!=(const YGValue& lhs, const YGValue& rhs); + switch (lhs.unit) { + case YGUnitUndefined: + case YGUnitAuto: + return true; + case YGUnitPoint: + case YGUnitPercent: + default: + return lhs.value == rhs.value; + } +} + +inline bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} #endif From da678ef9711d9b437bba15bd58f21393ad2f8b33 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:29 -0800 Subject: [PATCH 130/189] Add tests for `YGFloatOptional` Summary: @public Adds tests for `YGFloatOptional`, to ease refactorings. Reviewed By: SidharthGuglani Differential Revision: D13439610 fbshipit-source-id: e29da7f85ccedc46520b59f6c893bad521d35417 --- tests/YGFloatOptionalTest.cpp | 207 ++++++++++++++++++++++++++++++++++ yoga/YGFloatOptional.cpp | 2 +- yoga/YGFloatOptional.h | 2 +- 3 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 tests/YGFloatOptionalTest.cpp diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp new file mode 100644 index 00000000..f2995747 --- /dev/null +++ b/tests/YGFloatOptionalTest.cpp @@ -0,0 +1,207 @@ +/** + * 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 + +#include +#include +#include + +static const auto empty = YGFloatOptional{}; +static const auto zero = YGFloatOptional{0.0f}; +static const auto one = YGFloatOptional{1.0f}; +static const auto positive = YGFloatOptional{1234.5f}; +static const auto negative = YGFloatOptional{-9876.5f}; + +TEST(YGFloatOptional, value) { + ASSERT_EQ(zero.getValue(), 0.0f); + ASSERT_EQ(one.getValue(), 1.0f); + ASSERT_EQ(positive.getValue(), 1234.5f); + ASSERT_EQ(negative.getValue(), -9876.5f); + + ASSERT_TRUE(empty.isUndefined()); + ASSERT_FALSE(zero.isUndefined()); + ASSERT_FALSE(one.isUndefined()); + ASSERT_FALSE(positive.isUndefined()); + ASSERT_FALSE(negative.isUndefined()); +} + +TEST(YGFloatOptional, equality) { + ASSERT_TRUE(empty == empty); + ASSERT_TRUE(empty == YGUndefined); + ASSERT_FALSE(empty == zero); + ASSERT_FALSE(empty == negative); + ASSERT_FALSE(empty == 12.3f); + + ASSERT_TRUE(zero == zero); + ASSERT_TRUE(zero == 0.0f); + ASSERT_FALSE(zero == positive); + ASSERT_FALSE(zero == -5555.5f); + + ASSERT_TRUE(one == one); + ASSERT_TRUE(one == 1.0f); + ASSERT_FALSE(one == positive); + + ASSERT_TRUE(positive == positive); + ASSERT_TRUE(positive == positive.getValue()); + ASSERT_FALSE(positive == one); + + ASSERT_TRUE(negative == negative); + ASSERT_TRUE(negative == negative.getValue()); + ASSERT_FALSE(negative == zero); +} + +TEST(YGFloatOptional, inequality) { + ASSERT_FALSE(empty != empty); + ASSERT_FALSE(empty != YGUndefined); + ASSERT_TRUE(empty != zero); + ASSERT_TRUE(empty != negative); + ASSERT_TRUE(empty != 12.3f); + + ASSERT_FALSE(zero != zero); + ASSERT_FALSE(zero != 0.0f); + ASSERT_TRUE(zero != positive); + ASSERT_TRUE(zero != -5555.5f); + + ASSERT_FALSE(one != one); + ASSERT_FALSE(one != 1.0f); + ASSERT_TRUE(one != positive); + + ASSERT_FALSE(positive != positive); + ASSERT_FALSE(positive != positive.getValue()); + ASSERT_TRUE(positive != one); + + ASSERT_FALSE(negative != negative); + ASSERT_FALSE(negative != negative.getValue()); + ASSERT_TRUE(negative != zero); +} + +TEST(YGFloatOptional, greater_than_with_undefined) { + ASSERT_FALSE(empty > empty); + ASSERT_FALSE(empty > zero); + ASSERT_FALSE(empty > one); + ASSERT_FALSE(empty > positive); + ASSERT_FALSE(empty > negative); + ASSERT_FALSE(zero > empty); + ASSERT_FALSE(one > empty); + ASSERT_FALSE(positive > empty); + ASSERT_FALSE(negative > empty); +} + +TEST(YGFloatOptional, greater_than) { + ASSERT_TRUE(zero > negative); + ASSERT_FALSE(zero > zero); + ASSERT_FALSE(zero > positive); + ASSERT_FALSE(zero > one); + + ASSERT_TRUE(one > negative); + ASSERT_TRUE(one > zero); + ASSERT_FALSE(one > positive); + + ASSERT_TRUE(negative > YGFloatOptional{-INFINITY}); +} + +TEST(YGFloatOptional, less_than_with_undefined) { + ASSERT_FALSE(empty < empty); + ASSERT_FALSE(zero < empty); + ASSERT_FALSE(one < empty); + ASSERT_FALSE(positive < empty); + ASSERT_FALSE(negative < empty); + ASSERT_FALSE(empty < zero); + ASSERT_FALSE(empty < one); + ASSERT_FALSE(empty < positive); + ASSERT_FALSE(empty < negative); +} + +TEST(YGFloatOptional, less_than) { + ASSERT_TRUE(negative < zero); + ASSERT_FALSE(zero < zero); + ASSERT_FALSE(positive < zero); + ASSERT_FALSE(one < zero); + + ASSERT_TRUE(negative < one); + ASSERT_TRUE(zero < one); + ASSERT_FALSE(positive < one); + + ASSERT_TRUE(YGFloatOptional{-INFINITY} < negative); +} + +TEST(YGFloatOptional, greater_than_equals_with_undefined) { + ASSERT_TRUE(empty >= empty); + ASSERT_FALSE(empty >= zero); + ASSERT_FALSE(empty >= one); + ASSERT_FALSE(empty >= positive); + ASSERT_FALSE(empty >= negative); + ASSERT_FALSE(zero >= empty); + ASSERT_FALSE(one >= empty); + ASSERT_FALSE(positive >= empty); + ASSERT_FALSE(negative >= empty); +} + +TEST(YGFloatOptional, greater_than_equals) { + ASSERT_TRUE(zero >= negative); + ASSERT_TRUE(zero >= zero); + ASSERT_FALSE(zero >= positive); + ASSERT_FALSE(zero >= one); + + ASSERT_TRUE(one >= negative); + ASSERT_TRUE(one >= zero); + ASSERT_FALSE(one >= positive); + + ASSERT_TRUE(negative >= YGFloatOptional{-INFINITY}); +} + +TEST(YGFloatOptional, less_than_equals_with_undefined) { + ASSERT_TRUE(empty <= empty); + ASSERT_FALSE(zero <= empty); + ASSERT_FALSE(one <= empty); + ASSERT_FALSE(positive <= empty); + ASSERT_FALSE(negative <= empty); + ASSERT_FALSE(empty <= zero); + ASSERT_FALSE(empty <= one); + ASSERT_FALSE(empty <= positive); + ASSERT_FALSE(empty <= negative); +} + +TEST(YGFloatOptional, less_than_equals) { + ASSERT_TRUE(negative <= zero); + ASSERT_TRUE(zero <= zero); + ASSERT_FALSE(positive <= zero); + ASSERT_FALSE(one <= zero); + + ASSERT_TRUE(negative <= one); + ASSERT_TRUE(zero <= one); + ASSERT_FALSE(positive <= one); + + ASSERT_TRUE(YGFloatOptional{-INFINITY} <= negative); +} + +TEST(YGFloatOptional, addition) { + auto n = negative.getValue(); + auto p = positive.getValue(); + + ASSERT_EQ(zero + one, one); + ASSERT_EQ(negative + positive, YGFloatOptional{n + p}); + ASSERT_EQ(empty + zero, empty); + ASSERT_EQ(empty + empty, empty); + ASSERT_EQ(negative + empty, empty); +} + +TEST(YGFloatOptionalTest, YGFloatOptionalMax) { + ASSERT_EQ(YGFloatOptionalMax(empty, empty), empty); + ASSERT_EQ(YGFloatOptionalMax(empty, positive), positive); + ASSERT_EQ(YGFloatOptionalMax(negative, empty), negative); + ASSERT_EQ(YGFloatOptionalMax(negative, YGFloatOptional{-INFINITY}), negative); + ASSERT_EQ( + YGFloatOptionalMax(YGFloatOptional{1.0f}, YGFloatOptional{1.125f}), + YGFloatOptional{1.125f}); +} + +TEST(YGFloatOptionalTest, YGUnwrapFloatOptional) { + ASSERT_TRUE(YGFloatIsUndefined(YGUnwrapFloatOptional(empty))); + ASSERT_EQ(YGUnwrapFloatOptional(zero), 0.0f); + ASSERT_EQ(YGUnwrapFloatOptional(YGFloatOptional{123456.78f}), 123456.78f); +} diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index d023dccb..da7b8ce8 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -53,7 +53,7 @@ bool YGFloatOptional::operator!=(float val) const { return !(*this == val); } -YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) { +YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) const { if (!isUndefined_ && !op.isUndefined_) { return YGFloatOptional(value_ + op.value_); } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 07fbb64b..6f4af241 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -30,7 +30,7 @@ struct YGFloatOptional { return isUndefined_; } - YGFloatOptional operator+(const YGFloatOptional& op); + YGFloatOptional operator+(const YGFloatOptional& op) const; bool operator>(const YGFloatOptional& op) const; bool operator<(const YGFloatOptional& op) const; bool operator>=(const YGFloatOptional& op) const; From 6bdd39d0ed84e101112b31243bd3bcb60ff46ba1 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:30 -0800 Subject: [PATCH 131/189] Store `YGFloatOptional` in 32 bits Summary: @public After removing `-ffast-math`, `NaN` can again be used to represent `undefined`. That allows us to remove the additional flag from `YGFloatOptional`, and reduce memory usage. Reviewed By: SidharthGuglani Differential Revision: D13439611 fbshipit-source-id: 93e90f72f0415edb228b4e7d145e1fae35cc6b43 --- tests/YGFloatOptionalTest.cpp | 10 +++---- yoga/YGFloatOptional.cpp | 53 +++++++++-------------------------- yoga/YGFloatOptional.h | 32 +++++++++------------ yoga/YGNode.cpp | 2 +- 4 files changed, 34 insertions(+), 63 deletions(-) diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp index f2995747..3c73b0ba 100644 --- a/tests/YGFloatOptionalTest.cpp +++ b/tests/YGFloatOptionalTest.cpp @@ -10,11 +10,11 @@ #include #include -static const auto empty = YGFloatOptional{}; -static const auto zero = YGFloatOptional{0.0f}; -static const auto one = YGFloatOptional{1.0f}; -static const auto positive = YGFloatOptional{1234.5f}; -static const auto negative = YGFloatOptional{-9876.5f}; +constexpr auto empty = YGFloatOptional{}; +constexpr auto zero = YGFloatOptional{0.0f}; +constexpr auto one = YGFloatOptional{1.0f}; +constexpr auto positive = YGFloatOptional{1234.5f}; +constexpr auto negative = YGFloatOptional{-9876.5f}; TEST(YGFloatOptional, value) { ASSERT_EQ(zero.getValue(), 0.0f); diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index da7b8ce8..0bf89f29 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -7,23 +7,13 @@ #include "YGFloatOptional.h" #include #include -#include "Yoga.h" #include "Yoga-internal.h" +#include "Yoga.h" using namespace facebook; -YGFloatOptional::YGFloatOptional(float value) { - if (yoga::isUndefined(value)) { - isUndefined_ = true; - value_ = 0; - } else { - value_ = value; - isUndefined_ = false; - } -} - float YGFloatOptional::getValue() const { - if (isUndefined_) { + if (isUndefined()) { // Abort, accessing a value of an undefined float optional std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; std::exit(EXIT_FAILURE); @@ -31,53 +21,38 @@ float YGFloatOptional::getValue() const { return value_; } -bool YGFloatOptional::operator==(const YGFloatOptional& op) const { - if (isUndefined_ == op.isUndefined()) { - return isUndefined_ || value_ == op.getValue(); - } - return false; +bool YGFloatOptional::operator==(YGFloatOptional op) const { + return value_ == op.value_ || (isUndefined() && op.isUndefined()); } -bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { +bool YGFloatOptional::operator!=(YGFloatOptional op) const { return !(*this == op); } bool YGFloatOptional::operator==(float val) const { - if (yoga::isUndefined(val) == isUndefined_) { - return isUndefined_ || val == value_; - } - return false; + return value_ == val || (isUndefined() && yoga::isUndefined(val)); } bool YGFloatOptional::operator!=(float val) const { return !(*this == val); } -YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) const { - if (!isUndefined_ && !op.isUndefined_) { - return YGFloatOptional(value_ + op.value_); - } - return YGFloatOptional(); +YGFloatOptional YGFloatOptional::operator+(YGFloatOptional op) const { + return YGFloatOptional{value_ + op.value_}; } -bool YGFloatOptional::operator>(const YGFloatOptional& op) const { - if (isUndefined_ || op.isUndefined_) { - return false; - } +bool YGFloatOptional::operator>(YGFloatOptional op) const { return value_ > op.value_; } -bool YGFloatOptional::operator<(const YGFloatOptional& op) const { - if (isUndefined_ || op.isUndefined_) { - return false; - } +bool YGFloatOptional::operator<(YGFloatOptional op) const { return value_ < op.value_; } -bool YGFloatOptional::operator>=(const YGFloatOptional& op) const { - return *this == op || *this > op; +bool YGFloatOptional::operator>=(YGFloatOptional op) const { + return *this > op || *this == op; } -bool YGFloatOptional::operator<=(const YGFloatOptional& op) const { - return *this == op || *this < op; +bool YGFloatOptional::operator<=(YGFloatOptional op) const { + return *this < op || *this == op; } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 6f4af241..7b573d38 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -6,37 +6,33 @@ */ #pragma once +#include +#include + struct YGFloatOptional { private: - float value_ = 0; - bool isUndefined_ = true; + float value_ = std::numeric_limits::quiet_NaN(); public: - explicit YGFloatOptional(float value); - YGFloatOptional() = default; + explicit constexpr YGFloatOptional(float value) : value_(value) {} + constexpr YGFloatOptional() = default; // Program will terminate if the value of an undefined is accessed. Please // make sure to check if the optional is defined before calling this function. // To check if float optional is defined, use `isUndefined()`. float getValue() const; - // Sets the value of float optional, and thus isUndefined is assigned false. - void setValue(float val) { - value_ = val; - isUndefined_ = false; - } - bool isUndefined() const { - return isUndefined_; + return std::isnan(value_); } - YGFloatOptional operator+(const YGFloatOptional& op) const; - bool operator>(const YGFloatOptional& op) const; - bool operator<(const YGFloatOptional& op) const; - bool operator>=(const YGFloatOptional& op) const; - bool operator<=(const YGFloatOptional& op) const; - bool operator==(const YGFloatOptional& op) const; - bool operator!=(const YGFloatOptional& op) const; + YGFloatOptional operator+(YGFloatOptional op) const; + bool operator>(YGFloatOptional op) const; + bool operator<(YGFloatOptional op) const; + bool operator>=(YGFloatOptional op) const; + bool operator<=(YGFloatOptional op) const; + bool operator==(YGFloatOptional op) const; + bool operator!=(YGFloatOptional op) const; bool operator==(float val) const; bool operator!=(float val) const; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 1694692c..04c3c7f6 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -211,7 +211,7 @@ YGFloatOptional YGNode::relativePosition( YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize); if (!trailingPosition.isUndefined()) { - trailingPosition.setValue(-1 * trailingPosition.getValue()); + trailingPosition = YGFloatOptional{-1 * trailingPosition.getValue()}; } return trailingPosition; } From aaa018bbea9ce3361120f13c1d614e752827c2f7 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:30 -0800 Subject: [PATCH 132/189] Remove `YGUnwrapFloatOptional` Summary: Replaces `YGUnwrapFloatOptional` with `YGFloatOptional::unwrap`. This leads to more idiomatic C++, and to less function call nesting, thus increasing readability. Reviewed By: SidharthGuglani Differential Revision: D13439604 fbshipit-source-id: 33b43c08d725c253c359959e7cbbd83fd6bd9ba4 --- tests/YGFloatOptionalTest.cpp | 8 +- yoga/Utils.cpp | 4 - yoga/Utils.h | 5 - yoga/YGFloatOptional.h | 5 + yoga/YGNode.cpp | 14 +- yoga/Yoga.cpp | 376 ++++++++++++++++++---------------- 6 files changed, 211 insertions(+), 201 deletions(-) diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp index 3c73b0ba..38c7ebb3 100644 --- a/tests/YGFloatOptionalTest.cpp +++ b/tests/YGFloatOptionalTest.cpp @@ -200,8 +200,8 @@ TEST(YGFloatOptionalTest, YGFloatOptionalMax) { YGFloatOptional{1.125f}); } -TEST(YGFloatOptionalTest, YGUnwrapFloatOptional) { - ASSERT_TRUE(YGFloatIsUndefined(YGUnwrapFloatOptional(empty))); - ASSERT_EQ(YGUnwrapFloatOptional(zero), 0.0f); - ASSERT_EQ(YGUnwrapFloatOptional(YGFloatOptional{123456.78f}), 123456.78f); +TEST(YGFloatOptionalTest, unwrap) { + ASSERT_TRUE(YGFloatIsUndefined(empty.unwrap())); + ASSERT_EQ(zero.unwrap(), 0.0f); + ASSERT_EQ(YGFloatOptional{123456.78f}.unwrap(), 123456.78f); } diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 74cc38c9..331cb660 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -55,10 +55,6 @@ float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } -float YGUnwrapFloatOptional(const YGFloatOptional& op) { - return op.isUndefined() ? YGUndefined : op.getValue(); -} - YGFloatOptional YGFloatOptionalMax( const YGFloatOptional& op1, const YGFloatOptional& op2) { diff --git a/yoga/Utils.h b/yoga/Utils.h index d007ff54..e5e20ba3 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -82,11 +82,6 @@ bool YGFloatArrayEqual( // This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise float YGFloatSanitize(const float val); -// This function unwraps optional and returns YGUndefined if not defined or -// op.value otherwise -// TODO: Get rid off this function -float YGUnwrapFloatOptional(const YGFloatOptional& op); - YGFlexDirection YGFlexDirectionCross( const YGFlexDirection flexDirection, const YGDirection direction); diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 7b573d38..56bc8557 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -22,6 +22,11 @@ struct YGFloatOptional { // To check if float optional is defined, use `isUndefined()`. float getValue() const; + // returns the wrapped value, or a value x with YGIsUndefined(x) == true + float unwrap() const { + return value_; + } + bool isUndefined() const { return std::isnan(value_); } diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 04c3c7f6..d930c51a 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -236,20 +236,18 @@ void YGNode::setPosition( relativePosition(crossAxis, crossSize); setLayoutPosition( - YGUnwrapFloatOptional( - getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain), + (getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), leading[mainAxis]); setLayoutPosition( - YGUnwrapFloatOptional( - getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain), + (getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), trailing[mainAxis]); setLayoutPosition( - YGUnwrapFloatOptional( - getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross), + (getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross) + .unwrap(), leading[crossAxis]); setLayoutPosition( - YGUnwrapFloatOptional( - getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross), + (getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross) + .unwrap(), trailing[crossAxis]); } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 246e0f41..8db18e9e 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1096,9 +1096,9 @@ static inline float YGNodePaddingAndBorderForAxis( const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { - return YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(axis, widthSize) + - node->getTrailingPaddingAndBorder(axis, widthSize)); + return (node->getLeadingPaddingAndBorder(axis, widthSize) + + node->getTrailingPaddingAndBorder(axis, widthSize)) + .unwrap(); } static inline YGAlign YGNodeAlignItem( @@ -1180,9 +1180,9 @@ static inline float YGNodeDimWithMargin( const YGFlexDirection axis, const float widthSize) { return node->getLayout().measuredDimensions[dim[axis]] + - YGUnwrapFloatOptional( - node->getLeadingMargin(axis, widthSize) + - node->getTrailingMargin(axis, widthSize)); + (node->getLeadingMargin(axis, widthSize) + + node->getTrailingMargin(axis, widthSize)) + .unwrap(); } static inline bool YGNodeIsStyleDimDefined( @@ -1249,8 +1249,7 @@ static inline float YGNodeBoundAxis( const float axisSize, const float widthSize) { return YGFloatMax( - YGUnwrapFloatOptional( - YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)), + YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize).unwrap(), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } @@ -1357,22 +1356,24 @@ static void YGNodeComputeFlexBasisForChild( childWidthMeasureMode = YGMeasureModeUndefined; childHeightMeasureMode = YGMeasureModeUndefined; - auto marginRow = YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - auto marginColumn = YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + auto marginRow = + child->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); + auto marginColumn = + child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap(); if (isRowStyleDimDefined) { childWidth = - YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionWidth), ownerWidth)) + + YGResolveValue( + child->getResolvedDimension(YGDimensionWidth), ownerWidth) + .unwrap() + marginRow; childWidthMeasureMode = YGMeasureModeExactly; } if (isColumnStyleDimDefined) { childHeight = - YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionHeight), ownerHeight)) + + YGResolveValue( + child->getResolvedDimension(YGDimensionHeight), ownerHeight) + .unwrap() + marginColumn; childHeightMeasureMode = YGMeasureModeExactly; } @@ -1500,14 +1501,14 @@ static void YGNodeAbsoluteLayoutChild( YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined; YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; - auto marginRow = - YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width)); - auto marginColumn = YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionColumn, width)); + auto marginRow = child->getMarginForAxis(YGFlexDirectionRow, width).unwrap(); + auto marginColumn = + child->getMarginForAxis(YGFlexDirectionColumn, width).unwrap(); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { - childWidth = YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionWidth), width)) + + childWidth = + YGResolveValue(child->getResolvedDimension(YGDimensionWidth), width) + .unwrap() + marginRow; } else { // If the child doesn't have a specified width, compute the width based @@ -1518,17 +1519,18 @@ static void YGNodeAbsoluteLayoutChild( childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] - (node->getLeadingBorder(YGFlexDirectionRow) + node->getTrailingBorder(YGFlexDirectionRow)) - - YGUnwrapFloatOptional( - child->getLeadingPosition(YGFlexDirectionRow, width) + - child->getTrailingPosition(YGFlexDirectionRow, width)); + (child->getLeadingPosition(YGFlexDirectionRow, width) + + child->getTrailingPosition(YGFlexDirectionRow, width)) + .unwrap(); childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) { - childHeight = YGUnwrapFloatOptional(YGResolveValue( - child->getResolvedDimension(YGDimensionHeight), height)) + + childHeight = + YGResolveValue(child->getResolvedDimension(YGDimensionHeight), height) + .unwrap() + marginColumn; } else { // If the child doesn't have a specified height, compute the height @@ -1536,13 +1538,12 @@ static void YGNodeAbsoluteLayoutChild( // offsets if they're defined. if (child->isLeadingPositionDefined(YGFlexDirectionColumn) && child->isTrailingPosDefined(YGFlexDirectionColumn)) { - childHeight = - node->getLayout().measuredDimensions[YGDimensionHeight] - + childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] - (node->getLeadingBorder(YGFlexDirectionColumn) + node->getTrailingBorder(YGFlexDirectionColumn)) - - YGUnwrapFloatOptional( - child->getLeadingPosition(YGFlexDirectionColumn, height) + - child->getTrailingPosition(YGFlexDirectionColumn, height)); + (child->getLeadingPosition(YGFlexDirectionColumn, height) + + child->getTrailingPosition(YGFlexDirectionColumn, height)) + .unwrap(); childHeight = YGNodeBoundAxis( child, YGFlexDirectionColumn, childHeight, height, width); } @@ -1597,11 +1598,9 @@ static void YGNodeAbsoluteLayoutChild( "abs-measure", config); childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + - YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionRow, width)); + child->getMarginForAxis(YGFlexDirectionRow, width).unwrap(); childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional( - child->getMarginForAxis(YGFlexDirectionColumn, width)); + child->getMarginForAxis(YGFlexDirectionColumn, width).unwrap(); } YGLayoutNodeInternal( @@ -1623,9 +1622,9 @@ static void YGNodeAbsoluteLayoutChild( node->getLayout().measuredDimensions[dim[mainAxis]] - child->getLayout().measuredDimensions[dim[mainAxis]] - node->getTrailingBorder(mainAxis) - - YGUnwrapFloatOptional(child->getTrailingMargin(mainAxis, width)) - - YGUnwrapFloatOptional(child->getTrailingPosition( - mainAxis, isMainAxisRow ? width : height)), + child->getTrailingMargin(mainAxis, width).unwrap() - + child->getTrailingPosition(mainAxis, isMainAxisRow ? width : height) + .unwrap(), leading[mainAxis]); } else if ( !child->isLeadingPositionDefined(mainAxis) && @@ -1650,9 +1649,10 @@ static void YGNodeAbsoluteLayoutChild( node->getLayout().measuredDimensions[dim[crossAxis]] - child->getLayout().measuredDimensions[dim[crossAxis]] - node->getTrailingBorder(crossAxis) - - YGUnwrapFloatOptional(child->getTrailingMargin(crossAxis, width)) - - YGUnwrapFloatOptional(child->getTrailingPosition( - crossAxis, isMainAxisRow ? height : width)), + child->getTrailingMargin(crossAxis, width).unwrap() - + child + ->getTrailingPosition(crossAxis, isMainAxisRow ? height : width) + .unwrap(), leading[crossAxis]); } else if ( @@ -1691,10 +1691,10 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis( node, YGFlexDirectionColumn, availableWidth); - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, availableWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, availableWidth)); + const float marginAxisRow = + node->getMarginForAxis(YGFlexDirectionRow, availableWidth).unwrap(); + const float marginAxisColumn = + node->getMarginForAxis(YGFlexDirectionColumn, availableWidth).unwrap(); // We want to make sure we don't call measure with negative size const float innerWidth = YGFloatIsUndefined(availableWidth) @@ -1769,10 +1769,10 @@ static void YGNodeEmptyContainerSetMeasuredDimensions( YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth); const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, ownerWidth); - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + const float marginAxisRow = + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); + const float marginAxisColumn = + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap(); node->setLayoutMeasuredDimension( YGNodeBoundAxis( @@ -1813,10 +1813,10 @@ static bool YGNodeFixedSizeSetMeasuredDimensions( heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { - auto marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); - auto marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + auto marginAxisColumn = + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap(); + auto marginAxisRow = + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); node->setLayoutMeasuredDimension( YGNodeBoundAxis( @@ -1872,8 +1872,7 @@ static float YGNodeCalculateAvailableInnerDim( YGDimension dimension = YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight; - const float margin = - YGUnwrapFloatOptional(node->getMarginForAxis(direction, ownerDim)); + const float margin = node->getMarginForAxis(direction, ownerDim).unwrap(); const float paddingAndBorder = YGNodePaddingAndBorderForAxis(node, direction, ownerDim); @@ -1978,9 +1977,10 @@ static float YGNodeComputeFlexBasisForChildren( config); } - totalOuterFlexBasis += YGUnwrapFloatOptional( - child->getLayout().computedFlexBasis + - child->getMarginForAxis(mainAxis, availableInnerWidth)); + totalOuterFlexBasis += + (child->getLayout().computedFlexBasis + + child->getMarginForAxis(mainAxis, availableInnerWidth)) + .unwrap(); } return totalOuterFlexBasis; @@ -2015,14 +2015,15 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( continue; } child->setLineIndex(lineCount); - const float childMarginMainAxis = YGUnwrapFloatOptional( - child->getMarginForAxis(mainAxis, availableInnerWidth)); + const float childMarginMainAxis = + child->getMarginForAxis(mainAxis, availableInnerWidth).unwrap(); const float flexBasisWithMinAndMaxConstraints = - YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + YGNodeBoundAxisWithinMinAndMax( child, mainAxis, - YGUnwrapFloatOptional(child->getLayout().computedFlexBasis), - mainAxisownerSize)); + child->getLayout().computedFlexBasis.unwrap(), + mainAxisownerSize) + .unwrap(); // If this is a multi-line flow and this item pushes us over the // available size, we've @@ -2048,7 +2049,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( // child dimension. flexAlgoRowMeasurement.totalFlexShrinkScaledFactors += -child->resolveFlexShrink() * - YGUnwrapFloatOptional(child->getLayout().computedFlexBasis); + child->getLayout().computedFlexBasis.unwrap(); } flexAlgoRowMeasurement.relativeChildren.push_back(child); @@ -2095,12 +2096,13 @@ static float YGDistributeFreeSpaceSecondPass( const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - YGUnwrapFloatOptional( - currentRelativeChild->getLayout().computedFlexBasis), - mainAxisownerSize)); + childFlexBasis = + YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + currentRelativeChild->getLayout().computedFlexBasis.unwrap(), + mainAxisownerSize) + .unwrap(); float updatedMainSize = childFlexBasis; if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && @@ -2150,10 +2152,12 @@ static float YGDistributeFreeSpaceSecondPass( deltaFreeSpace += updatedMainSize - childFlexBasis; - const float marginMain = YGUnwrapFloatOptional( - currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth)); - const float marginCross = YGUnwrapFloatOptional( - currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth)); + const float marginMain = + currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth) + .unwrap(); + const float marginCross = + currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth) + .unwrap(); float childCrossSize; float childMainSize = updatedMainSize + marginMain; @@ -2189,9 +2193,10 @@ static float YGDistributeFreeSpaceSecondPass( : YGMeasureModeAtMost; } else { childCrossSize = - YGUnwrapFloatOptional(YGResolveValue( + YGResolveValue( currentRelativeChild->getResolvedDimension(dim[crossAxis]), - availableInnerCrossDim)) + + availableInnerCrossDim) + .unwrap() + marginCross; const bool isLoosePercentageMeasurement = currentRelativeChild->getResolvedDimension(dim[crossAxis]).unit == @@ -2271,12 +2276,13 @@ static void YGDistributeFreeSpaceFirstPass( float deltaFreeSpace = 0; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - float childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - YGUnwrapFloatOptional( - currentRelativeChild->getLayout().computedFlexBasis), - mainAxisownerSize)); + float childFlexBasis = + YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + currentRelativeChild->getLayout().computedFlexBasis.unwrap(), + mainAxisownerSize) + .unwrap(); if (collectedFlexItemsValues.remainingFreeSpace < 0) { flexShrinkScaledFactor = @@ -2427,10 +2433,10 @@ static void YGJustifyMainAxis( const float availableInnerWidth, const bool performLayout) { const YGStyle& style = node->getStyle(); - const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(mainAxis, ownerWidth)); - const float trailingPaddingAndBorderMain = YGUnwrapFloatOptional( - node->getTrailingPaddingAndBorder(mainAxis, ownerWidth)); + const float leadingPaddingAndBorderMain = + node->getLeadingPaddingAndBorder(mainAxis, ownerWidth).unwrap(); + const float trailingPaddingAndBorderMain = + node->getTrailingPaddingAndBorder(mainAxis, ownerWidth).unwrap(); // If we are using "at most" rules in the main axis, make sure that // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && @@ -2446,8 +2452,8 @@ static void YGJustifyMainAxis( // `minAvailableMainDim` denotes minimum available space in which child // can be laid out, it will exclude space consumed by padding and border. const float minAvailableMainDim = - YGUnwrapFloatOptional(YGResolveValue( - style.minDimensions[dim[mainAxis]], mainAxisownerSize)) - + YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) + .unwrap() - leadingPaddingAndBorderMain - trailingPaddingAndBorderMain; const float occupiedSpaceByChildNodes = availableInnerMainDim - collectedFlexItemsValues.remainingFreeSpace; @@ -2537,11 +2543,10 @@ static void YGJustifyMainAxis( // defined, we override the position to whatever the user said // (and margin/border). child->setLayoutPosition( - YGUnwrapFloatOptional( - child->getLeadingPosition(mainAxis, availableInnerMainDim)) + + child->getLeadingPosition(mainAxis, availableInnerMainDim) + .unwrap() + node->getLeadingBorder(mainAxis) + - YGUnwrapFloatOptional( - child->getLeadingMargin(mainAxis, availableInnerWidth)), + child->getLeadingMargin(mainAxis, availableInnerWidth).unwrap(), pos[mainAxis]); } } else { @@ -2575,9 +2580,8 @@ static void YGJustifyMainAxis( // they weren't computed. This means we can't call // YGNodeDimWithMargin. collectedFlexItemsValues.mainDim += betweenMainDim + - YGUnwrapFloatOptional(child->getMarginForAxis( - mainAxis, availableInnerWidth)) + - YGUnwrapFloatOptional(childLayout.computedFlexBasis); + child->getMarginForAxis(mainAxis, availableInnerWidth).unwrap() + + childLayout.computedFlexBasis.unwrap(); collectedFlexItemsValues.crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus @@ -2589,12 +2593,16 @@ static void YGJustifyMainAxis( // If the child is baseline aligned then the cross dimension is // calculated by adding maxAscent and maxDescent from the baseline. const float ascent = YGBaseline(child) + - YGUnwrapFloatOptional(child->getLeadingMargin( - YGFlexDirectionColumn, availableInnerWidth)); + child + ->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth) + .unwrap(); const float descent = child->getLayout().measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional(child->getMarginForAxis( - YGFlexDirectionColumn, availableInnerWidth)) - + child + ->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth) + .unwrap() - ascent; maxAscentForCurrentLine = @@ -2747,20 +2755,16 @@ static void YGNodelayoutImpl( YGResolveFlexDirection(YGFlexDirectionColumn, direction); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getLeadingMargin(flexRowDirection, ownerWidth)), + node->getLeadingMargin(flexRowDirection, ownerWidth).unwrap(), YGEdgeStart); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getTrailingMargin(flexRowDirection, ownerWidth)), + node->getTrailingMargin(flexRowDirection, ownerWidth).unwrap(), YGEdgeEnd); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getLeadingMargin(flexColumnDirection, ownerWidth)), + node->getLeadingMargin(flexColumnDirection, ownerWidth).unwrap(), YGEdgeTop); node->setLayoutMargin( - YGUnwrapFloatOptional( - node->getTrailingMargin(flexColumnDirection, ownerWidth)), + node->getTrailingMargin(flexColumnDirection, ownerWidth).unwrap(), YGEdgeBottom); node->setLayoutBorder(node->getLeadingBorder(flexRowDirection), YGEdgeStart); @@ -2770,20 +2774,16 @@ static void YGNodelayoutImpl( node->getTrailingBorder(flexColumnDirection), YGEdgeBottom); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getLeadingPadding(flexRowDirection, ownerWidth)), + node->getLeadingPadding(flexRowDirection, ownerWidth).unwrap(), YGEdgeStart); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getTrailingPadding(flexRowDirection, ownerWidth)), + node->getTrailingPadding(flexRowDirection, ownerWidth).unwrap(), YGEdgeEnd); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getLeadingPadding(flexColumnDirection, ownerWidth)), + node->getLeadingPadding(flexColumnDirection, ownerWidth).unwrap(), YGEdgeTop); node->setLayoutPadding( - YGUnwrapFloatOptional( - node->getTrailingPadding(flexColumnDirection, ownerWidth)), + node->getTrailingPadding(flexColumnDirection, ownerWidth).unwrap(), YGEdgeBottom); if (node->getMeasure() != nullptr) { @@ -2841,8 +2841,8 @@ static void YGNodelayoutImpl( const float mainAxisownerSize = isMainAxisRow ? ownerWidth : ownerHeight; const float crossAxisownerSize = isMainAxisRow ? ownerHeight : ownerWidth; - const float leadingPaddingAndBorderCross = YGUnwrapFloatOptional( - node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)); + const float leadingPaddingAndBorderCross = + node->getLeadingPaddingAndBorder(crossAxis, ownerWidth).unwrap(); const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); const float paddingAndBorderAxisCross = @@ -2858,26 +2858,30 @@ static void YGNodelayoutImpl( const float paddingAndBorderAxisColumn = isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain; - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + const float marginAxisRow = + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); + const float marginAxisColumn = + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap(); const float minInnerWidth = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - + YGResolveValue( + node->getStyle().minDimensions[YGDimensionWidth], ownerWidth) + .unwrap() - paddingAndBorderAxisRow; const float maxInnerWidth = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - + YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth) + .unwrap() - paddingAndBorderAxisRow; const float minInnerHeight = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - + YGResolveValue( + node->getStyle().minDimensions[YGDimensionHeight], ownerHeight) + .unwrap() - paddingAndBorderAxisColumn; const float maxInnerHeight = - YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) - + YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) + .unwrap() - paddingAndBorderAxisColumn; const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; @@ -3088,11 +3092,11 @@ static void YGNodelayoutImpl( child->isLeadingPositionDefined(crossAxis); if (isChildLeadingPosDefined) { child->setLayoutPosition( - YGUnwrapFloatOptional(child->getLeadingPosition( - crossAxis, availableInnerCrossDim)) + + child->getLeadingPosition(crossAxis, availableInnerCrossDim) + .unwrap() + node->getLeadingBorder(crossAxis) + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + child->getLeadingMargin(crossAxis, availableInnerWidth) + .unwrap(), pos[crossAxis]); } // If leading position is not defined or calculations result in Nan, @@ -3101,8 +3105,8 @@ static void YGNodelayoutImpl( YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( node->getLeadingBorder(crossAxis) + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + child->getLeadingMargin(crossAxis, availableInnerWidth) + .unwrap(), pos[crossAxis]); } } else { @@ -3128,16 +3132,17 @@ static void YGNodelayoutImpl( child->getLayout().measuredDimensions[dim[mainAxis]]; float childCrossSize = !child->getStyle().aspectRatio.isUndefined() - ? ((YGUnwrapFloatOptional(child->getMarginForAxis( - crossAxis, availableInnerWidth)) + + ? child->getMarginForAxis(crossAxis, availableInnerWidth) + .unwrap() + (isMainAxisRow ? childMainSize / child->getStyle().aspectRatio.getValue() : childMainSize * - child->getStyle().aspectRatio.getValue()))) + child->getStyle().aspectRatio.getValue()) : collectedFlexItemsValues.crossDim; - childMainSize += YGUnwrapFloatOptional( - child->getMarginForAxis(mainAxis, availableInnerWidth)); + childMainSize += + child->getMarginForAxis(mainAxis, availableInnerWidth) + .unwrap(); YGMeasureMode childMainMeasureMode = YGMeasureModeExactly; YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly; @@ -3279,17 +3284,21 @@ static void YGNodelayoutImpl( lineHeight = YGFloatMax( lineHeight, child->getLayout().measuredDimensions[dim[crossAxis]] + - YGUnwrapFloatOptional(child->getMarginForAxis( - crossAxis, availableInnerWidth))); + child->getMarginForAxis(crossAxis, availableInnerWidth) + .unwrap()); } if (YGNodeAlignItem(node, child) == YGAlignBaseline) { const float ascent = YGBaseline(child) + - YGUnwrapFloatOptional(child->getLeadingMargin( - YGFlexDirectionColumn, availableInnerWidth)); + child + ->getLeadingMargin( + YGFlexDirectionColumn, availableInnerWidth) + .unwrap(); const float descent = child->getLayout().measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional(child->getMarginForAxis( - YGFlexDirectionColumn, availableInnerWidth)) - + child + ->getMarginForAxis( + YGFlexDirectionColumn, availableInnerWidth) + .unwrap() - ascent; maxAscentForCurrentLine = YGFloatMax(maxAscentForCurrentLine, ascent); @@ -3314,16 +3323,16 @@ static void YGNodelayoutImpl( case YGAlignFlexStart: { child->setLayoutPosition( currentLead + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + child->getLeadingMargin(crossAxis, availableInnerWidth) + .unwrap(), pos[crossAxis]); break; } case YGAlignFlexEnd: { child->setLayoutPosition( currentLead + lineHeight - - YGUnwrapFloatOptional(child->getTrailingMargin( - crossAxis, availableInnerWidth)) - + child->getTrailingMargin(crossAxis, availableInnerWidth) + .unwrap() - child->getLayout().measuredDimensions[dim[crossAxis]], pos[crossAxis]); break; @@ -3340,8 +3349,8 @@ static void YGNodelayoutImpl( case YGAlignStretch: { child->setLayoutPosition( currentLead + - YGUnwrapFloatOptional(child->getLeadingMargin( - crossAxis, availableInnerWidth)), + child->getLeadingMargin(crossAxis, availableInnerWidth) + .unwrap(), pos[crossAxis]); // Remeasure child with the line height as it as been only @@ -3351,15 +3360,15 @@ static void YGNodelayoutImpl( const float childWidth = isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionWidth] + - YGUnwrapFloatOptional(child->getMarginForAxis( - mainAxis, availableInnerWidth))) + child->getMarginForAxis(mainAxis, availableInnerWidth) + .unwrap()) : lineHeight; const float childHeight = !isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionHeight] + - YGUnwrapFloatOptional(child->getMarginForAxis( - crossAxis, availableInnerWidth))) + child->getMarginForAxis(crossAxis, availableInnerWidth) + .unwrap()) : lineHeight; if (!(YGFloatsEqual( @@ -3389,8 +3398,10 @@ static void YGNodelayoutImpl( case YGAlignBaseline: { child->setLayoutPosition( currentLead + maxAscentForCurrentLine - YGBaseline(child) + - YGUnwrapFloatOptional(child->getLeadingPosition( - YGFlexDirectionColumn, availableInnerCrossDim)), + child + ->getLeadingPosition( + YGFlexDirectionColumn, availableInnerCrossDim) + .unwrap(), YGEdgeTop); break; @@ -3446,8 +3457,9 @@ static void YGNodelayoutImpl( YGFloatMax( YGFloatMin( availableInnerMainDim + paddingAndBorderAxisMain, - YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( - node, mainAxis, maxLineMainDim, mainAxisownerSize))), + YGNodeBoundAxisWithinMinAndMax( + node, mainAxis, maxLineMainDim, mainAxisownerSize) + .unwrap()), paddingAndBorderAxisMain), dim[mainAxis]); } @@ -3473,11 +3485,12 @@ static void YGNodelayoutImpl( YGFloatMax( YGFloatMin( availableInnerCrossDim + paddingAndBorderAxisCross, - YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax( + YGNodeBoundAxisWithinMinAndMax( node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross, - crossAxisownerSize))), + crossAxisownerSize) + .unwrap()), paddingAndBorderAxisCross), dim[crossAxis]); } @@ -3777,10 +3790,10 @@ bool YGLayoutNodeInternal( // expensive to measure, so it's worth avoiding redundant measurements if at // all possible. if (node->getMeasure() != nullptr) { - const float marginAxisRow = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float marginAxisColumn = YGUnwrapFloatOptional( - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + const float marginAxisRow = + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); + const float marginAxisColumn = + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth).unwrap(); // First, try to use the layout cache. if (YGNodeCanUseCachedMeasurement( @@ -4080,16 +4093,18 @@ void YGNodeCalculateLayout( float width = YGUndefined; YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow, ownerWidth)) { - width = YGUnwrapFloatOptional( - YGResolveValue( - node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) + - node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); + width = + (YGResolveValue( + node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) + + node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)) + .unwrap(); widthMeasureMode = YGMeasureModeExactly; } else if (!YGResolveValue( node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth) .isUndefined()) { - width = YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)); + width = YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth) + .unwrap(); widthMeasureMode = YGMeasureModeAtMost; } else { width = ownerWidth; @@ -4100,18 +4115,19 @@ void YGNodeCalculateLayout( float height = YGUndefined; YGMeasureMode heightMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn, ownerHeight)) { - height = YGUnwrapFloatOptional( - YGResolveValue( - node->getResolvedDimension(dim[YGFlexDirectionColumn]), - ownerHeight) + - node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); + height = (YGResolveValue( + node->getResolvedDimension(dim[YGFlexDirectionColumn]), + ownerHeight) + + node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)) + .unwrap(); heightMeasureMode = YGMeasureModeExactly; } else if (!YGResolveValue( node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) .isUndefined()) { - height = YGUnwrapFloatOptional(YGResolveValue( - node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); + height = YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) + .unwrap(); heightMeasureMode = YGMeasureModeAtMost; } else { height = ownerHeight; From 4b5ae211da43e0257684e24c413c5d9846811c70 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:30 -0800 Subject: [PATCH 133/189] Eliminate `YGFloatOptional::getValue()` Summary: @public Replace `YGFloatOptional::getValue()` with `YGFloatOptional::unwrap()`. `YGFloatOptional::getValue()` has the unfortunate property of calling `std::exit` if the wrapped value is undefined. Here, we eliminate the method, and just call `.unwrap()` everywhere. Reviewed By: shergin Differential Revision: D13439608 fbshipit-source-id: 5ae82b170537d0a10c301412567a7a66fd50bab4 --- tests/YGFloatOptionalTest.cpp | 21 +++++++++--------- yoga/Utils.cpp | 11 ++++----- yoga/Utils.h | 4 ++-- yoga/YGFloatOptional.cpp | 9 -------- yoga/YGFloatOptional.h | 5 ----- yoga/YGNode.cpp | 20 ++++++++--------- yoga/YGNodePrint.cpp | 2 +- yoga/YGStyle.cpp | 8 +++---- yoga/Yoga.cpp | 42 +++++++++++++++++------------------ 9 files changed, 55 insertions(+), 67 deletions(-) diff --git a/tests/YGFloatOptionalTest.cpp b/tests/YGFloatOptionalTest.cpp index 38c7ebb3..3e231723 100644 --- a/tests/YGFloatOptionalTest.cpp +++ b/tests/YGFloatOptionalTest.cpp @@ -17,10 +17,11 @@ constexpr auto positive = YGFloatOptional{1234.5f}; constexpr auto negative = YGFloatOptional{-9876.5f}; TEST(YGFloatOptional, value) { - ASSERT_EQ(zero.getValue(), 0.0f); - ASSERT_EQ(one.getValue(), 1.0f); - ASSERT_EQ(positive.getValue(), 1234.5f); - ASSERT_EQ(negative.getValue(), -9876.5f); + ASSERT_TRUE(YGFloatIsUndefined(empty.unwrap())); + ASSERT_EQ(zero.unwrap(), 0.0f); + ASSERT_EQ(one.unwrap(), 1.0f); + ASSERT_EQ(positive.unwrap(), 1234.5f); + ASSERT_EQ(negative.unwrap(), -9876.5f); ASSERT_TRUE(empty.isUndefined()); ASSERT_FALSE(zero.isUndefined()); @@ -46,11 +47,11 @@ TEST(YGFloatOptional, equality) { ASSERT_FALSE(one == positive); ASSERT_TRUE(positive == positive); - ASSERT_TRUE(positive == positive.getValue()); + ASSERT_TRUE(positive == positive.unwrap()); ASSERT_FALSE(positive == one); ASSERT_TRUE(negative == negative); - ASSERT_TRUE(negative == negative.getValue()); + ASSERT_TRUE(negative == negative.unwrap()); ASSERT_FALSE(negative == zero); } @@ -71,11 +72,11 @@ TEST(YGFloatOptional, inequality) { ASSERT_TRUE(one != positive); ASSERT_FALSE(positive != positive); - ASSERT_FALSE(positive != positive.getValue()); + ASSERT_FALSE(positive != positive.unwrap()); ASSERT_TRUE(positive != one); ASSERT_FALSE(negative != negative); - ASSERT_FALSE(negative != negative.getValue()); + ASSERT_FALSE(negative != negative.unwrap()); ASSERT_TRUE(negative != zero); } @@ -180,8 +181,8 @@ TEST(YGFloatOptional, less_than_equals) { } TEST(YGFloatOptional, addition) { - auto n = negative.getValue(); - auto p = positive.getValue(); + auto n = negative.unwrap(); + auto p = positive.unwrap(); ASSERT_EQ(zero + one, one); ASSERT_EQ(negative + positive, YGFloatOptional{n + p}); diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 331cb660..2035fe00 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -55,11 +55,12 @@ float YGFloatSanitize(const float val) { return yoga::isUndefined(val) ? 0 : val; } -YGFloatOptional YGFloatOptionalMax( - const YGFloatOptional& op1, - const YGFloatOptional& op2) { - if (!op1.isUndefined() && !op2.isUndefined()) { - return op1.getValue() > op2.getValue() ? op1 : op2; +YGFloatOptional YGFloatOptionalMax(YGFloatOptional op1, YGFloatOptional op2) { + if (op1 >= op2) { + return op1; + } + if (op2 > op1) { + return op2; } return op1.isUndefined() ? op2 : op1; } diff --git a/yoga/Utils.h b/yoga/Utils.h index e5e20ba3..9ea7a738 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -60,8 +60,8 @@ bool YGFloatsEqual(const float a, const float b); float YGFloatMax(const float a, const float b); YGFloatOptional YGFloatOptionalMax( - const YGFloatOptional& op1, - const YGFloatOptional& op2); + const YGFloatOptional op1, + const YGFloatOptional op2); float YGFloatMin(const float a, const float b); diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index 0bf89f29..d202d4d5 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -12,15 +12,6 @@ using namespace facebook; -float YGFloatOptional::getValue() const { - if (isUndefined()) { - // Abort, accessing a value of an undefined float optional - std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; - std::exit(EXIT_FAILURE); - } - return value_; -} - bool YGFloatOptional::operator==(YGFloatOptional op) const { return value_ == op.value_ || (isUndefined() && op.isUndefined()); } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 56bc8557..b4974798 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -17,11 +17,6 @@ struct YGFloatOptional { explicit constexpr YGFloatOptional(float value) : value_(value) {} constexpr YGFloatOptional() = default; - // Program will terminate if the value of an undefined is accessed. Please - // make sure to check if the optional is defined before calling this function. - // To check if float optional is defined, use `isUndefined()`. - float getValue() const; - // returns the wrapped value, or a value x with YGIsUndefined(x) == true float unwrap() const { return value_; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index d930c51a..3da72cb6 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -211,7 +211,7 @@ YGFloatOptional YGNode::relativePosition( YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize); if (!trailingPosition.isUndefined()) { - trailingPosition = YGFloatOptional{-1 * trailingPosition.getValue()}; + trailingPosition = YGFloatOptional{-1 * trailingPosition.unwrap()}; } return trailingPosition; } @@ -302,7 +302,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) { return flexBasis; } - if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) { + if (!style_.flex.isUndefined() && style_.flex.unwrap() > 0.0f) { return config_->useWebDefaults ? YGValueAuto : YGValueZero; } return YGValueAuto; @@ -393,10 +393,10 @@ float YGNode::resolveFlexGrow() { return 0.0; } if (!style_.flexGrow.isUndefined()) { - return style_.flexGrow.getValue(); + return style_.flexGrow.unwrap(); } - if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) { - return style_.flex.getValue(); + if (!style_.flex.isUndefined() && style_.flex.unwrap() > 0.0f) { + return style_.flex.unwrap(); } return kDefaultFlexGrow; } @@ -406,11 +406,11 @@ float YGNode::resolveFlexShrink() { return 0.0; } if (!style_.flexShrink.isUndefined()) { - return style_.flexShrink.getValue(); + return style_.flexShrink.unwrap(); } if (!config_->useWebDefaults && !style_.flex.isUndefined() && - style_.flex.getValue() < 0.0f) { - return -style_.flex.getValue(); + style_.flex.unwrap() < 0.0f) { + return -style_.flex.unwrap(); } return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink; } @@ -455,7 +455,7 @@ YGFloatOptional YGNode::getLeadingPadding( YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && style_.padding[YGEdgeStart].unit != YGUnitUndefined && - !paddingEdgeStart.isUndefined() && paddingEdgeStart.getValue() >= 0.0f) { + !paddingEdgeStart.isUndefined() && paddingEdgeStart.unwrap() >= 0.0f) { return paddingEdgeStart; } @@ -471,7 +471,7 @@ YGFloatOptional YGNode::getTrailingPadding( if (YGFlexDirectionIsRow(axis) && style_.padding[YGEdgeEnd].unit != YGUnitUndefined && !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() && - YGResolveValue(style_.padding[YGEdgeEnd], widthSize).getValue() >= 0.0f) { + YGResolveValue(style_.padding[YGEdgeEnd], widthSize).unwrap() >= 0.0f) { return YGResolveValue(style_.padding[YGEdgeEnd], widthSize); } diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 541a6fef..8eb33f93 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -43,7 +43,7 @@ static void appendFloatOptionalIfDefined( const string key, const YGFloatOptional num) { if (!num.isUndefined()) { - appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue()); + appendFormatedString(base, "%s: %g; ", key.c_str(), num.unwrap()); } } diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index bc90463e..78df8b01 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -28,26 +28,26 @@ bool YGStyle::operator==(const YGStyle& style) { if (areNonFloatValuesEqual && !flex.isUndefined() && !style.flex.isUndefined()) { areNonFloatValuesEqual = - areNonFloatValuesEqual && flex.getValue() == style.flex.getValue(); + areNonFloatValuesEqual && flex == style.flex; } areNonFloatValuesEqual = areNonFloatValuesEqual && flexGrow.isUndefined() == style.flexGrow.isUndefined(); if (areNonFloatValuesEqual && !flexGrow.isUndefined()) { areNonFloatValuesEqual = areNonFloatValuesEqual && - flexGrow.getValue() == style.flexGrow.getValue(); + flexGrow == style.flexGrow; } areNonFloatValuesEqual = areNonFloatValuesEqual && flexShrink.isUndefined() == style.flexShrink.isUndefined(); if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) { areNonFloatValuesEqual = areNonFloatValuesEqual && - flexShrink.getValue() == style.flexShrink.getValue(); + flexShrink == style.flexShrink; } if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) { areNonFloatValuesEqual = areNonFloatValuesEqual && - aspectRatio.getValue() == style.aspectRatio.getValue(); + aspectRatio == style.aspectRatio; } return areNonFloatValuesEqual; diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 8db18e9e..abc4ae74 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -581,14 +581,14 @@ void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) { float YGNodeStyleGetFlexGrow(const YGNodeRef node) { return node->getStyle().flexGrow.isUndefined() ? kDefaultFlexGrow - : node->getStyle().flexGrow.getValue(); + : node->getStyle().flexGrow.unwrap(); } float YGNodeStyleGetFlexShrink(const YGNodeRef node) { return node->getStyle().flexShrink.isUndefined() ? (node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink) - : node->getStyle().flexShrink.getValue(); + : node->getStyle().flexShrink.unwrap(); } namespace { @@ -857,7 +857,7 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { // TODO(T26792433): Change the API to accept YGFloatOptional. float YGNodeStyleGetFlex(const YGNodeRef node) { return node->getStyle().flex.isUndefined() ? YGUndefined - : node->getStyle().flex.getValue(); + : node->getStyle().flex.unwrap(); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -959,7 +959,7 @@ float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) { // TODO(T26792433): Change the API to accept YGFloatOptional. float YGNodeStyleGetAspectRatio(const YGNodeRef node) { const YGFloatOptional op = node->getStyle().aspectRatio; - return op.isUndefined() ? YGUndefined : op.getValue(); + return op.isUndefined() ? YGUndefined : op.unwrap(); } // TODO(T26792433): Change the API to accept YGFloatOptional. @@ -1229,11 +1229,11 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( node->getStyle().maxDimensions[YGDimensionWidth], axisSize); } - if (!max.isUndefined() && max.getValue() >= 0 && value > max.getValue()) { + if (!max.isUndefined() && max.unwrap() >= 0 && value > max.unwrap()) { return max; } - if (!min.isUndefined() && min.getValue() >= 0 && value < min.getValue()) { + if (!min.isUndefined() && min.unwrap() >= 0 && value < min.unwrap()) { return min; } @@ -1277,14 +1277,14 @@ static void YGConstrainMaxSizeForMode( switch (*mode) { case YGMeasureModeExactly: case YGMeasureModeAtMost: - *size = (maxSize.isUndefined() || *size < maxSize.getValue()) + *size = (maxSize.isUndefined() || *size < maxSize.unwrap()) ? *size - : maxSize.getValue(); + : maxSize.unwrap(); break; case YGMeasureModeUndefined: if (!maxSize.isUndefined()) { *mode = YGMeasureModeAtMost; - *size = maxSize.getValue(); + *size = maxSize.unwrap(); } break; } @@ -1399,13 +1399,13 @@ static void YGNodeComputeFlexBasisForChild( if (!child->getStyle().aspectRatio.isUndefined()) { if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) { childHeight = marginColumn + - (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); + (childWidth - marginRow) / child->getStyle().aspectRatio.unwrap(); childHeightMeasureMode = YGMeasureModeExactly; } else if ( isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { childWidth = marginRow + (childHeight - marginColumn) * - child->getStyle().aspectRatio.getValue(); + child->getStyle().aspectRatio.unwrap(); childWidthMeasureMode = YGMeasureModeExactly; } } @@ -1425,7 +1425,7 @@ static void YGNodeComputeFlexBasisForChild( childWidthMeasureMode = YGMeasureModeExactly; if (!child->getStyle().aspectRatio.isUndefined()) { childHeight = - (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); + (childWidth - marginRow) / child->getStyle().aspectRatio.unwrap(); childHeightMeasureMode = YGMeasureModeExactly; } } @@ -1442,7 +1442,7 @@ static void YGNodeComputeFlexBasisForChild( if (!child->getStyle().aspectRatio.isUndefined()) { childWidth = (childHeight - marginColumn) * - child->getStyle().aspectRatio.getValue(); + child->getStyle().aspectRatio.unwrap(); childWidthMeasureMode = YGMeasureModeExactly; } } @@ -1557,10 +1557,10 @@ static void YGNodeAbsoluteLayoutChild( if (YGFloatIsUndefined(childWidth)) { childWidth = marginRow + (childHeight - marginColumn) * - child->getStyle().aspectRatio.getValue(); + child->getStyle().aspectRatio.unwrap(); } else if (YGFloatIsUndefined(childHeight)) { childHeight = marginColumn + - (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); + (childWidth - marginRow) / child->getStyle().aspectRatio.unwrap(); } } } @@ -1886,14 +1886,14 @@ static float YGNodeCalculateAvailableInnerDim( YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); const float minInnerDim = minDimensionOptional.isUndefined() ? 0.0f - : minDimensionOptional.getValue() - paddingAndBorder; + : minDimensionOptional.unwrap() - paddingAndBorder; const YGFloatOptional maxDimensionOptional = YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim); const float maxInnerDim = maxDimensionOptional.isUndefined() ? FLT_MAX - : maxDimensionOptional.getValue() - paddingAndBorder; + : maxDimensionOptional.unwrap() - paddingAndBorder; availableInnerDim = YGFloatMax(YGFloatMin(availableInnerDim, maxInnerDim), minInnerDim); } @@ -2166,9 +2166,9 @@ static float YGDistributeFreeSpaceSecondPass( if (!currentRelativeChild->getStyle().aspectRatio.isUndefined()) { childCrossSize = isMainAxisRow ? (childMainSize - marginMain) / - currentRelativeChild->getStyle().aspectRatio.getValue() + currentRelativeChild->getStyle().aspectRatio.unwrap() : (childMainSize - marginMain) * - currentRelativeChild->getStyle().aspectRatio.getValue(); + currentRelativeChild->getStyle().aspectRatio.unwrap(); childCrossMeasureMode = YGMeasureModeExactly; childCrossSize += marginCross; @@ -3135,9 +3135,9 @@ static void YGNodelayoutImpl( ? child->getMarginForAxis(crossAxis, availableInnerWidth) .unwrap() + (isMainAxisRow ? childMainSize / - child->getStyle().aspectRatio.getValue() + child->getStyle().aspectRatio.unwrap() : childMainSize * - child->getStyle().aspectRatio.getValue()) + child->getStyle().aspectRatio.unwrap()) : collectedFlexItemsValues.crossDim; childMainSize += From 236bcc1a39421d66cc5b4a8bef6d428873820f71 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:30 -0800 Subject: [PATCH 134/189] Pass `YGFloatOptional` by value, not reference Summary: @public `YGFloatOptional` is a 32bit type now, and can be passed by value efficiently. Reviewed By: SidharthGuglani Differential Revision: D13439603 fbshipit-source-id: e12539ad5b3cccbd5bc27869866ca66c023b24a7 --- yoga/YGNode.cpp | 13 ++++++------- yoga/YGNode.h | 2 +- yoga/Yoga.cpp | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 3da72cb6..1a08fab8 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -175,7 +175,7 @@ void YGNode::setLayoutLastOwnerDirection(YGDirection direction) { } void YGNode::setLayoutComputedFlexBasis( - const YGFloatOptional& computedFlexBasis) { + const YGFloatOptional computedFlexBasis) { layout_.computedFlexBasis = computedFlexBasis; } @@ -451,7 +451,7 @@ float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { YGFloatOptional YGNode::getLeadingPadding( const YGFlexDirection axis, const float widthSize) const { - const YGFloatOptional& paddingEdgeStart = + const YGFloatOptional paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && style_.padding[YGEdgeStart].unit != YGUnitUndefined && @@ -468,11 +468,10 @@ YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getTrailingPadding( const YGFlexDirection axis, const float widthSize) const { - if (YGFlexDirectionIsRow(axis) && - style_.padding[YGEdgeEnd].unit != YGUnitUndefined && - !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() && - YGResolveValue(style_.padding[YGEdgeEnd], widthSize).unwrap() >= 0.0f) { - return YGResolveValue(style_.padding[YGEdgeEnd], widthSize); + const YGFloatOptional paddingEdgeEnd = + YGResolveValue(style_.padding[YGEdgeEnd], widthSize); + if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) { + return paddingEdgeEnd; } YGFloatOptional resolvedValue = YGResolveValue( diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 719eb2ea..57312812 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -235,7 +235,7 @@ struct YGNode { void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); - void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis); + void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis); void setLayoutComputedFlexBasisGeneration( uint32_t computedFlexBasisGeneration); void setLayoutMeasuredDimension(float measuredDimension, int index); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index abc4ae74..653f47e7 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1325,14 +1325,14 @@ static void YGNodeComputeFlexBasisForChild( child->getConfig(), YGExperimentalFeatureWebFlexBasis) && child->getLayout().computedFlexBasisGeneration != gCurrentGenerationCount)) { - const YGFloatOptional& paddingAndBorder = YGFloatOptional( + const YGFloatOptional paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)); child->setLayoutComputedFlexBasis( YGFloatOptionalMax(resolvedFlexBasis, paddingAndBorder)); } } else if (isMainAxisRow && isRowStyleDimDefined) { // The width is definite, so use that as the flex basis. - const YGFloatOptional& paddingAndBorder = YGFloatOptional( + const YGFloatOptional paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, ownerWidth)); child->setLayoutComputedFlexBasis(YGFloatOptionalMax( @@ -1341,7 +1341,7 @@ static void YGNodeComputeFlexBasisForChild( paddingAndBorder)); } else if (!isMainAxisRow && isColumnStyleDimDefined) { // The height is definite, so use that as the flex basis. - const YGFloatOptional& paddingAndBorder = + const YGFloatOptional paddingAndBorder = YGFloatOptional(YGNodePaddingAndBorderForAxis( child, YGFlexDirectionColumn, ownerWidth)); child->setLayoutComputedFlexBasis(YGFloatOptionalMax( From 96d93f29826257ff6e9bb6c19211adb423029c29 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 135/189] Inline `YGFloatOptional` completely Summary: @public `YGFLoatOptional` only contains trivial functionality. Make it header-only. Reviewed By: SidharthGuglani Differential Revision: D13439609 fbshipit-source-id: 3f3c6c3a15e05ac55da2af30eb629f786ecb90a9 --- yoga/YGFloatOptional.cpp | 49 ---------------------------------------- yoga/YGFloatOptional.h | 39 ++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 59 deletions(-) delete mode 100644 yoga/YGFloatOptional.cpp diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp deleted file mode 100644 index d202d4d5..00000000 --- a/yoga/YGFloatOptional.cpp +++ /dev/null @@ -1,49 +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 "YGFloatOptional.h" -#include -#include -#include "Yoga-internal.h" -#include "Yoga.h" - -using namespace facebook; - -bool YGFloatOptional::operator==(YGFloatOptional op) const { - return value_ == op.value_ || (isUndefined() && op.isUndefined()); -} - -bool YGFloatOptional::operator!=(YGFloatOptional op) const { - return !(*this == op); -} - -bool YGFloatOptional::operator==(float val) const { - return value_ == val || (isUndefined() && yoga::isUndefined(val)); -} - -bool YGFloatOptional::operator!=(float val) const { - return !(*this == val); -} - -YGFloatOptional YGFloatOptional::operator+(YGFloatOptional op) const { - return YGFloatOptional{value_ + op.value_}; -} - -bool YGFloatOptional::operator>(YGFloatOptional op) const { - return value_ > op.value_; -} - -bool YGFloatOptional::operator<(YGFloatOptional op) const { - return value_ < op.value_; -} - -bool YGFloatOptional::operator>=(YGFloatOptional op) const { - return *this > op || *this == op; -} - -bool YGFloatOptional::operator<=(YGFloatOptional op) const { - return *this < op || *this == op; -} diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index b4974798..44cf344e 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -8,6 +8,7 @@ #include #include +#include "Yoga-internal.h" struct YGFloatOptional { private: @@ -18,7 +19,7 @@ struct YGFloatOptional { constexpr YGFloatOptional() = default; // returns the wrapped value, or a value x with YGIsUndefined(x) == true - float unwrap() const { + constexpr float unwrap() const { return value_; } @@ -26,14 +27,32 @@ struct YGFloatOptional { return std::isnan(value_); } - YGFloatOptional operator+(YGFloatOptional op) const; - bool operator>(YGFloatOptional op) const; - bool operator<(YGFloatOptional op) const; - bool operator>=(YGFloatOptional op) const; - bool operator<=(YGFloatOptional op) const; - bool operator==(YGFloatOptional op) const; - bool operator!=(YGFloatOptional op) const; + YGFloatOptional operator+(YGFloatOptional op) const { + return YGFloatOptional{value_ + op.value_}; + } + bool operator>(YGFloatOptional op) const { + return value_ > op.value_; + } + bool operator<(YGFloatOptional op) const { + return value_ < op.value_; + } + bool operator>=(YGFloatOptional op) const { + return *this > op || *this == op; + } + bool operator<=(YGFloatOptional op) const { + return *this < op || *this == op; + } + bool operator==(YGFloatOptional op) const { + return value_ == op.value_ || (isUndefined() && op.isUndefined()); + } + bool operator!=(YGFloatOptional op) const { + return !(*this == op); + } - bool operator==(float val) const; - bool operator!=(float val) const; + bool operator==(float val) const { + return value_ == val || (isUndefined() && yoga::isUndefined(val)); + } + bool operator!=(float val) const { + return !(*this == val); + } }; From 3f794397185359cb111f6e4a664db123071b6b92 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 136/189] Get rid of `static_cast` in `YGResolveValue` Summary: @public Removes `static_cast` from `YGResolveValue` Reviewed By: SidharthGuglani Differential Revision: D13439605 fbshipit-source-id: 8736541c8e1d43fd698d368cb4f3211ffd929364 --- yoga/Utils.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/yoga/Utils.h b/yoga/Utils.h index 9ea7a738..fed3c1fb 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -95,16 +95,13 @@ inline YGFloatOptional YGResolveValue( const YGValue value, const float ownerSize) { switch (value.unit) { - case YGUnitUndefined: - case YGUnitAuto: - return YGFloatOptional(); case YGUnitPoint: - return YGFloatOptional(value.value); + return YGFloatOptional{value.value}; case YGUnitPercent: - return YGFloatOptional( - static_cast(value.value * ownerSize * 0.01)); + return YGFloatOptional{value.value * ownerSize * 0.01f}; + default: + return YGFloatOptional{}; } - return YGFloatOptional(); } inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) { From 852db1d885943324db7eb50ddc6c6df124a60e6c Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 137/189] Remove unnecessary `static` keyword MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public Header-declared inline functions shouldn’t be decleared `static` Reviewed By: SidharthGuglani Differential Revision: D13439607 fbshipit-source-id: 89555bb19a3fff6e29ca4afc10fe15fecca8fa17 --- yoga/Utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yoga/Utils.h b/yoga/Utils.h index fed3c1fb..a0d49235 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -123,7 +123,7 @@ inline YGFlexDirection YGResolveFlexDirection( return flexDirection; } -static inline YGFloatOptional YGResolveValueMargin( +inline YGFloatOptional YGResolveValueMargin( const YGValue value, const float ownerSize) { return value.unit == YGUnitAuto ? YGFloatOptional(0) From e96d14395c0af54579a38926a44bbf07a97359fb Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 138/189] `YGNodeBoundAxisWithinMinAndMax` accepts `YGFloatOptional` Summary: @public Saves some calls to `.unwrap()` Reviewed By: SidharthGuglani Differential Revision: D13439600 fbshipit-source-id: ce0f6bad9a0709e9d64e23d8349bc2423b9b2ad4 --- yoga/Yoga.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 653f47e7..bc457b1f 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1212,7 +1212,7 @@ static inline bool YGNodeIsLayoutDimDefined( static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( const YGNodeRef node, const YGFlexDirection axis, - const float value, + const YGFloatOptional value, const float axisSize) { YGFloatOptional min; YGFloatOptional max; @@ -1229,15 +1229,15 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( node->getStyle().maxDimensions[YGDimensionWidth], axisSize); } - if (!max.isUndefined() && max.unwrap() >= 0 && value > max.unwrap()) { + if (max >= YGFloatOptional{0} && value > max) { return max; } - if (!min.isUndefined() && min.unwrap() >= 0 && value < min.unwrap()) { + if (min >= YGFloatOptional{0} && value < min) { return min; } - return YGFloatOptional(value); + return value; } // Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't @@ -1249,7 +1249,9 @@ static inline float YGNodeBoundAxis( const float axisSize, const float widthSize) { return YGFloatMax( - YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize).unwrap(), + YGNodeBoundAxisWithinMinAndMax( + node, axis, YGFloatOptional{value}, axisSize) + .unwrap(), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } @@ -2021,7 +2023,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( YGNodeBoundAxisWithinMinAndMax( child, mainAxis, - child->getLayout().computedFlexBasis.unwrap(), + child->getLayout().computedFlexBasis, mainAxisownerSize) .unwrap(); @@ -2096,13 +2098,12 @@ static float YGDistributeFreeSpaceSecondPass( const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap; for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) { - childFlexBasis = - YGNodeBoundAxisWithinMinAndMax( - currentRelativeChild, - mainAxis, - currentRelativeChild->getLayout().computedFlexBasis.unwrap(), - mainAxisownerSize) - .unwrap(); + childFlexBasis = YGNodeBoundAxisWithinMinAndMax( + currentRelativeChild, + mainAxis, + currentRelativeChild->getLayout().computedFlexBasis, + mainAxisownerSize) + .unwrap(); float updatedMainSize = childFlexBasis; if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) && @@ -2280,7 +2281,7 @@ static void YGDistributeFreeSpaceFirstPass( YGNodeBoundAxisWithinMinAndMax( currentRelativeChild, mainAxis, - currentRelativeChild->getLayout().computedFlexBasis.unwrap(), + currentRelativeChild->getLayout().computedFlexBasis, mainAxisownerSize) .unwrap(); @@ -3458,7 +3459,10 @@ static void YGNodelayoutImpl( YGFloatMin( availableInnerMainDim + paddingAndBorderAxisMain, YGNodeBoundAxisWithinMinAndMax( - node, mainAxis, maxLineMainDim, mainAxisownerSize) + node, + mainAxis, + YGFloatOptional{maxLineMainDim}, + mainAxisownerSize) .unwrap()), paddingAndBorderAxisMain), dim[mainAxis]); @@ -3488,7 +3492,8 @@ static void YGNodelayoutImpl( YGNodeBoundAxisWithinMinAndMax( node, crossAxis, - totalLineCrossDim + paddingAndBorderAxisCross, + YGFloatOptional{totalLineCrossDim + + paddingAndBorderAxisCross}, crossAxisownerSize) .unwrap()), paddingAndBorderAxisCross), From 4f51871fa8f2bd5f8b47000bfd769e74b8225f7e Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 139/189] Remove templates for setting/getting style properties Summary: @public Replaces the `StyleProp` template with a simple setter macro / inlined getter code. The template was introduced to replace more extensive macros that would generate function signatures, too. Here, we keep the spirit of that change by only generating function bodies. Reviewed By: SidharthGuglani Differential Revision: D13439612 fbshipit-source-id: 36f6a86917d035be6891cb736d1f288d8e02f5cf --- yoga/Yoga.cpp | 63 ++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index bc457b1f..3356a811 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -593,19 +593,6 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { namespace { -template -struct StyleProp { - static T get(YGNodeRef node) { - return node->getStyle().*P; - } - static void set(YGNodeRef node, T newValue) { - if (node->getStyle().*P != newValue) { - node->getStyle().*P = newValue; - node->markDirtyAndPropogate(); - } - } -}; - struct Value { template static YGValue create(float value) { @@ -765,84 +752,88 @@ struct DimensionProp { return node->getLayout().instanceName[edge]; \ } -void YGNodeStyleSetDirection( - const YGNodeRef node, - const YGDirection direction) { - StyleProp::set(node, direction); +#define YG_NODE_STYLE_SET(node, property, value) \ + if (node->getStyle().property != value) { \ + node->getStyle().property = value; \ + node->markDirtyAndPropogate(); \ + } + +void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { + YG_NODE_STYLE_SET(node, direction, value); } YGDirection YGNodeStyleGetDirection(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().direction; } void YGNodeStyleSetFlexDirection( const YGNodeRef node, const YGFlexDirection flexDirection) { - StyleProp::set(node, flexDirection); + YG_NODE_STYLE_SET(node, flexDirection, flexDirection); } YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().flexDirection; } void YGNodeStyleSetJustifyContent( const YGNodeRef node, const YGJustify justifyContent) { - StyleProp::set(node, justifyContent); + YG_NODE_STYLE_SET(node, justifyContent, justifyContent); } YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().justifyContent; } void YGNodeStyleSetAlignContent( const YGNodeRef node, const YGAlign alignContent) { - StyleProp::set(node, alignContent); + YG_NODE_STYLE_SET(node, alignContent, alignContent); } YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().alignContent; } void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { - StyleProp::set(node, alignItems); + YG_NODE_STYLE_SET(node, alignItems, alignItems); } YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().alignItems; } void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { - StyleProp::set(node, alignSelf); + YG_NODE_STYLE_SET(node, alignSelf, alignSelf); } YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().alignSelf; } void YGNodeStyleSetPositionType( const YGNodeRef node, const YGPositionType positionType) { - StyleProp::set(node, positionType); + YG_NODE_STYLE_SET(node, positionType, positionType); } YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().positionType; } void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { - StyleProp::set(node, flexWrap); + YG_NODE_STYLE_SET(node, flexWrap, flexWrap); } YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().flexWrap; } void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { - StyleProp::set(node, overflow); + YG_NODE_STYLE_SET(node, overflow, overflow); } YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().overflow; } void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { - StyleProp::set(node, display); + YG_NODE_STYLE_SET(node, display, display); } YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) { - return StyleProp::get(node); + return node->getStyle().display; } // TODO(T26792433): Change the API to accept YGFloatOptional. From dd97fcc96825d0eb7e3fdd1ffb20b150c049bdf0 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 140/189] Use bitfields for enum members of `YGStyle` Summary: @public Puts all enum fields of `YGStyle` into bitfields. This saves 36 bytes (> 3%) per node. Reviewed By: SidharthGuglani Differential Revision: D13439606 fbshipit-source-id: b60a5444762041bc6f8cc5e04757034cb6893b30 --- yoga/YGStyle.h | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index c3a01d44..c4f7e3c7 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -30,16 +30,16 @@ constexpr std::array kYGDefaultDimensionValuesUnit = { struct YGStyle { using Dimensions = std::array; - YGDirection direction = YGDirectionInherit; - YGFlexDirection flexDirection = YGFlexDirectionColumn; - YGJustify justifyContent = YGJustifyFlexStart; - YGAlign alignContent = YGAlignFlexStart; - YGAlign alignItems = YGAlignStretch; - YGAlign alignSelf = YGAlignAuto; - YGPositionType positionType = YGPositionTypeRelative; - YGWrap flexWrap = YGWrapNoWrap; - YGOverflow overflow = YGOverflowVisible; - YGDisplay display = YGDisplayFlex; + YGDirection direction : 2; + YGFlexDirection flexDirection : 2; + YGJustify justifyContent : 3; + YGAlign alignContent : 3; + YGAlign alignItems : 3; + YGAlign alignSelf : 3; + YGPositionType positionType : 1; + YGWrap flexWrap : 2; + YGOverflow overflow : 2; + YGDisplay display : 1; YGFloatOptional flex = {}; YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; @@ -54,7 +54,17 @@ struct YGStyle { // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio = {}; - YGStyle() = default; + YGStyle() + : direction(YGDirectionInherit), + flexDirection(YGFlexDirectionColumn), + justifyContent(YGJustifyFlexStart), + alignContent(YGAlignFlexStart), + alignItems(YGAlignStretch), + alignSelf(YGAlignAuto), + positionType(YGPositionTypeRelative), + flexWrap(YGWrapNoWrap), + overflow(YGOverflowVisible), + display(YGDisplayFlex) {} bool operator==(const YGStyle& style); bool operator!=(YGStyle style) { From 130a9a2aa201938ed7aaa56319e861cc0f6648c5 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 07:09:31 -0800 Subject: [PATCH 141/189] Don't pass `std::string` by pointer Summary: @public Pass strings by mutable ref rather than pointer. Reviewed By: SidharthGuglani Differential Revision: D13439613 fbshipit-source-id: ea889abe0fe8ec44ae02f13c1d9a10c0dbfdbcf1 --- yoga/YGNodePrint.cpp | 27 +++++++++++++-------------- yoga/YGNodePrint.h | 2 +- yoga/Yoga.cpp | 2 +- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 8eb33f93..753a00b6 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -14,9 +14,9 @@ namespace facebook { namespace yoga { typedef std::string string; -static void indent(string* base, uint32_t level) { +static void indent(string& base, uint32_t level) { for (uint32_t i = 0; i < level; ++i) { - base->append(" "); + base.append(" "); } } @@ -25,7 +25,7 @@ static bool areFourValuesEqual(const std::array& four) { YGValueEqual(four[0], four[3]); } -static void appendFormatedString(string* str, const char* fmt, ...) { +static void appendFormatedString(string& str, const char* fmt, ...) { va_list args; va_start(args, fmt); va_list argsCopy; @@ -35,11 +35,11 @@ static void appendFormatedString(string* str, const char* fmt, ...) { vsnprintf(buf.data(), buf.size(), fmt, argsCopy); va_end(argsCopy); string result = string(buf.begin(), buf.end() - 1); - str->append(result); + str.append(result); } static void appendFloatOptionalIfDefined( - string* base, + string& base, const string key, const YGFloatOptional num) { if (!num.isUndefined()) { @@ -48,12 +48,12 @@ static void appendFloatOptionalIfDefined( } static void appendNumberIfNotUndefined( - string* base, + string& base, const string key, const YGValue number) { if (number.unit != YGUnitUndefined) { if (number.unit == YGUnitAuto) { - base->append(key + ": auto; "); + base.append(key + ": auto; "); } else { string unit = number.unit == YGUnitPoint ? "px" : "%%"; appendFormatedString( @@ -63,24 +63,23 @@ static void appendNumberIfNotUndefined( } static void -appendNumberIfNotAuto(string* base, const string& key, const YGValue number) { +appendNumberIfNotAuto(string& base, const string& key, const YGValue number) { if (number.unit != YGUnitAuto) { appendNumberIfNotUndefined(base, key, number); } } static void -appendNumberIfNotZero(string* base, const string& str, const YGValue number) { - +appendNumberIfNotZero(string& base, const string& str, const YGValue number) { if (number.unit == YGUnitAuto) { - base->append(str + ": auto; "); + base.append(str + ": auto; "); } else if (!YGFloatsEqual(number.value, 0)) { appendNumberIfNotUndefined(base, str, number); } } static void appendEdges( - string* base, + string& base, const string& key, const std::array& edges) { if (areFourValuesEqual(edges)) { @@ -94,7 +93,7 @@ static void appendEdges( } static void appendEdgeIfNotUndefined( - string* base, + string& base, const string& str, const std::array& edges, const YGEdge edge) { @@ -103,7 +102,7 @@ static void appendEdgeIfNotUndefined( } void YGNodeToString( - std::string* str, + std::string& str, YGNodeRef node, YGPrintOptions options, uint32_t level) { diff --git a/yoga/YGNodePrint.h b/yoga/YGNodePrint.h index 9d36ba8d..9615bf8e 100644 --- a/yoga/YGNodePrint.h +++ b/yoga/YGNodePrint.h @@ -13,7 +13,7 @@ namespace facebook { namespace yoga { void YGNodeToString( - std::string* str, + std::string& str, YGNodeRef node, YGPrintOptions options, uint32_t level); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 3356a811..4a1a98a2 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1060,7 +1060,7 @@ static void YGNodePrintInternal( const YGNodeRef node, const YGPrintOptions options) { std::string str; - facebook::yoga::YGNodeToString(&str, node, options, 0); + facebook::yoga::YGNodeToString(str, node, options, 0); YGLog(node, YGLogLevelDebug, str.c_str()); } From c5f24440489aaad73f3d3fa4f50a6eed07de95f7 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 13 Dec 2018 10:38:10 -0800 Subject: [PATCH 142/189] Don't use `default` in exhaustive switch Summary: @public removes the `default` case from an already exhaustive switch. Reviewed By: SidharthGuglani Differential Revision: D13451869 fbshipit-source-id: 32727330c7fce013963f5c83c95a73b230d5c938 --- yoga/YGValue.h | 1 - 1 file changed, 1 deletion(-) diff --git a/yoga/YGValue.h b/yoga/YGValue.h index 4e43f7b2..59440be3 100644 --- a/yoga/YGValue.h +++ b/yoga/YGValue.h @@ -44,7 +44,6 @@ inline bool operator==(const YGValue& lhs, const YGValue& rhs) { return true; case YGUnitPoint: case YGUnitPercent: - default: return lhs.value == rhs.value; } } From 8bc89651d6a7e71258f1b6e265b751e55d967548 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 14 Dec 2018 09:20:27 -0800 Subject: [PATCH 143/189] Introduce `CompactValue` Summary: @public `CompactValue` represents a `YGValue` in 32bits instead of 64. This comes at the cost of a range limitation, as one exponent bit is borrowed for the unit. *Undefined* and *Auto* have no magnitude, and are represented as *NaN* values. The data structure is meant to be used as a field type on `YGStyle` to save memory. This is header-only for efficient inlining. Reviewed By: jackerghan, aCorrado Differential Revision: D13187211 fbshipit-source-id: 16e3ffad592e38e2493e4f7c8b952d372e449846 --- BUCK | 2 + tests/CompactValueTest.cpp | 349 +++++++++++++++++++++++++++++++++++++ yoga/CompactValue.h | 182 +++++++++++++++++++ 3 files changed, 533 insertions(+) create mode 100644 tests/CompactValueTest.cpp create mode 100644 yoga/CompactValue.h diff --git a/BUCK b/BUCK index aeeac450..4087a183 100644 --- a/BUCK +++ b/BUCK @@ -20,6 +20,7 @@ TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + [ yoga_cxx_library( name = "yoga", srcs = glob(["yoga/*.cpp"]), + headers = subdir_glob([("", "yoga/**/*.h")]), header_namespace = "", exported_headers = subdir_glob([("", "yoga/*.h")]), compiler_flags = COMPILER_FLAGS, @@ -34,6 +35,7 @@ yoga_cxx_library( yoga_cxx_test( name = "YogaTests", srcs = glob(["tests/*.cpp"]), + headers = subdir_glob([("", "yoga/**/*.h")]), compiler_flags = TEST_COMPILER_FLAGS, contacts = ["emilsj@fb.com"], visibility = ["PUBLIC"], diff --git a/tests/CompactValueTest.cpp b/tests/CompactValueTest.cpp new file mode 100644 index 00000000..7d2afc13 --- /dev/null +++ b/tests/CompactValueTest.cpp @@ -0,0 +1,349 @@ +/** + * 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. + */ +#define YOGA_COMPACT_VALUE_TEST + +#include +#include +#include + +using facebook::yoga::detail::CompactValue; + +const auto tooSmall = nextafterf(CompactValue::LOWER_BOUND, -INFINITY); +const auto tooLargePoints = + nextafterf(CompactValue::UPPER_BOUND_POINT, INFINITY); +const auto tooLargePercent = + nextafterf(CompactValue::UPPER_BOUND_PERCENT, INFINITY); + +TEST(YogaTest, compact_value_can_represent_undefined) { + auto c = CompactValue{YGValue{12.5f, YGUnitUndefined}}; + YGValue v = c; + ASSERT_EQ(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-1.25, YGUnitPoint})); + ASSERT_NE(v, (YGValue{25, YGUnitPercent})); + ASSERT_TRUE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_auto) { + auto c = CompactValue{YGValue{0, YGUnitAuto}}; + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_EQ(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-1.25, YGUnitPoint})); + ASSERT_NE(v, (YGValue{25, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_TRUE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_zero_points) { + auto c = CompactValue{YGValue{0, YGUnitPoint}}; + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{0, YGUnitPoint})); + ASSERT_NE(v, (YGValue{0, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_lower_bound_points) { + auto c = CompactValue({YGValue{CompactValue::LOWER_BOUND, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPoint})); + ASSERT_NE(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_negative_lower_bound_points) { + auto c = CompactValue({YGValue{-CompactValue::LOWER_BOUND, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPoint})); + ASSERT_NE(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_clamps_smaller_than_lower_bound_points_to_zero) { + auto c = CompactValue({YGValue{tooSmall, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{0, YGUnitPoint})); + ASSERT_NE(v, (YGValue{0, YGUnitPercent})); +} + +TEST( + YogaTest, + compact_value_clamps_greater_than_negative_lower_bound_points_to_zero) { + auto c = CompactValue({YGValue{-tooSmall, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{0, YGUnitPoint})); + ASSERT_NE(v, (YGValue{0, YGUnitPercent})); +} + +TEST(YogaTest, compact_value_can_represent_upper_bound_points) { + auto c = + CompactValue({YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); + ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_negative_upper_bound_points) { + auto c = + CompactValue({YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); + ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST( + YogaTest, + compact_value_clamps_greater_than__upper_bound_points_to_upper_bound) { + auto c = CompactValue({YGValue{tooLargePoints, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); + ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); +} + +TEST( + YogaTest, + compact_value_clamps_smaller_than_negative_upper_bound_points_to_upper_bound) { + auto c = CompactValue({YGValue{-tooLargePoints, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPoint})); + ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_POINT, YGUnitPercent})); +} + +TEST(YogaTest, compact_value_can_represent_one_point) { + auto c = CompactValue({YGValue{1, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{1, YGUnitPoint})); + ASSERT_NE(v, (YGValue{1, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_negative_one_point) { + auto c = CompactValue({YGValue{-1, YGUnitPoint}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_EQ(v, (YGValue{-1, YGUnitPoint})); + ASSERT_NE(v, (YGValue{-1, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_zero_percent) { + auto c = CompactValue{YGValue{0, YGUnitPercent}}; + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{0, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{0, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_lower_bound_percent) { + auto c = CompactValue({YGValue{CompactValue::LOWER_BOUND, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{CompactValue::LOWER_BOUND, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_negative_lower_bound_percent) { + auto c = CompactValue({YGValue{-CompactValue::LOWER_BOUND, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{-CompactValue::LOWER_BOUND, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_clamps_smaller_than_lower_bound_percent_to_zero) { + auto c = CompactValue({YGValue{tooSmall, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{0, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{0, YGUnitPercent})); +} + +TEST( + YogaTest, + compact_value_clamps_greater_than_negative_lower_bound_percent_to_zero) { + auto c = CompactValue({YGValue{-tooSmall, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{0, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{0, YGUnitPercent})); +} + +TEST(YogaTest, compact_value_can_represent_upper_bound_percent) { + auto c = + CompactValue({YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_negative_upper_bound_percent) { + auto c = CompactValue( + {YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST( + YogaTest, + compact_value_clamps_greater_than_upper_bound_percent_to_upper_bound) { + auto c = CompactValue({YGValue{tooLargePercent, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); +} + +TEST( + YogaTest, + compact_value_clamps_smaller_than_negative_upper_bound_percent_to_upper_bound) { + auto c = CompactValue({YGValue{-tooLargePercent, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{-CompactValue::UPPER_BOUND_PERCENT, YGUnitPercent})); +} + +TEST(YogaTest, compact_value_can_represent_one_percent) { + auto c = CompactValue({YGValue{1, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{1, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{1, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, compact_value_can_represent_negative_one_percent) { + auto c = CompactValue({YGValue{-1, YGUnitPercent}}); + YGValue v = c; + ASSERT_NE(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-1, YGUnitPoint})); + ASSERT_EQ(v, (YGValue{-1, YGUnitPercent})); + ASSERT_FALSE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + +TEST(YogaTest, dedicated_unit_factories) { + ASSERT_EQ(CompactValue::ofUndefined(), CompactValue(YGValueUndefined)); + ASSERT_EQ(CompactValue::ofAuto(), CompactValue(YGValueAuto)); + ASSERT_EQ( + CompactValue::of(-9876.5f), + CompactValue(YGValue{-9876.5f, YGUnitPoint})); + ASSERT_EQ( + CompactValue::of(123.456f), + CompactValue(YGValue{123.456f, YGUnitPercent})); +} + +TEST(YogaTest, dedicated_unit_maybe_factories) { + ASSERT_EQ( + CompactValue::ofMaybe(-9876.5f), + CompactValue(YGValue{-9876.5f, YGUnitPoint})); + ASSERT_EQ( + CompactValue::ofMaybe(YGUndefined), + CompactValue(YGValueUndefined)); + ASSERT_EQ( + CompactValue::ofMaybe(123.456f), + CompactValue(YGValue{123.456f, YGUnitPercent})); + ASSERT_EQ( + CompactValue::ofMaybe(YGUndefined), + CompactValue(YGValueUndefined)); +} + +TEST(YogaTest, can_be_assigned_from_YGValue) { + CompactValue c{}; + + YGValue v{2.0f, YGUnitPercent}; + c = v; + ASSERT_EQ((YGValue)c, v); + + c = YGValue{123, YGUnitPoint}; + ASSERT_EQ((YGValue)c, (YGValue{123, YGUnitPoint})); +} + +TEST(YogaTest, compact_value_bound_representations) { + ASSERT_EQ( + CompactValue::of(CompactValue::LOWER_BOUND).repr(), + uint32_t{0}); + ASSERT_EQ( + CompactValue::of(CompactValue::UPPER_BOUND_POINT).repr(), + uint32_t{0x3fffffff}); + ASSERT_EQ( + CompactValue::of(CompactValue::LOWER_BOUND).repr(), + uint32_t{0x40000000}); + ASSERT_EQ( + CompactValue::of(CompactValue::UPPER_BOUND_PERCENT).repr(), + uint32_t{0x7f7fffff}); + + ASSERT_EQ( + CompactValue::of(-CompactValue::LOWER_BOUND).repr(), + uint32_t{0x80000000}); + ASSERT_EQ( + CompactValue::of(-CompactValue::UPPER_BOUND_POINT).repr(), + uint32_t{0xbfffffff}); + ASSERT_EQ( + CompactValue::of(-CompactValue::LOWER_BOUND).repr(), + uint32_t{0xc0000000}); + ASSERT_EQ( + CompactValue::of(-CompactValue::UPPER_BOUND_PERCENT) + .repr(), + uint32_t{0xff7fffff}); +} diff --git a/yoga/CompactValue.h b/yoga/CompactValue.h new file mode 100644 index 00000000..1ca9d619 --- /dev/null +++ b/yoga/CompactValue.h @@ -0,0 +1,182 @@ +/** + * 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 + +#include +#include +#include + +static_assert( + std::numeric_limits::is_iec559, + "facebook::yoga::detail::CompactValue only works with IEEE754 floats"); + +#ifdef YOGA_COMPACT_VALUE_TEST +#define VISIBLE_FOR_TESTING public: +#else +#define VISIBLE_FOR_TESTING private: +#endif + +namespace facebook { +namespace yoga { +namespace detail { + +// This class stores YGValue in 32 bits. +// - The value does not matter for Undefined and Auto. NaNs are used for their +// representation. +// - To differentiate between Point and Percent, one exponent bit is used. +// Supported the range [0x40, 0xbf] (0xbf is inclusive for point, but +// exclusive for percent). +// - Value ranges: +// points: 1.08420217e-19f to 36893485948395847680 +// 0x00000000 0x3fffffff +// percent: 1.08420217e-19f to 18446742974197923840 +// 0x40000000 0x7f7fffff +// - Zero is supported, negative zero is not +// - values outside of the representable range are clamped +class CompactValue { + friend constexpr bool operator==(CompactValue, CompactValue) noexcept; + + public: + static constexpr auto LOWER_BOUND = 1.08420217e-19f; + static constexpr auto UPPER_BOUND_POINT = 36893485948395847680.0f; + static constexpr auto UPPER_BOUND_PERCENT = 18446742974197923840.0f; + + template + static CompactValue of(float value) noexcept { + if (value == 0.0f || (value < LOWER_BOUND && value > -LOWER_BOUND)) { + constexpr auto zero = + Unit == YGUnitPercent ? ZERO_BITS_PERCENT : ZERO_BITS_POINT; + return {Payload{zero}}; + } + + constexpr auto upperBound = + Unit == YGUnitPercent ? UPPER_BOUND_PERCENT : UPPER_BOUND_POINT; + if (value > upperBound || value < -upperBound) { + value = copysignf(upperBound, value); + } + + uint32_t unitBit = Unit == YGUnitPercent ? PERCENT_BIT : 0; + auto data = Payload{value}; + data.repr -= BIAS; + data.repr |= unitBit; + return {data}; + } + + template + static CompactValue ofMaybe(float value) noexcept { + return std::isnan(value) ? ofUndefined() : of(value); + } + + static constexpr CompactValue ofUndefined() noexcept { + return CompactValue{}; + } + + static constexpr CompactValue ofAuto() noexcept { + return CompactValue{Payload{AUTO_BITS}}; + } + + constexpr CompactValue() noexcept + : payload_(std::numeric_limits::quiet_NaN()) {} + + CompactValue(const YGValue& x) noexcept : payload_(uint32_t{0}) { + switch (x.unit) { + case YGUnitUndefined: + *this = ofUndefined(); + break; + case YGUnitAuto: + *this = ofAuto(); + break; + case YGUnitPoint: + *this = of(x.value); + break; + case YGUnitPercent: + *this = of(x.value); + break; + } + } + + operator YGValue() const noexcept { + switch (payload_.repr) { + case AUTO_BITS: + return YGValueAuto; + case ZERO_BITS_POINT: + return YGValue{0.0f, YGUnitPoint}; + case ZERO_BITS_PERCENT: + return YGValue{0.0f, YGUnitPercent}; + } + + if (std::isnan(payload_.value)) { + return YGValueUndefined; + } + + auto data = payload_; + data.repr &= ~PERCENT_BIT; + data.repr += BIAS; + + return YGValue{data.value, + payload_.repr & 0x40000000 ? YGUnitPercent : YGUnitPoint}; + } + + bool isUndefined() const noexcept { + return ( + payload_.repr != AUTO_BITS && payload_.repr != ZERO_BITS_POINT && + payload_.repr != ZERO_BITS_PERCENT && std::isnan(payload_.value)); + } + + bool isAuto() const noexcept { + return payload_.repr == AUTO_BITS; + } + + private: + union Payload { + float value; + uint32_t repr; + Payload() = delete; + constexpr Payload(uint32_t r) : repr(r) {} + constexpr Payload(float v) : value(v) {} + }; + + static constexpr uint32_t BIAS = 0x20000000; + static constexpr uint32_t PERCENT_BIT = 0x40000000; + + // these are signaling NaNs with specific bit pattern as payload + // they will be silenced whenever going through an FPU operation on ARM + x86 + static constexpr uint32_t AUTO_BITS = 0x7faaaaaa; + static constexpr uint32_t ZERO_BITS_POINT = 0x7f8f0f0f; + static constexpr uint32_t ZERO_BITS_PERCENT = 0x7f80f0f0; + + constexpr CompactValue(Payload data) noexcept : payload_(data) {} + + Payload payload_; + + VISIBLE_FOR_TESTING uint32_t repr() { + return payload_.repr; + } +}; + +template <> +CompactValue CompactValue::of(float) noexcept = delete; +template <> +CompactValue CompactValue::of(float) noexcept = delete; +template <> +CompactValue CompactValue::ofMaybe(float) noexcept = delete; +template <> +CompactValue CompactValue::ofMaybe(float) noexcept = delete; + +constexpr bool operator==(CompactValue a, CompactValue b) noexcept { + return a.payload_.repr == b.payload_.repr; +} + +constexpr bool operator!=(CompactValue a, CompactValue b) noexcept { + return !(a == b); +} + +} // namespace detail +} // namespace yoga +} // namespace facebook From 3df41aefdbec2772c36261a93966de8c0b8a6e08 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 14 Dec 2018 09:20:27 -0800 Subject: [PATCH 144/189] Encapsulate arrays of `YGValue` within `YGStyle` Summary: @public Enforce more encapsulation of arrays of `YGValue` in `YGSty;e`. This will allow us to use `CompactValue` in `YGStyle` while (mostly) retaining API compatibility. Reviewed By: SidharthGuglani Differential Revision: D13452042 fbshipit-source-id: 382b1c7245c4bea4280126ab1413e7e931b62eaa --- yoga/YGStyle.cpp | 26 +++++++---------- yoga/YGStyle.h | 34 ++++++++-------------- yoga/YGValue.h | 2 ++ yoga/Yoga-internal.h | 69 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 83 insertions(+), 48 deletions(-) diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 78df8b01..1c06cd35 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -15,39 +15,35 @@ bool YGStyle::operator==(const YGStyle& style) { alignSelf == style.alignSelf && positionType == style.positionType && flexWrap == style.flexWrap && overflow == style.overflow && display == style.display && YGValueEqual(flexBasis, style.flexBasis) && - YGValueArrayEqual(margin, style.margin) && - YGValueArrayEqual(position, style.position) && - YGValueArrayEqual(padding, style.padding) && - YGValueArrayEqual(border, style.border) && - YGValueArrayEqual(dimensions, style.dimensions) && - YGValueArrayEqual(minDimensions, style.minDimensions) && - YGValueArrayEqual(maxDimensions, style.maxDimensions); + margin == style.margin && position == style.position && + padding == style.padding && border == style.border && + dimensions == style.dimensions && minDimensions == style.minDimensions && + maxDimensions == style.maxDimensions; areNonFloatValuesEqual = areNonFloatValuesEqual && flex.isUndefined() == style.flex.isUndefined(); if (areNonFloatValuesEqual && !flex.isUndefined() && !style.flex.isUndefined()) { - areNonFloatValuesEqual = - areNonFloatValuesEqual && flex == style.flex; + areNonFloatValuesEqual = areNonFloatValuesEqual && flex == style.flex; } areNonFloatValuesEqual = areNonFloatValuesEqual && flexGrow.isUndefined() == style.flexGrow.isUndefined(); if (areNonFloatValuesEqual && !flexGrow.isUndefined()) { - areNonFloatValuesEqual = areNonFloatValuesEqual && - flexGrow == style.flexGrow; + areNonFloatValuesEqual = + areNonFloatValuesEqual && flexGrow == style.flexGrow; } areNonFloatValuesEqual = areNonFloatValuesEqual && flexShrink.isUndefined() == style.flexShrink.isUndefined(); if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) { - areNonFloatValuesEqual = areNonFloatValuesEqual && - flexShrink == style.flexShrink; + areNonFloatValuesEqual = + areNonFloatValuesEqual && flexShrink == style.flexShrink; } if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) { - areNonFloatValuesEqual = areNonFloatValuesEqual && - aspectRatio == style.aspectRatio; + areNonFloatValuesEqual = + areNonFloatValuesEqual && aspectRatio == style.aspectRatio; } return areNonFloatValuesEqual; diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index c4f7e3c7..63b255de 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -5,6 +5,9 @@ * file in the root directory of this source tree. */ #pragma once +#include +#include +#include #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -13,22 +16,9 @@ constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; -constexpr std::array kYGDefaultEdgeValuesUnit = { - {kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined, - kYGValueUndefined}}; - -constexpr std::array kYGDefaultDimensionValuesUnit = { - {kYGValueUndefined, kYGValueUndefined}}; - struct YGStyle { - using Dimensions = std::array; + using Dimensions = facebook::yoga::detail::Values<2>; + using Edges = facebook::yoga::detail::Values; YGDirection direction : 2; YGFlexDirection flexDirection : 2; @@ -44,13 +34,13 @@ struct YGStyle { YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; YGValue flexBasis = kYGValueAuto; - std::array margin = kYGDefaultEdgeValuesUnit; - std::array position = kYGDefaultEdgeValuesUnit; - std::array padding = kYGDefaultEdgeValuesUnit; - std::array border = kYGDefaultEdgeValuesUnit; - Dimensions dimensions = {{kYGValueAuto, kYGValueAuto}}; - Dimensions minDimensions = kYGDefaultDimensionValuesUnit; - Dimensions maxDimensions = kYGDefaultDimensionValuesUnit; + Edges margin{kYGValueUndefined}; + Edges position{kYGValueUndefined}; + Edges padding{kYGValueUndefined}; + Edges border{kYGValueUndefined}; + Dimensions dimensions{kYGValueAuto}; + Dimensions minDimensions{kYGValueUndefined}; + Dimensions maxDimensions{kYGValueUndefined}; // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio = {}; diff --git a/yoga/YGValue.h b/yoga/YGValue.h index 59440be3..c3df5fc9 100644 --- a/yoga/YGValue.h +++ b/yoga/YGValue.h @@ -46,6 +46,8 @@ inline bool operator==(const YGValue& lhs, const YGValue& rhs) { case YGUnitPercent: return lhs.value == rhs.value; } + + return false; } inline bool operator!=(const YGValue& lhs, const YGValue& rhs) { diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index ef5e5d8c..cc4da004 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -42,17 +42,6 @@ extern const YGValue YGValueUndefined; extern const YGValue YGValueAuto; extern const YGValue YGValueZero; -template -bool YGValueArrayEqual( - const std::array val1, - const std::array val2) { - bool areEqual = true; - for (uint32_t i = 0; i < size && areEqual; ++i) { - areEqual = YGValueEqual(val1[i], val2[i]); - } - return areEqual; -} - struct YGCachedMeasurement { float availableWidth; float availableHeight; @@ -99,6 +88,64 @@ struct YGCachedMeasurement { // layouts should not require more than 16 entries to fit within the cache. #define YG_MAX_CACHED_RESULT_COUNT 16 +namespace facebook { +namespace yoga { +namespace detail { + +template +class Values { + private: + std::array values_; + + public: + Values() = default; + explicit Values(const YGValue& defaultValue) noexcept { + values_.fill(defaultValue); + } + + operator const std::array&() const noexcept { + return values_; + } + operator std::array&() noexcept { + return values_; + } + const YGValue& operator[](size_t i) const noexcept { + return values_[i]; + } + YGValue& operator[](size_t i) noexcept { + return values_[i]; + } + + template + YGValue get() const noexcept { + return std::get(values_); + } + + template + void set(YGValue& value) noexcept { + std::get(values_) = value; + } + + bool operator==(const Values& other) const noexcept { + for (size_t i = 0; i < Size; ++i) { + if (values_[i] != other.values_[i]) { + return false; + } + } + return true; + } + + Values& operator=(const Values& other) = default; + Values& operator=(const std::array& other) noexcept { + values_ = other; + return *this; + } +}; + +} // namespace detail +} // namespace yoga +} // namespace facebook + static const float kDefaultFlexGrow = 0.0f; static const float kDefaultFlexShrink = 0.0f; static const float kWebDefaultFlexShrink = 1.0f; From 8461aeaef0ee5b34ff9128777d6951effe968b13 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 14 Dec 2018 09:20:27 -0800 Subject: [PATCH 145/189] Remove cast from `detail::Values` to `std::array` will do actual work. In order to avoid that from happening implicitely, we remove the casting operator. Reviewed By: SidharthGuglani Differential Revision: D13464292 fbshipit-source-id: 217065b001a63cfa8adde715063682c583007a4d --- yoga/YGNodePrint.cpp | 7 ++++--- yoga/Yoga-internal.h | 12 +----------- yoga/Yoga.cpp | 2 +- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 753a00b6..03bff15a 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -20,7 +20,8 @@ static void indent(string& base, uint32_t level) { } } -static bool areFourValuesEqual(const std::array& four) { +static bool areFourValuesEqual( + const facebook::yoga::detail::Values& four) { return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) && YGValueEqual(four[0], four[3]); } @@ -81,7 +82,7 @@ appendNumberIfNotZero(string& base, const string& str, const YGValue number) { static void appendEdges( string& base, const string& key, - const std::array& edges) { + const facebook::yoga::detail::Values& edges) { if (areFourValuesEqual(edges)) { appendNumberIfNotZero(base, key, edges[YGEdgeLeft]); } else { @@ -95,7 +96,7 @@ static void appendEdges( static void appendEdgeIfNotUndefined( string& base, const string& str, - const std::array& edges, + const facebook::yoga::detail::Values& edges, const YGEdge edge) { appendNumberIfNotUndefined( base, str, *YGComputedEdgeValue(edges, edge, &YGValueUndefined)); diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index cc4da004..719d7b37 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -103,12 +103,6 @@ class Values { values_.fill(defaultValue); } - operator const std::array&() const noexcept { - return values_; - } - operator std::array&() noexcept { - return values_; - } const YGValue& operator[](size_t i) const noexcept { return values_[i]; } @@ -136,10 +130,6 @@ class Values { } Values& operator=(const Values& other) = default; - Values& operator=(const std::array& other) noexcept { - values_ = other; - return *this; - } }; } // namespace detail @@ -153,6 +143,6 @@ static const float kWebDefaultFlexShrink = 1.0f; extern bool YGFloatsEqual(const float a, const float b); extern bool YGValueEqual(const YGValue a, const YGValue b); extern const YGValue* YGComputedEdgeValue( - const std::array& edges, + const facebook::yoga::detail::Values& edges, const YGEdge edge, const YGValue* const defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 4a1a98a2..beb01c59 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -103,7 +103,7 @@ bool YGFloatIsUndefined(const float value) { } const YGValue* YGComputedEdgeValue( - const std::array& edges, + const facebook::yoga::detail::Values& edges, const YGEdge edge, const YGValue* const defaultValue) { if (edges[edge].unit != YGUnitUndefined) { From 885b4cbdfb73bad75edc53b73b6a076af74c94b0 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 18 Dec 2018 08:11:24 -0800 Subject: [PATCH 146/189] Switch storage in `YGStyle` to `CompactValue` Summary: @public Switches the storage in `facebook::yoga::detail::Values` from `YGValue` to `facebook::yoga::detail::CompactValue`. This cuts heap size for arrays of values in half. Reviewed By: SidharthGuglani Differential Revision: D13465586 fbshipit-source-id: 49a4d6d29a73bdd44843b1f3c57bf746050c94d6 --- yoga/CompactValue.h | 6 +- yoga/Utils.h | 6 +- yoga/YGNode.cpp | 119 ++++++++++++------------ yoga/YGNodePrint.cpp | 4 +- yoga/YGStyle.h | 21 +++-- yoga/Yoga-internal.h | 18 ++-- yoga/Yoga.cpp | 212 ++++++++++++++++++++----------------------- 7 files changed, 195 insertions(+), 191 deletions(-) diff --git a/yoga/CompactValue.h b/yoga/CompactValue.h index 1ca9d619..7120f1c1 100644 --- a/yoga/CompactValue.h +++ b/yoga/CompactValue.h @@ -6,7 +6,7 @@ */ #pragma once -#include +#include "YGValue.h" #include #include @@ -73,6 +73,10 @@ class CompactValue { return std::isnan(value) ? ofUndefined() : of(value); } + static constexpr CompactValue ofZero() noexcept { + return CompactValue{Payload{ZERO_BITS_POINT}}; + } + static constexpr CompactValue ofUndefined() noexcept { return CompactValue{}; } diff --git a/yoga/Utils.h b/yoga/Utils.h index a0d49235..7e5a8636 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -7,6 +7,7 @@ #pragma once #include "YGNode.h" #include "Yoga-internal.h" +#include "CompactValue.h" // This struct is an helper model to hold the data for step 4 of flexbox // algo, which is collecting the flex items in a line. @@ -124,8 +125,7 @@ inline YGFlexDirection YGResolveFlexDirection( } inline YGFloatOptional YGResolveValueMargin( - const YGValue value, + yoga::detail::CompactValue value, const float ownerSize) { - return value.unit == YGUnitAuto ? YGFloatOptional(0) - : YGResolveValue(value, ownerSize); + return value.isAuto() ? YGFloatOptional{0} : YGResolveValue(value, ownerSize); } diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 1a08fab8..8e7e210b 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -6,87 +6,92 @@ */ #include "YGNode.h" #include +#include "CompactValue.h" #include "Utils.h" using namespace facebook; +using facebook::yoga::detail::CompactValue; YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection axis, const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { - const YGValue* leadingPosition = - YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined); - if (leadingPosition->unit != YGUnitUndefined) { - return YGResolveValue(*leadingPosition, axisSize); + auto leadingPosition = YGComputedEdgeValue( + style_.position, YGEdgeStart, CompactValue::ofUndefined()); + if (!leadingPosition.isUndefined()) { + return YGResolveValue(leadingPosition, axisSize); } } - const YGValue* leadingPosition = - YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined); + auto leadingPosition = YGComputedEdgeValue( + style_.position, leading[axis], CompactValue::ofUndefined()); - return leadingPosition->unit == YGUnitUndefined - ? YGFloatOptional(0) - : YGResolveValue(*leadingPosition, axisSize); + return leadingPosition.isUndefined() + ? YGFloatOptional{0} + : YGResolveValue(leadingPosition, axisSize); } YGFloatOptional YGNode::getTrailingPosition( const YGFlexDirection axis, const float axisSize) const { if (YGFlexDirectionIsRow(axis)) { - const YGValue* trailingPosition = - YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined); - if (trailingPosition->unit != YGUnitUndefined) { - return YGResolveValue(*trailingPosition, axisSize); + auto trailingPosition = YGComputedEdgeValue( + style_.position, YGEdgeEnd, CompactValue::ofUndefined()); + if (!trailingPosition.isUndefined()) { + return YGResolveValue(trailingPosition, axisSize); } } - const YGValue* trailingPosition = - YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined); + auto trailingPosition = YGComputedEdgeValue( + style_.position, trailing[axis], CompactValue::ofUndefined()); - return trailingPosition->unit == YGUnitUndefined - ? YGFloatOptional(0) - : YGResolveValue(*trailingPosition, axisSize); + return trailingPosition.isUndefined() + ? YGFloatOptional{0} + : YGResolveValue(trailingPosition, axisSize); } bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && - YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined) - ->unit != YGUnitUndefined) || - YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined) - ->unit != YGUnitUndefined; + !YGComputedEdgeValue( + style_.position, YGEdgeStart, CompactValue::ofUndefined()) + .isUndefined()) || + !YGComputedEdgeValue( + style_.position, leading[axis], CompactValue::ofUndefined()) + .isUndefined(); } bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const { return (YGFlexDirectionIsRow(axis) && - YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined) - ->unit != YGUnitUndefined) || - YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined) - ->unit != YGUnitUndefined; + !YGComputedEdgeValue( + style_.position, YGEdgeEnd, CompactValue::ofUndefined()) + .isUndefined()) || + !YGComputedEdgeValue( + style_.position, trailing[axis], CompactValue::ofUndefined()) + .isUndefined(); } YGFloatOptional YGNode::getLeadingMargin( const YGFlexDirection axis, const float widthSize) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeStart].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeStart].isUndefined()) { return YGResolveValueMargin(style_.margin[YGEdgeStart], widthSize); } return YGResolveValueMargin( - *YGComputedEdgeValue(style_.margin, leading[axis], &YGValueZero), + YGComputedEdgeValue(style_.margin, leading[axis], CompactValue::ofZero()), widthSize); } YGFloatOptional YGNode::getTrailingMargin( const YGFlexDirection axis, const float widthSize) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeEnd].isUndefined()) { return YGResolveValueMargin(style_.margin[YGEdgeEnd], widthSize); } return YGResolveValueMargin( - *YGComputedEdgeValue(style_.margin, trailing[axis], &YGValueZero), + YGComputedEdgeValue( + style_.margin, trailing[axis], CompactValue::ofZero()), widthSize); } @@ -280,8 +285,7 @@ YGNode& YGNode::operator=(const YGNode& node) { } YGValue YGNode::marginLeadingValue(const YGFlexDirection axis) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeStart].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeStart].isUndefined()) { return style_.margin[YGEdgeStart]; } else { return style_.margin[leading[axis]]; @@ -289,8 +293,7 @@ YGValue YGNode::marginLeadingValue(const YGFlexDirection axis) const { } YGValue YGNode::marginTrailingValue(const YGFlexDirection axis) const { - if (YGFlexDirectionIsRow(axis) && - style_.margin[YGEdgeEnd].unit != YGUnitUndefined) { + if (YGFlexDirectionIsRow(axis) && !style_.margin[YGEdgeEnd].isUndefined()) { return style_.margin[YGEdgeEnd]; } else { return style_.margin[trailing[axis]]; @@ -310,7 +313,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { void YGNode::resolveDimension() { for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) { - if (getStyle().maxDimensions[dim].unit != YGUnitUndefined && + if (!getStyle().maxDimensions[dim].isUndefined() && YGValueEqual( getStyle().maxDimensions[dim], style_.minDimensions[dim])) { resolvedDimensions_[dim] = style_.maxDimensions[dim]; @@ -422,30 +425,32 @@ bool YGNode::isNodeFlexible() { } float YGNode::getLeadingBorder(const YGFlexDirection axis) const { - if (YGFlexDirectionIsRow(axis) && - style_.border[YGEdgeStart].unit != YGUnitUndefined && - !yoga::isUndefined(style_.border[YGEdgeStart].value) && - style_.border[YGEdgeStart].value >= 0.0f) { - return style_.border[YGEdgeStart].value; + YGValue leadingBorder; + if (YGFlexDirectionIsRow(axis) && !style_.border[YGEdgeStart].isUndefined()) { + leadingBorder = style_.border[YGEdgeStart]; + if (leadingBorder.value >= 0) { + return leadingBorder.value; + } } - float computedEdgeValue = - YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value; - return YGFloatMax(computedEdgeValue, 0.0f); + leadingBorder = + YGComputedEdgeValue(style_.border, leading[axis], CompactValue::ofZero()); + return YGFloatMax(leadingBorder.value, 0.0f); } float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { + YGValue trailingBorder; if (YGFlexDirectionIsRow(flexDirection) && - style_.border[YGEdgeEnd].unit != YGUnitUndefined && - !yoga::isUndefined(style_.border[YGEdgeEnd].value) && - style_.border[YGEdgeEnd].value >= 0.0f) { - return style_.border[YGEdgeEnd].value; + !style_.border[YGEdgeEnd].isUndefined()) { + trailingBorder = style_.border[YGEdgeEnd]; + if (trailingBorder.value >= 0.0f) { + return trailingBorder.value; + } } - float computedEdgeValue = - YGComputedEdgeValue(style_.border, trailing[flexDirection], &YGValueZero) - ->value; - return YGFloatMax(computedEdgeValue, 0.0f); + trailingBorder = YGComputedEdgeValue( + style_.border, trailing[flexDirection], CompactValue::ofZero()); + return YGFloatMax(trailingBorder.value, 0.0f); } YGFloatOptional YGNode::getLeadingPadding( @@ -454,13 +459,14 @@ YGFloatOptional YGNode::getLeadingPadding( const YGFloatOptional paddingEdgeStart = YGResolveValue(style_.padding[YGEdgeStart], widthSize); if (YGFlexDirectionIsRow(axis) && - style_.padding[YGEdgeStart].unit != YGUnitUndefined && + !style_.padding[YGEdgeStart].isUndefined() && !paddingEdgeStart.isUndefined() && paddingEdgeStart.unwrap() >= 0.0f) { return paddingEdgeStart; } YGFloatOptional resolvedValue = YGResolveValue( - *YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero), + YGComputedEdgeValue( + style_.padding, leading[axis], CompactValue::ofZero()), widthSize); return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f)); } @@ -475,7 +481,8 @@ YGFloatOptional YGNode::getTrailingPadding( } YGFloatOptional resolvedValue = YGResolveValue( - *YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero), + YGComputedEdgeValue( + style_.padding, trailing[axis], CompactValue::ofZero()), widthSize); return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f)); diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 03bff15a..4be2ff5a 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -99,7 +99,9 @@ static void appendEdgeIfNotUndefined( const facebook::yoga::detail::Values& edges, const YGEdge edge) { appendNumberIfNotUndefined( - base, str, *YGComputedEdgeValue(edges, edge, &YGValueUndefined)); + base, + str, + YGComputedEdgeValue(edges, edge, detail::CompactValue::ofUndefined())); } void YGNodeToString( diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 63b255de..abcc7052 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -8,6 +8,7 @@ #include #include #include +#include "CompactValue.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -17,6 +18,10 @@ constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; struct YGStyle { + private: + using CompactValue = facebook::yoga::detail::CompactValue; + + public: using Dimensions = facebook::yoga::detail::Values<2>; using Edges = facebook::yoga::detail::Values; @@ -33,14 +38,14 @@ struct YGStyle { YGFloatOptional flex = {}; YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; - YGValue flexBasis = kYGValueAuto; - Edges margin{kYGValueUndefined}; - Edges position{kYGValueUndefined}; - Edges padding{kYGValueUndefined}; - Edges border{kYGValueUndefined}; - Dimensions dimensions{kYGValueAuto}; - Dimensions minDimensions{kYGValueUndefined}; - Dimensions maxDimensions{kYGValueUndefined}; + CompactValue flexBasis = CompactValue::ofAuto(); + Edges margin = {}; + Edges position = {}; + Edges padding = {}; + Edges border = {}; + Dimensions dimensions{CompactValue::ofAuto()}; + Dimensions minDimensions = {}; + Dimensions maxDimensions = {}; // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio = {}; diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 719d7b37..a182a465 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -9,6 +9,7 @@ #include #include #include +#include "CompactValue.h" #include "Yoga.h" using YGVector = std::vector; @@ -95,7 +96,7 @@ namespace detail { template class Values { private: - std::array values_; + std::array values_; public: Values() = default; @@ -103,10 +104,10 @@ class Values { values_.fill(defaultValue); } - const YGValue& operator[](size_t i) const noexcept { + const CompactValue& operator[](size_t i) const noexcept { return values_[i]; } - YGValue& operator[](size_t i) noexcept { + CompactValue& operator[](size_t i) noexcept { return values_[i]; } @@ -120,6 +121,11 @@ class Values { std::get(values_) = value; } + template + void set(YGValue&& value) noexcept { + set(value); + } + bool operator==(const Values& other) const noexcept { for (size_t i = 0; i < Size; ++i) { if (values_[i] != other.values_[i]) { @@ -142,7 +148,7 @@ static const float kWebDefaultFlexShrink = 1.0f; extern bool YGFloatsEqual(const float a, const float b); extern bool YGValueEqual(const YGValue a, const YGValue b); -extern const YGValue* YGComputedEdgeValue( +extern facebook::yoga::detail::CompactValue YGComputedEdgeValue( const facebook::yoga::detail::Values& edges, - const YGEdge edge, - const YGValue* const defaultValue); + YGEdge edge, + facebook::yoga::detail::CompactValue defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index beb01c59..9b8aa8a4 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -23,6 +23,8 @@ __forceinline const float fmaxf(const float a, const float b) { #endif #endif +using namespace facebook::yoga; + #ifdef ANDROID static int YGAndroidLog( const YGConfigRef config, @@ -102,31 +104,31 @@ bool YGFloatIsUndefined(const float value) { return facebook::yoga::isUndefined(value); } -const YGValue* YGComputedEdgeValue( +detail::CompactValue YGComputedEdgeValue( const facebook::yoga::detail::Values& edges, - const YGEdge edge, - const YGValue* const defaultValue) { - if (edges[edge].unit != YGUnitUndefined) { - return &edges[edge]; + YGEdge edge, + detail::CompactValue defaultValue) { + if (!edges[edge].isUndefined()) { + return edges[edge]; } if ((edge == YGEdgeTop || edge == YGEdgeBottom) && - edges[YGEdgeVertical].unit != YGUnitUndefined) { - return &edges[YGEdgeVertical]; + !edges[YGEdgeVertical].isUndefined()) { + return edges[YGEdgeVertical]; } if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) && - edges[YGEdgeHorizontal].unit != YGUnitUndefined) { - return &edges[YGEdgeHorizontal]; + !edges[YGEdgeHorizontal].isUndefined()) { + return edges[YGEdgeHorizontal]; } - if (edges[YGEdgeAll].unit != YGUnitUndefined) { - return &edges[YGEdgeAll]; + if (!edges[YGEdgeAll].isUndefined()) { + return edges[YGEdgeAll]; } if (edge == YGEdgeStart || edge == YGEdgeEnd) { - return &YGValueUndefined; + return detail::CompactValue::ofUndefined(); } return defaultValue; @@ -595,14 +597,21 @@ namespace { struct Value { template - static YGValue create(float value) { - return { - YGFloatSanitize(value), - YGFloatIsUndefined(value) ? YGUnitUndefined : U, - }; + static detail::CompactValue create(float value) { + return detail::CompactValue::ofMaybe(value); } }; +template <> +inline detail::CompactValue Value::create(float) { + return detail::CompactValue::ofUndefined(); +} + +template <> +inline detail::CompactValue Value::create(float) { + return detail::CompactValue::ofAuto(); +} + template struct DimensionProp { template @@ -616,10 +625,8 @@ struct DimensionProp { template static void set(YGNodeRef node, float newValue) { - YGValue value = Value::create(newValue); - if (((node->getStyle().*P)[idx].value != value.value && - value.unit != YGUnitUndefined) || - (node->getStyle().*P)[idx].unit != value.unit) { + auto value = Value::create(newValue); + if ((node->getStyle().*P)[idx] != value) { (node->getStyle().*P)[idx] = value; node->markDirtyAndPropogate(); } @@ -628,37 +635,30 @@ struct DimensionProp { } // namespace -#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ - type, name, paramName, instanceName) \ - void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \ - }; \ - if ((node->getStyle().instanceName.value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName.unit != value.unit) { \ - node->getStyle().instanceName = value; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const type paramName) { \ - if (node->getStyle().instanceName.value != YGFloatSanitize(paramName) || \ - node->getStyle().instanceName.unit != YGUnitPercent) { \ - node->getStyle().instanceName = YGFloatIsUndefined(paramName) \ - ? YGValue{0, YGUnitAuto} \ - : YGValue{paramName, YGUnitPercent}; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ - if (node->getStyle().instanceName.unit != YGUnitAuto) { \ - node->getStyle().instanceName = {0, YGUnitAuto}; \ - node->markDirtyAndPropogate(); \ - } \ +#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \ + type, name, paramName, instanceName) \ + void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName != value) { \ + node->getStyle().instanceName = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const type paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName != value) { \ + node->getStyle().instanceName = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ + if (node->getStyle().instanceName != detail::CompactValue::ofAuto()) { \ + node->getStyle().instanceName = detail::CompactValue::ofAuto(); \ + node->markDirtyAndPropogate(); \ + } \ } #define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( \ @@ -676,49 +676,40 @@ struct DimensionProp { #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \ void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \ - if (node->getStyle().instanceName[edge].unit != YGUnitAuto) { \ - node->getStyle().instanceName[edge] = {0, YGUnitAuto}; \ + if (node->getStyle().instanceName[edge] != \ + detail::CompactValue::ofAuto()) { \ + node->getStyle().instanceName[edge] = detail::CompactValue::ofAuto(); \ node->markDirtyAndPropogate(); \ } \ } -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL( \ - type, name, paramName, instanceName) \ - void YGNodeStyleSet##name( \ - const YGNodeRef node, const YGEdge edge, const float paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \ - }; \ - if ((node->getStyle().instanceName[edge].value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[edge].unit != value.unit) { \ - node->getStyle().instanceName[edge] = value; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const YGEdge edge, const float paramName) { \ - YGValue value = { \ - YGFloatSanitize(paramName), \ - YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \ - }; \ - if ((node->getStyle().instanceName[edge].value != value.value && \ - value.unit != YGUnitUndefined) || \ - node->getStyle().instanceName[edge].unit != value.unit) { \ - node->getStyle().instanceName[edge] = value; \ - node->markDirtyAndPropogate(); \ - } \ - } \ - \ - WIN_STRUCT(type) \ - YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ - YGValue value = node->getStyle().instanceName[edge]; \ - if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \ - value.value = YGUndefined; \ - } \ - return WIN_STRUCT_REF(value); \ +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL( \ + type, name, paramName, instanceName) \ + void YGNodeStyleSet##name( \ + const YGNodeRef node, const YGEdge edge, const float paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName[edge] != value) { \ + node->getStyle().instanceName[edge] = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const YGEdge edge, const float paramName) { \ + auto value = detail::CompactValue::ofMaybe(paramName); \ + if (node->getStyle().instanceName[edge] != value) { \ + node->getStyle().instanceName[edge] = value; \ + node->markDirtyAndPropogate(); \ + } \ + } \ + \ + WIN_STRUCT(type) \ + YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ + YGValue value = node->getStyle().instanceName[edge]; \ + if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \ + value.value = YGUndefined; \ + } \ + return WIN_STRUCT_REF(value); \ } #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ @@ -881,13 +872,8 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node) { } void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { - YGValue value = { - YGFloatSanitize(flexBasis), - YGFloatIsUndefined(flexBasis) ? YGUnitUndefined : YGUnitPoint, - }; - if ((node->getStyle().flexBasis.value != value.value && - value.unit != YGUnitUndefined) || - node->getStyle().flexBasis.unit != value.unit) { + auto value = detail::CompactValue::ofMaybe(flexBasis); + if (node->getStyle().flexBasis != value) { node->getStyle().flexBasis = value; node->markDirtyAndPropogate(); } @@ -896,18 +882,16 @@ void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { void YGNodeStyleSetFlexBasisPercent( const YGNodeRef node, const float flexBasisPercent) { - if (node->getStyle().flexBasis.value != flexBasisPercent || - node->getStyle().flexBasis.unit != YGUnitPercent) { - node->getStyle().flexBasis = YGFloatIsUndefined(flexBasisPercent) - ? YGValue{0, YGUnitAuto} - : YGValue{flexBasisPercent, YGUnitPercent}; + auto value = detail::CompactValue::ofMaybe(flexBasisPercent); + if (node->getStyle().flexBasis != value) { + node->getStyle().flexBasis = value; node->markDirtyAndPropogate(); } } void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { - if (node->getStyle().flexBasis.unit != YGUnitAuto) { - node->getStyle().flexBasis = {0, YGUnitAuto}; + if (node->getStyle().flexBasis != detail::CompactValue::ofAuto()) { + node->getStyle().flexBasis = detail::CompactValue::ofAuto(); node->markDirtyAndPropogate(); } } @@ -922,27 +906,23 @@ void YGNodeStyleSetBorder( const YGNodeRef node, const YGEdge edge, const float border) { - YGValue value = { - YGFloatSanitize(border), - YGFloatIsUndefined(border) ? YGUnitUndefined : YGUnitPoint, - }; - if ((node->getStyle().border[edge].value != value.value && - value.unit != YGUnitUndefined) || - node->getStyle().border[edge].unit != value.unit) { + auto value = detail::CompactValue::ofMaybe(border); + if (node->getStyle().border[edge] != value) { node->getStyle().border[edge] = value; node->markDirtyAndPropogate(); } } float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) { - if (node->getStyle().border[edge].unit == YGUnitUndefined || - node->getStyle().border[edge].unit == YGUnitAuto) { + if (node->getStyle().border[edge].isUndefined() || + node->getStyle().border[edge].isAuto()) { // TODO(T26792433): Rather than returning YGUndefined, change the api to // return YGFloatOptional. return YGUndefined; } - return node->getStyle().border[edge].value; + auto border = (YGValue)node->getStyle().border[edge]; + return border.value; } // Yoga specific properties, not compatible with flexbox specification @@ -2433,7 +2413,7 @@ static void YGJustifyMainAxis( // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == YGMeasureModeAtMost && collectedFlexItemsValues.remainingFreeSpace > 0) { - if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined && + if (!style.minDimensions[dim[mainAxis]].isUndefined() && !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize) .isUndefined()) { // This condition makes sure that if the size of main dimension(after From f6415889ca72fc7df00e3fa3cdc0fdb9f28a4d39 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 18 Dec 2018 08:11:25 -0800 Subject: [PATCH 147/189] Use bitfields for `YGLayout` and `YGNode` Summary: @public Further heap size reductions by using bitfields in `YGLayout` and `YGNode`. Reviewed By: SidharthGuglani Differential Revision: D13466325 fbshipit-source-id: ddcef0a1b3822e7449fe485d99c920d54139c893 --- yoga/YGLayout.h | 14 +++++++++----- yoga/YGNode.h | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 2a0215d3..94a92adf 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -17,11 +17,13 @@ struct YGLayout { std::array margin = {}; std::array border = {}; std::array padding = {}; - YGDirection direction = YGDirectionInherit; + YGDirection direction : 2; + bool didUseLegacyFlag : 1; + bool doesLegacyStretchFlagAffectsLayout : 1; + bool hadOverflow : 1; uint32_t computedFlexBasisGeneration = 0; YGFloatOptional computedFlexBasis = {}; - bool hadOverflow = false; // Instead of recomputing the entire layout every single time, we // cache some information to break early when nothing changed @@ -34,10 +36,12 @@ struct YGLayout { std::array measuredDimensions = kYGDefaultDimensionValues; YGCachedMeasurement cachedLayout = YGCachedMeasurement(); - bool didUseLegacyFlag = false; - bool doesLegacyStretchFlagAffectsLayout = false; - YGLayout() = default; + YGLayout() + : direction(YGDirectionInherit), + didUseLegacyFlag(false), + doesLegacyStretchFlagAffectsLayout(false), + hadOverflow(false) {} bool operator==(YGLayout layout) const; bool operator!=(YGLayout layout) const { diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 57312812..2c00ec75 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -15,9 +15,10 @@ struct YGNode { private: void* context_ = nullptr; YGPrintFunc print_ = nullptr; - bool hasNewLayout_ = true; - bool isReferenceBaseline_ = false; - YGNodeType nodeType_ = YGNodeTypeDefault; + bool hasNewLayout_ : 1; + bool isReferenceBaseline_ : 1; + bool isDirty_ : 1; + YGNodeType nodeType_ : 1; YGMeasureFunc measure_ = nullptr; YGBaselineFunc baseline_ = nullptr; YGDirtiedFunc dirtied_ = nullptr; @@ -27,7 +28,6 @@ struct YGNode { YGNodeRef owner_ = nullptr; YGVector children_ = {}; YGConfigRef config_ = nullptr; - bool isDirty_ = false; std::array resolvedDimensions_ = { {YGValueUndefined, YGValueUndefined}}; @@ -36,7 +36,11 @@ struct YGNode { const float axisSize) const; public: - YGNode() = default; + YGNode() + : hasNewLayout_(true), + isReferenceBaseline_(false), + isDirty_(false), + nodeType_(YGNodeTypeDefault) {} ~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree explicit YGNode(const YGConfigRef newConfig) : config_(newConfig){}; YGNode(const YGNode& node) = default; From 56e133ab4c7966c0d61c0335b59beeb589d7a223 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Wed, 19 Dec 2018 15:12:27 -0800 Subject: [PATCH 148/189] Do not use glob for static paths. Summary: ``` >>> Lint for xplat/yoga/csharp/BUCK: Warning (BUILDIFIERLINT2) constant-glob Glob pattern `Yoga/YGInterop.cpp` has no wildcard ('*'). Constant patterns can be error-prone, move the file outside the glob. (https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#constant-glob) 30 31 yoga_cxx_library( 32 name = "yoganet", >>> 33 srcs = glob(["Yoga/YGInterop.cpp"]), 34 compiler_flags = COMPILER_FLAGS, 35 link_style = "static", 36 link_whole = True, ``` Differential Revision: D13521382 fbshipit-source-id: 744368e7818370c8ec68f332caaf766cad635e7a --- csharp/BUCK | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/BUCK b/csharp/BUCK index 0f8a0bf8..0df9bea4 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -30,7 +30,7 @@ fb_native.csharp_library( yoga_cxx_library( name = "yoganet", - srcs = glob(["Yoga/YGInterop.cpp"]), + srcs = ["Yoga/YGInterop.cpp"], compiler_flags = COMPILER_FLAGS, link_style = "static", link_whole = True, From 5514722ce27a6c094c91a310fd27942f64f658ed Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 21 Dec 2018 03:12:17 -0800 Subject: [PATCH 149/189] Add tests for `YogaNode#hasNewLayout()` / `#markLayoutSeen()` Summary: @public Adds test for the `hasNewLayout()` and `markLayoutSeen()` methods of `YogaNode`. The behavior of these methods wasn't previously covered by a test. This will allow us to change the implementation with confidence. Reviewed By: SidharthGuglani Differential Revision: D13534351 fbshipit-source-id: 23a9f9b70df18fd7c34023fd77b9df9fbd733f61 --- .../tests/com/facebook/yoga/YogaNodeTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index e65c4ff7..405c322e 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -386,6 +386,52 @@ public class YogaNodeTest { assertFalse(root.getDoesLegacyStretchFlagAffectsLayout()); } + @Test + public void initiallyHasNewLayout() { + YogaNode root = createNode(); + assertTrue(root.hasNewLayout()); + } + + @Test + public void initialLayoutCanBeMarkedSeen() { + YogaNode root = createNode(); + root.markLayoutSeen(); + assertFalse(root.hasNewLayout()); + } + + @Test + public void calculatingLayoutMarksLayoutAsUnseen() { + YogaNode root = createNode(); + root.markLayoutSeen(); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + assertTrue(root.hasNewLayout()); + } + + @Test + public void calculatedLayoutCanBeMarkedSeen() { + YogaNode root = createNode(); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + root.markLayoutSeen(); + assertFalse(root.hasNewLayout()); + } + + @Test + public void recalculatingLayoutDoesMarkAsUnseen() { + YogaNode root = createNode(); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + root.markLayoutSeen(); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + assertTrue(root.hasNewLayout()); + } + + @Test + public void resetAlsoResetsLayoutSeen() { + YogaNode root = createNode(); + root.markLayoutSeen(); + root.reset(); + assertTrue(root.hasNewLayout()); + } + private YogaNode createNode() { return mNodeFactory.create(); } From 138521ccc289c03ad18ff9ac4798e1937bf1c548 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 21 Dec 2018 03:12:17 -0800 Subject: [PATCH 150/189] Test `YogaNode#getLayoutDirection()` Summary: @public Previously untested. Allows us to ship with more confidence Reviewed By: SidharthGuglani Differential Revision: D13534350 fbshipit-source-id: a2e7577befdeeb7a27148e16624eeb7a347efd87 --- java/tests/com/facebook/yoga/YogaNodeTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index 405c322e..a792fe52 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -432,6 +432,16 @@ public class YogaNodeTest { assertTrue(root.hasNewLayout()); } + @Test + public void directionIsPassedThrough() { + YogaNode root = createNode(); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(root.getLayoutDirection(), YogaDirection.RTL); + } + private YogaNode createNode() { return mNodeFactory.create(); } From b9ae948ce9b7acea7b7e30f83a160e2c3c1d9ecd Mon Sep 17 00:00:00 2001 From: Reinier Hartog Date: Mon, 31 Dec 2018 13:36:31 +0100 Subject: [PATCH 151/189] Add fb_native_wrapper.bzl to fix CI --- tools/build_defs/fb_native_wrapper.bzl | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tools/build_defs/fb_native_wrapper.bzl diff --git a/tools/build_defs/fb_native_wrapper.bzl b/tools/build_defs/fb_native_wrapper.bzl new file mode 100644 index 00000000..3d246dee --- /dev/null +++ b/tools/build_defs/fb_native_wrapper.bzl @@ -0,0 +1,109 @@ +# 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. + +fb_native = struct( + android_aar = native.android_aar, + android_app_modularity = native.android_app_modularity, + android_binary = native.android_binary, + android_build_config = native.android_build_config, + android_bundle = native.android_bundle, + android_instrumentation_apk = native.android_instrumentation_apk, + android_instrumentation_test = native.android_instrumentation_test, + android_library = native.android_library, + android_manifest = native.android_manifest, + android_prebuilt_aar = native.android_prebuilt_aar, + android_resource = native.android_resource, + apk_genrule = native.apk_genrule, + apple_asset_catalog = native.apple_asset_catalog, + apple_binary = native.apple_binary, + apple_bundle = native.apple_bundle, + apple_library = native.apple_library, + apple_package = native.apple_package, + apple_resource = native.apple_resource, + apple_test = native.apple_test, + cgo_library = native.cgo_library, + command_alias = native.command_alias, + config_setting = native.config_setting, + constraint_setting = native.constraint_setting, + constraint_value = native.constraint_value, + core_data_model = native.core_data_model, + csharp_library = native.csharp_library, + cxx_binary = native.cxx_binary, + cxx_genrule = native.cxx_genrule, + cxx_library = native.cxx_library, + cxx_lua_extension = native.cxx_lua_extension, + cxx_precompiled_header = native.cxx_precompiled_header, + cxx_python_extension = native.cxx_python_extension, + cxx_test = native.cxx_test, + d_binary = native.d_binary, + d_library = native.d_library, + d_test = native.d_test, + export_file = native.export_file, + filegroup = native.filegroup, + gen_aidl = native.gen_aidl, + genrule = native.genrule, + go_binary = native.go_binary, + go_library = native.go_library, + go_test = native.go_test, + groovy_library = native.groovy_library, + groovy_test = native.groovy_test, + gwt_binary = native.gwt_binary, + halide_library = native.halide_library, + haskell_binary = native.haskell_binary, + haskell_ghci = native.haskell_ghci, + haskell_haddock = native.haskell_haddock, + haskell_library = native.haskell_library, + haskell_prebuilt_library = native.haskell_prebuilt_library, + http_archive = native.http_archive, + http_file = native.http_file, + jar_genrule = native.jar_genrule, + java_annotation_processor = native.java_annotation_processor, + java_binary = native.java_binary, + java_library = native.java_library, + java_test = native.java_test, + js_bundle = native.js_bundle, + js_bundle_genrule = native.js_bundle_genrule, + js_library = native.js_library, + keystore = native.keystore, + kotlin_library = native.kotlin_library, + kotlin_test = native.kotlin_test, + lua_binary = native.lua_binary, + lua_library = native.lua_library, + ndk_library = native.ndk_library, + ocaml_binary = native.ocaml_binary, + ocaml_library = native.ocaml_library, + platform = native.platform, + prebuilt_apple_framework = native.prebuilt_apple_framework, + prebuilt_cxx_library = native.prebuilt_cxx_library, + prebuilt_cxx_library_group = native.prebuilt_cxx_library_group, + prebuilt_dotnet_library = native.prebuilt_dotnet_library, + prebuilt_go_library = native.prebuilt_go_library, + prebuilt_jar = native.prebuilt_jar, + prebuilt_native_library = native.prebuilt_native_library, + prebuilt_ocaml_library = native.prebuilt_ocaml_library, + prebuilt_python_library = native.prebuilt_python_library, + prebuilt_rust_library = native.prebuilt_rust_library, + python_binary = native.python_binary, + python_library = native.python_library, + python_test = native.python_test, + remote_file = native.remote_file, + robolectric_test = native.robolectric_test, + rust_binary = native.rust_binary, + rust_library = native.rust_library, + rust_test = native.rust_test, + scala_library = native.scala_library, + scala_test = native.scala_test, + scene_kit_assets = native.scene_kit_assets, + sh_binary = native.sh_binary, + sh_test = native.sh_test, + swift_library = native.swift_library, + test_suite = native.test_suite, + versioned_alias = native.versioned_alias, + worker_tool = native.worker_tool, + xcode_postbuild_script = native.xcode_postbuild_script, + xcode_prebuild_script = native.xcode_prebuild_script, + xcode_workspace_config = native.xcode_workspace_config, + zip_file = native.zip_file, +) From b66642cb863c12ab1c2c1227b32302adee7df374 Mon Sep 17 00:00:00 2001 From: Sidharth Guglani Date: Fri, 4 Jan 2019 06:02:41 -0800 Subject: [PATCH 152/189] fixed a csharp test case Summary: Using default logger in test case Reviewed By: davidaurelio Differential Revision: D13565071 fbshipit-source-id: 93cee223a7f366e3e965fde2d5cdc7d4b27e310f --- csharp/tests/Facebook.Yoga/YogaNodeTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/tests/Facebook.Yoga/YogaNodeTest.cs b/csharp/tests/Facebook.Yoga/YogaNodeTest.cs index eb9f1e8d..69332735 100644 --- a/csharp/tests/Facebook.Yoga/YogaNodeTest.cs +++ b/csharp/tests/Facebook.Yoga/YogaNodeTest.cs @@ -259,7 +259,7 @@ namespace Facebook.Yoga [Test] public void TestPrintWithLogger() { - YogaNode node = new YogaNode(new YogaConfig{Logger = (c, n, l, m) => {}}); + YogaNode node = new YogaNode(); node.Width = 110; node.Height = 105; node.CalculateLayout(); From 899664dddd39eeee2f784c2671bc9bdb22005b54 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 8 Jan 2019 09:27:46 -0800 Subject: [PATCH 153/189] Remove stray file Summary: @public Remove accidental copy of `Yoga-internal.h` Reviewed By: SidharthGuglani Differential Revision: D13596615 fbshipit-source-id: c137b45caa9c55f75f9bd199be535f1b08977249 --- fbcode/xplat/yoga/yoga/Yoga-internal.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 fbcode/xplat/yoga/yoga/Yoga-internal.h diff --git a/fbcode/xplat/yoga/yoga/Yoga-internal.h b/fbcode/xplat/yoga/yoga/Yoga-internal.h deleted file mode 100644 index e69de29b..00000000 From 5ee32fbefcccb580d93d7cfe60b552e01f9f5bc4 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 8 Jan 2019 12:47:53 -0800 Subject: [PATCH 154/189] Add `.clang-format` Summary: @public Add `.clang-format` for automatic formatting of our C++ code. Reviewed By: SidharthGuglani Differential Revision: D13596651 fbshipit-source-id: c3f866ad552cd7a1d5824f43b093f45842a2142e --- .clang-format | 56 ++++++++++++++++++++++++++++++++++++++++++++ .clang-format-ignore | 1 + 2 files changed, 57 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-format-ignore diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..52a48cf2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,56 @@ +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: false +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 80 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +FixNamespaceComments: true +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyReturnTypeOnItsOwnLine: 2000 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +Standard: Cpp11 +UseTab: Never diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 00000000..51430a06 --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1 @@ +^lib/.* From ab9d06abf595448983d5a120003312abc2140ad6 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 8 Jan 2019 12:47:53 -0800 Subject: [PATCH 155/189] Apply clang-format rules Summary: @public Formats Yoga's source according to our clang-format configuration Reviewed By: SidharthGuglani Differential Revision: D13596650 fbshipit-source-id: c3722d4eafd63b7596a8b1e85c0197e9d2d6cb7d --- benchmark/YGBenchmark.c | 33 ++++---- java/jni/YGJNI.cpp | 28 ++++--- yoga/CompactValue.h | 4 +- yoga/YGEnums.cpp | 64 +++++++-------- yoga/YGEnums.h | 173 ++++++++++++++++++++-------------------- yoga/YGFloatOptional.h | 4 +- yoga/YGLayout.h | 2 +- yoga/YGMacros.h | 8 +- yoga/YGNode.cpp | 3 +- yoga/YGNode.h | 4 +- yoga/YGNodePrint.cpp | 12 ++- yoga/YGStyle.h | 4 +- yoga/YGValue.h | 2 +- yoga/Yoga-internal.h | 8 +- yoga/Yoga.cpp | 8 +- yoga/Yoga.h | 7 +- 16 files changed, 188 insertions(+), 176 deletions(-) diff --git a/benchmark/YGBenchmark.c b/benchmark/YGBenchmark.c index 7256e8f3..2b534378 100644 --- a/benchmark/YGBenchmark.c +++ b/benchmark/YGBenchmark.c @@ -15,7 +15,7 @@ #define NUM_REPETITIONS 1000 #define YGBENCHMARKS(BLOCK) \ - int main(int argc, char const *argv[]) { \ + int main(int argc, char const* argv[]) { \ clock_t __start; \ clock_t __endTimes[NUM_REPETITIONS]; \ { BLOCK } \ @@ -25,14 +25,13 @@ #define YGBENCHMARK(NAME, BLOCK) \ __start = clock(); \ for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \ - { BLOCK } \ - __endTimes[__i] = clock(); \ + {BLOCK} __endTimes[__i] = clock(); \ } \ __printBenchmarkResult(NAME, __start, __endTimes); -static int __compareDoubles(const void *a, const void *b) { - double arg1 = *(const double *) a; - double arg2 = *(const double *) b; +static int __compareDoubles(const void* a, const void* b) { + double arg1 = *(const double*) a; + double arg2 = *(const double*) b; if (arg1 < arg2) { return -1; @@ -45,7 +44,10 @@ static int __compareDoubles(const void *a, const void *b) { return 0; } -static void __printBenchmarkResult(char *name, clock_t start, clock_t *endTimes) { +static void __printBenchmarkResult( + char* name, + clock_t start, + clock_t* endTimes) { double timesInMs[NUM_REPETITIONS]; double mean = 0; clock_t lastEnd = start; @@ -69,12 +71,12 @@ static void __printBenchmarkResult(char *name, clock_t start, clock_t *endTimes) printf("%s: median: %lf ms, stddev: %lf ms\n", name, median, stddev); } - -static YGSize _measure(YGNodeRef node, - float width, - YGMeasureMode widthMode, - float height, - YGMeasureMode heightMode) { +static YGSize _measure( + YGNodeRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode) { return (YGSize){ .width = widthMode == YGMeasureModeUndefined ? 10 : width, .height = heightMode == YGMeasureModeUndefined ? 10 : width, @@ -82,7 +84,6 @@ static YGSize _measure(YGNodeRef node, } YGBENCHMARKS({ - YGBENCHMARK("Stack with flex", { const YGNodeRef root = YGNodeNew(); YGNodeStyleSetWidth(root, 100); @@ -160,7 +161,8 @@ YGBENCHMARKS({ for (uint32_t iiii = 0; iiii < 10; iiii++) { const YGNodeRef grandGrandGrandChild = YGNodeNew(); - YGNodeStyleSetFlexDirection(grandGrandGrandChild, YGFlexDirectionRow); + YGNodeStyleSetFlexDirection( + grandGrandGrandChild, YGFlexDirectionRow); YGNodeStyleSetFlexGrow(grandGrandGrandChild, 1); YGNodeStyleSetWidth(grandGrandGrandChild, 10); YGNodeStyleSetHeight(grandGrandGrandChild, 10); @@ -173,5 +175,4 @@ YGBENCHMARKS({ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); YGNodeFreeRecursive(root); }); - }); diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index fb4ec3c6..ea0d9d07 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -100,7 +100,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { const int PADDING = 2; const int BORDER = 4; - int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); + int hasEdgeSetFlag = (int) obj->getFieldValue(edgeSetFlagField); obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); @@ -180,8 +180,10 @@ static inline YGConfigRef _jlong2YGConfigRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } -static YGNodeRef -YGJNIOnNodeClonedFunc(YGNodeRef oldNode, YGNodeRef owner, int childIndex) { +static YGNodeRef YGJNIOnNodeClonedFunc( + YGNodeRef oldNode, + YGNodeRef owner, + int childIndex) { auto config = oldNode->getConfig(); if (!config) { return nullptr; @@ -404,7 +406,7 @@ void jni_YGNodeMarkDirtyAndPropogateToDescendants(jlong nativePointer) { } jboolean jni_YGNodeIsDirty(jlong nativePointer) { - return (jboolean)_jlong2YGNodeRef(nativePointer)->isDirty(); + return (jboolean) _jlong2YGNodeRef(nativePointer)->isDirty(); } void jni_YGNodeSetHasMeasureFunc(jlong nativePointer, jboolean hasMeasureFunc) { @@ -432,14 +434,14 @@ struct JYogaValue : public JavaClass { } }; -#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \ - javatype jni_YGNodeStyleGet##name(jlong nativePointer) { \ - return (javatype)YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \ - } \ - \ - void jni_YGNodeStyleSet##name(jlong nativePointer, javatype value) { \ - YGNodeStyleSet##name( \ - _jlong2YGNodeRef(nativePointer), static_cast(value)); \ +#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \ + javatype jni_YGNodeStyleGet##name(jlong nativePointer) { \ + return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \ + } \ + \ + void jni_YGNodeStyleSet##name(jlong nativePointer, javatype value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } #define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ @@ -467,7 +469,7 @@ struct JYogaValue : public JavaClass { #define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ javatype jni_YGNodeStyleGet##name(jlong nativePointer, jint edge) { \ - return (javatype)YGNodeStyleGet##name( \ + return (javatype) YGNodeStyleGet##name( \ _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ } \ \ diff --git a/yoga/CompactValue.h b/yoga/CompactValue.h index 7120f1c1..22b9624e 100644 --- a/yoga/CompactValue.h +++ b/yoga/CompactValue.h @@ -42,7 +42,7 @@ namespace detail { class CompactValue { friend constexpr bool operator==(CompactValue, CompactValue) noexcept; - public: +public: static constexpr auto LOWER_BOUND = 1.08420217e-19f; static constexpr auto UPPER_BOUND_POINT = 36893485948395847680.0f; static constexpr auto UPPER_BOUND_PERCENT = 18446742974197923840.0f; @@ -137,7 +137,7 @@ class CompactValue { return payload_.repr == AUTO_BITS; } - private: +private: union Payload { float value; uint32_t repr; diff --git a/yoga/YGEnums.cpp b/yoga/YGEnums.cpp index e2518176..ff4b1307 100644 --- a/yoga/YGEnums.cpp +++ b/yoga/YGEnums.cpp @@ -6,8 +6,8 @@ */ #include "YGEnums.h" -const char *YGAlignToString(const YGAlign value){ - switch(value){ +const char* YGAlignToString(const YGAlign value) { + switch (value) { case YGAlignAuto: return "auto"; case YGAlignFlexStart: @@ -28,8 +28,8 @@ const char *YGAlignToString(const YGAlign value){ return "unknown"; } -const char *YGDimensionToString(const YGDimension value){ - switch(value){ +const char* YGDimensionToString(const YGDimension value) { + switch (value) { case YGDimensionWidth: return "width"; case YGDimensionHeight: @@ -38,8 +38,8 @@ const char *YGDimensionToString(const YGDimension value){ return "unknown"; } -const char *YGDirectionToString(const YGDirection value){ - switch(value){ +const char* YGDirectionToString(const YGDirection value) { + switch (value) { case YGDirectionInherit: return "inherit"; case YGDirectionLTR: @@ -50,8 +50,8 @@ const char *YGDirectionToString(const YGDirection value){ return "unknown"; } -const char *YGDisplayToString(const YGDisplay value){ - switch(value){ +const char* YGDisplayToString(const YGDisplay value) { + switch (value) { case YGDisplayFlex: return "flex"; case YGDisplayNone: @@ -60,8 +60,8 @@ const char *YGDisplayToString(const YGDisplay value){ return "unknown"; } -const char *YGEdgeToString(const YGEdge value){ - switch(value){ +const char* YGEdgeToString(const YGEdge value) { + switch (value) { case YGEdgeLeft: return "left"; case YGEdgeTop: @@ -84,16 +84,16 @@ const char *YGEdgeToString(const YGEdge value){ return "unknown"; } -const char *YGExperimentalFeatureToString(const YGExperimentalFeature value){ - switch(value){ +const char* YGExperimentalFeatureToString(const YGExperimentalFeature value) { + switch (value) { case YGExperimentalFeatureWebFlexBasis: return "web-flex-basis"; } return "unknown"; } -const char *YGFlexDirectionToString(const YGFlexDirection value){ - switch(value){ +const char* YGFlexDirectionToString(const YGFlexDirection value) { + switch (value) { case YGFlexDirectionColumn: return "column"; case YGFlexDirectionColumnReverse: @@ -106,8 +106,8 @@ const char *YGFlexDirectionToString(const YGFlexDirection value){ return "unknown"; } -const char *YGJustifyToString(const YGJustify value){ - switch(value){ +const char* YGJustifyToString(const YGJustify value) { + switch (value) { case YGJustifyFlexStart: return "flex-start"; case YGJustifyCenter: @@ -124,8 +124,8 @@ const char *YGJustifyToString(const YGJustify value){ return "unknown"; } -const char *YGLogLevelToString(const YGLogLevel value){ - switch(value){ +const char* YGLogLevelToString(const YGLogLevel value) { + switch (value) { case YGLogLevelError: return "error"; case YGLogLevelWarn: @@ -142,8 +142,8 @@ const char *YGLogLevelToString(const YGLogLevel value){ return "unknown"; } -const char *YGMeasureModeToString(const YGMeasureMode value){ - switch(value){ +const char* YGMeasureModeToString(const YGMeasureMode value) { + switch (value) { case YGMeasureModeUndefined: return "undefined"; case YGMeasureModeExactly: @@ -154,8 +154,8 @@ const char *YGMeasureModeToString(const YGMeasureMode value){ return "unknown"; } -const char *YGNodeTypeToString(const YGNodeType value){ - switch(value){ +const char* YGNodeTypeToString(const YGNodeType value) { + switch (value) { case YGNodeTypeDefault: return "default"; case YGNodeTypeText: @@ -164,8 +164,8 @@ const char *YGNodeTypeToString(const YGNodeType value){ return "unknown"; } -const char *YGOverflowToString(const YGOverflow value){ - switch(value){ +const char* YGOverflowToString(const YGOverflow value) { + switch (value) { case YGOverflowVisible: return "visible"; case YGOverflowHidden: @@ -176,8 +176,8 @@ const char *YGOverflowToString(const YGOverflow value){ return "unknown"; } -const char *YGPositionTypeToString(const YGPositionType value){ - switch(value){ +const char* YGPositionTypeToString(const YGPositionType value) { + switch (value) { case YGPositionTypeRelative: return "relative"; case YGPositionTypeAbsolute: @@ -186,8 +186,8 @@ const char *YGPositionTypeToString(const YGPositionType value){ return "unknown"; } -const char *YGPrintOptionsToString(const YGPrintOptions value){ - switch(value){ +const char* YGPrintOptionsToString(const YGPrintOptions value) { + switch (value) { case YGPrintOptionsLayout: return "layout"; case YGPrintOptionsStyle: @@ -198,8 +198,8 @@ const char *YGPrintOptionsToString(const YGPrintOptions value){ return "unknown"; } -const char *YGUnitToString(const YGUnit value){ - switch(value){ +const char* YGUnitToString(const YGUnit value) { + switch (value) { case YGUnitUndefined: return "undefined"; case YGUnitPoint: @@ -212,8 +212,8 @@ const char *YGUnitToString(const YGUnit value){ return "unknown"; } -const char *YGWrapToString(const YGWrap value){ - switch(value){ +const char* YGWrapToString(const YGWrap value) { + switch (value) { case YGWrapNoWrap: return "no-wrap"; case YGWrapWrap: diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index da223051..222f0ed0 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -11,68 +11,69 @@ YG_EXTERN_C_BEGIN #define YGAlignCount 8 -typedef YG_ENUM_BEGIN(YGAlign) { - YGAlignAuto, - YGAlignFlexStart, - YGAlignCenter, - YGAlignFlexEnd, - YGAlignStretch, - YGAlignBaseline, - YGAlignSpaceBetween, - YGAlignSpaceAround, +typedef YG_ENUM_BEGIN(YGAlign){ + YGAlignAuto, + YGAlignFlexStart, + YGAlignCenter, + YGAlignFlexEnd, + YGAlignStretch, + YGAlignBaseline, + YGAlignSpaceBetween, + YGAlignSpaceAround, } YG_ENUM_END(YGAlign); -WIN_EXPORT const char *YGAlignToString(const YGAlign value); +WIN_EXPORT const char* YGAlignToString(const YGAlign value); #define YGDimensionCount 2 -typedef YG_ENUM_BEGIN(YGDimension) { - YGDimensionWidth, - YGDimensionHeight, +typedef YG_ENUM_BEGIN(YGDimension){ + YGDimensionWidth, + YGDimensionHeight, } YG_ENUM_END(YGDimension); -WIN_EXPORT const char *YGDimensionToString(const YGDimension value); +WIN_EXPORT const char* YGDimensionToString(const YGDimension value); #define YGDirectionCount 3 -typedef YG_ENUM_BEGIN(YGDirection) { - YGDirectionInherit, - YGDirectionLTR, - YGDirectionRTL, +typedef YG_ENUM_BEGIN(YGDirection){ + YGDirectionInherit, + YGDirectionLTR, + YGDirectionRTL, } YG_ENUM_END(YGDirection); -WIN_EXPORT const char *YGDirectionToString(const YGDirection value); +WIN_EXPORT const char* YGDirectionToString(const YGDirection value); #define YGDisplayCount 2 -typedef YG_ENUM_BEGIN(YGDisplay) { - YGDisplayFlex, - YGDisplayNone, +typedef YG_ENUM_BEGIN(YGDisplay){ + YGDisplayFlex, + YGDisplayNone, } YG_ENUM_END(YGDisplay); -WIN_EXPORT const char *YGDisplayToString(const YGDisplay value); +WIN_EXPORT const char* YGDisplayToString(const YGDisplay value); #define YGEdgeCount 9 -typedef YG_ENUM_BEGIN(YGEdge) { - YGEdgeLeft, - YGEdgeTop, - YGEdgeRight, - YGEdgeBottom, - YGEdgeStart, - YGEdgeEnd, - YGEdgeHorizontal, - YGEdgeVertical, - YGEdgeAll, +typedef YG_ENUM_BEGIN(YGEdge){ + YGEdgeLeft, + YGEdgeTop, + YGEdgeRight, + YGEdgeBottom, + YGEdgeStart, + YGEdgeEnd, + YGEdgeHorizontal, + YGEdgeVertical, + YGEdgeAll, } YG_ENUM_END(YGEdge); -WIN_EXPORT const char *YGEdgeToString(const YGEdge value); +WIN_EXPORT const char* YGEdgeToString(const YGEdge value); #define YGExperimentalFeatureCount 1 -typedef YG_ENUM_BEGIN(YGExperimentalFeature) { - YGExperimentalFeatureWebFlexBasis, +typedef YG_ENUM_BEGIN(YGExperimentalFeature){ + YGExperimentalFeatureWebFlexBasis, } YG_ENUM_END(YGExperimentalFeature); -WIN_EXPORT const char *YGExperimentalFeatureToString(const YGExperimentalFeature value); +WIN_EXPORT const char* YGExperimentalFeatureToString( + const YGExperimentalFeature value); #define YGFlexDirectionCount 4 -typedef YG_ENUM_BEGIN(YGFlexDirection) { - YGFlexDirectionColumn, - YGFlexDirectionColumnReverse, - YGFlexDirectionRow, - YGFlexDirectionRowReverse, +typedef YG_ENUM_BEGIN(YGFlexDirection){ + YGFlexDirectionColumn, + YGFlexDirectionColumnReverse, + YGFlexDirectionRow, + YGFlexDirectionRowReverse, } YG_ENUM_END(YGFlexDirection); -WIN_EXPORT const char *YGFlexDirectionToString(const YGFlexDirection value); +WIN_EXPORT const char* YGFlexDirectionToString(const YGFlexDirection value); #define YGJustifyCount 6 typedef YG_ENUM_BEGIN(YGJustify){ @@ -83,72 +84,72 @@ typedef YG_ENUM_BEGIN(YGJustify){ YGJustifySpaceAround, YGJustifySpaceEvenly, } YG_ENUM_END(YGJustify); -WIN_EXPORT const char *YGJustifyToString(const YGJustify value); +WIN_EXPORT const char* YGJustifyToString(const YGJustify value); #define YGLogLevelCount 6 -typedef YG_ENUM_BEGIN(YGLogLevel) { - YGLogLevelError, - YGLogLevelWarn, - YGLogLevelInfo, - YGLogLevelDebug, - YGLogLevelVerbose, - YGLogLevelFatal, +typedef YG_ENUM_BEGIN(YGLogLevel){ + YGLogLevelError, + YGLogLevelWarn, + YGLogLevelInfo, + YGLogLevelDebug, + YGLogLevelVerbose, + YGLogLevelFatal, } YG_ENUM_END(YGLogLevel); -WIN_EXPORT const char *YGLogLevelToString(const YGLogLevel value); +WIN_EXPORT const char* YGLogLevelToString(const YGLogLevel value); #define YGMeasureModeCount 3 -typedef YG_ENUM_BEGIN(YGMeasureMode) { - YGMeasureModeUndefined, - YGMeasureModeExactly, - YGMeasureModeAtMost, +typedef YG_ENUM_BEGIN(YGMeasureMode){ + YGMeasureModeUndefined, + YGMeasureModeExactly, + YGMeasureModeAtMost, } YG_ENUM_END(YGMeasureMode); -WIN_EXPORT const char *YGMeasureModeToString(const YGMeasureMode value); +WIN_EXPORT const char* YGMeasureModeToString(const YGMeasureMode value); #define YGNodeTypeCount 2 -typedef YG_ENUM_BEGIN(YGNodeType) { - YGNodeTypeDefault, - YGNodeTypeText, +typedef YG_ENUM_BEGIN(YGNodeType){ + YGNodeTypeDefault, + YGNodeTypeText, } YG_ENUM_END(YGNodeType); -WIN_EXPORT const char *YGNodeTypeToString(const YGNodeType value); +WIN_EXPORT const char* YGNodeTypeToString(const YGNodeType value); #define YGOverflowCount 3 -typedef YG_ENUM_BEGIN(YGOverflow) { - YGOverflowVisible, - YGOverflowHidden, - YGOverflowScroll, +typedef YG_ENUM_BEGIN(YGOverflow){ + YGOverflowVisible, + YGOverflowHidden, + YGOverflowScroll, } YG_ENUM_END(YGOverflow); -WIN_EXPORT const char *YGOverflowToString(const YGOverflow value); +WIN_EXPORT const char* YGOverflowToString(const YGOverflow value); #define YGPositionTypeCount 2 -typedef YG_ENUM_BEGIN(YGPositionType) { - YGPositionTypeRelative, - YGPositionTypeAbsolute, +typedef YG_ENUM_BEGIN(YGPositionType){ + YGPositionTypeRelative, + YGPositionTypeAbsolute, } YG_ENUM_END(YGPositionType); -WIN_EXPORT const char *YGPositionTypeToString(const YGPositionType value); +WIN_EXPORT const char* YGPositionTypeToString(const YGPositionType value); #define YGPrintOptionsCount 3 -typedef YG_ENUM_BEGIN(YGPrintOptions) { - YGPrintOptionsLayout = 1, - YGPrintOptionsStyle = 2, - YGPrintOptionsChildren = 4, +typedef YG_ENUM_BEGIN(YGPrintOptions){ + YGPrintOptionsLayout = 1, + YGPrintOptionsStyle = 2, + YGPrintOptionsChildren = 4, } YG_ENUM_END(YGPrintOptions); -WIN_EXPORT const char *YGPrintOptionsToString(const YGPrintOptions value); +WIN_EXPORT const char* YGPrintOptionsToString(const YGPrintOptions value); #define YGUnitCount 4 -typedef YG_ENUM_BEGIN(YGUnit) { - YGUnitUndefined, - YGUnitPoint, - YGUnitPercent, - YGUnitAuto, +typedef YG_ENUM_BEGIN(YGUnit){ + YGUnitUndefined, + YGUnitPoint, + YGUnitPercent, + YGUnitAuto, } YG_ENUM_END(YGUnit); -WIN_EXPORT const char *YGUnitToString(const YGUnit value); +WIN_EXPORT const char* YGUnitToString(const YGUnit value); #define YGWrapCount 3 -typedef YG_ENUM_BEGIN(YGWrap) { - YGWrapNoWrap, - YGWrapWrap, - YGWrapWrapReverse, +typedef YG_ENUM_BEGIN(YGWrap){ + YGWrapNoWrap, + YGWrapWrap, + YGWrapWrapReverse, } YG_ENUM_END(YGWrap); -WIN_EXPORT const char *YGWrapToString(const YGWrap value); +WIN_EXPORT const char* YGWrapToString(const YGWrap value); YG_EXTERN_C_END diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 44cf344e..02d4c856 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -11,10 +11,10 @@ #include "Yoga-internal.h" struct YGFloatOptional { - private: +private: float value_ = std::numeric_limits::quiet_NaN(); - public: +public: explicit constexpr YGFloatOptional(float value) : value_(value) {} constexpr YGFloatOptional() = default; diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 94a92adf..4a68d86a 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -28,7 +28,7 @@ struct YGLayout { // Instead of recomputing the entire layout every single time, we // cache some information to break early when nothing changed uint32_t generationCount = 0; - YGDirection lastOwnerDirection = (YGDirection)-1; + YGDirection lastOwnerDirection = (YGDirection) -1; uint32_t nextCachedMeasurementsIndex = 0; std::array diff --git a/yoga/YGMacros.h b/yoga/YGMacros.h index 7da8a870..0e131902 100644 --- a/yoga/YGMacros.h +++ b/yoga/YGMacros.h @@ -21,7 +21,7 @@ #endif #ifdef WINARMDLL -#define WIN_STRUCT(type) type * +#define WIN_STRUCT(type) type* #define WIN_STRUCT_REF(value) &value #else #define WIN_STRUCT(type) type @@ -29,9 +29,9 @@ #endif #ifdef NS_ENUM -// Cannot use NSInteger as NSInteger has a different size than int (which is the default type of a -// enum). -// Therefor when linking the Yoga C library into obj-c the header is a missmatch for the Yoga ABI. +// Cannot use NSInteger as NSInteger has a different size than int (which is the +// default type of a enum). Therefor when linking the Yoga C library into obj-c +// the header is a missmatch for the Yoga ABI. #define YG_ENUM_BEGIN(name) NS_ENUM(int, name) #define YG_ENUM_END(name) #else diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 8e7e210b..022e6067 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -113,7 +113,8 @@ void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { YGAssertWithNode( this, children_.size() == 0, - "Cannot set measure function: Nodes with measure functions cannot have children."); + "Cannot set measure function: Nodes with measure functions cannot have " + "children."); measure_ = measureFunc; // TODO: t18095186 Move nodeType to opt-in function and mark appropriate // places in Litho diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 2c00ec75..db1e7d42 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -12,7 +12,7 @@ #include "Yoga-internal.h" struct YGNode { - private: +private: void* context_ = nullptr; YGPrintFunc print_ = nullptr; bool hasNewLayout_ : 1; @@ -35,7 +35,7 @@ struct YGNode { const YGFlexDirection axis, const float axisSize) const; - public: +public: YGNode() : hasNewLayout_(true), isReferenceBaseline_(false), diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 4be2ff5a..1c0c2708 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -63,15 +63,19 @@ static void appendNumberIfNotUndefined( } } -static void -appendNumberIfNotAuto(string& base, const string& key, const YGValue number) { +static void appendNumberIfNotAuto( + string& base, + const string& key, + const YGValue number) { if (number.unit != YGUnitAuto) { appendNumberIfNotUndefined(base, key, number); } } -static void -appendNumberIfNotZero(string& base, const string& str, const YGValue number) { +static void appendNumberIfNotZero( + string& base, + const string& str, + const YGValue number) { if (number.unit == YGUnitAuto) { base.append(str + ": auto; "); } else if (!YGFloatsEqual(number.value, 0)) { diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index abcc7052..05d594b1 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -18,10 +18,10 @@ constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; struct YGStyle { - private: +private: using CompactValue = facebook::yoga::detail::CompactValue; - public: +public: using Dimensions = facebook::yoga::detail::Values<2>; using Edges = facebook::yoga::detail::Values; diff --git a/yoga/YGValue.h b/yoga/YGValue.h index c3df5fc9..2395e07c 100644 --- a/yoga/YGValue.h +++ b/yoga/YGValue.h @@ -15,7 +15,7 @@ YG_EXTERN_C_BEGIN // Not defined in MSVC++ #ifndef NAN static const uint32_t __nan = 0x7fc00000; -#define NAN (*(const float*)__nan) +#define NAN (*(const float*) __nan) #endif #define YGUndefined NAN diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index a182a465..50d96dc2 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -55,8 +55,8 @@ struct YGCachedMeasurement { YGCachedMeasurement() : availableWidth(0), availableHeight(0), - widthMeasureMode((YGMeasureMode)-1), - heightMeasureMode((YGMeasureMode)-1), + widthMeasureMode((YGMeasureMode) -1), + heightMeasureMode((YGMeasureMode) -1), computedWidth(-1), computedHeight(-1) {} @@ -95,10 +95,10 @@ namespace detail { template class Values { - private: +private: std::array values_; - public: +public: Values() = default; explicit Values(const YGValue& defaultValue) noexcept { values_.fill(defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 9b8aa8a4..fc9bb0da 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -74,7 +74,7 @@ static int YGAndroidLog( return result; } #else -#define YG_UNUSED(x) (void)(x); +#define YG_UNUSED(x) (void) (x); static int YGDefaultLog( const YGConfigRef config, @@ -921,7 +921,7 @@ float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) { return YGUndefined; } - auto border = (YGValue)node->getStyle().border[edge]; + auto border = (YGValue) node->getStyle().border[edge]; return border.value; } @@ -3745,8 +3745,8 @@ bool YGLayoutNodeInternal( if (needToVisitNode) { // Invalidate the cached results. layout->nextCachedMeasurementsIndex = 0; - layout->cachedLayout.widthMeasureMode = (YGMeasureMode)-1; - layout->cachedLayout.heightMeasureMode = (YGMeasureMode)-1; + layout->cachedLayout.widthMeasureMode = (YGMeasureMode) -1; + layout->cachedLayout.heightMeasureMode = (YGMeasureMode) -1; layout->cachedLayout.computedWidth = -1; layout->cachedLayout.computedHeight = -1; } diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 787af6df..0c45cbe1 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -358,8 +358,11 @@ WIN_EXPORT float YGNodeLayoutGetPadding( const YGEdge edge); WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger); -WIN_EXPORT void -YGLog(const YGNodeRef node, YGLogLevel level, const char* message, ...); +WIN_EXPORT void YGLog( + const YGNodeRef node, + YGLogLevel level, + const char* message, + ...); WIN_EXPORT void YGLogWithConfig( const YGConfigRef config, YGLogLevel level, From 4b97375524185dfb5124b9a8c30799bd8acda5e6 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 8 Jan 2019 12:47:54 -0800 Subject: [PATCH 156/189] Remove repetition in `YGEnums.h` Summary: @public Wraps enum definition in a single macro. Down the line, this will allow us to add more functionality: - Replace manual counts with `yoga::enums::count()` - `yoga::enums::max()` - A bitfield implementation with known memory layout using `max<>()` Reviewed By: SidharthGuglani Differential Revision: D13597259 fbshipit-source-id: 543a11a53090bedf1474d00328565ed57d059e23 --- yoga/YGEnums.h | 114 ++++++++++++++++--------------------------------- 1 file changed, 36 insertions(+), 78 deletions(-) diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index 222f0ed0..00be5044 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -8,10 +8,15 @@ #include "YGMacros.h" +#define YG_ENUM_DECL(NAME, ...) \ + typedef YG_ENUM_BEGIN(NAME){__VA_ARGS__} YG_ENUM_END(NAME); \ + WIN_EXPORT const char* NAME##ToString(NAME); + YG_EXTERN_C_BEGIN #define YGAlignCount 8 -typedef YG_ENUM_BEGIN(YGAlign){ +YG_ENUM_DECL( + YGAlign, YGAlignAuto, YGAlignFlexStart, YGAlignCenter, @@ -19,34 +24,20 @@ typedef YG_ENUM_BEGIN(YGAlign){ YGAlignStretch, YGAlignBaseline, YGAlignSpaceBetween, - YGAlignSpaceAround, -} YG_ENUM_END(YGAlign); -WIN_EXPORT const char* YGAlignToString(const YGAlign value); + YGAlignSpaceAround); #define YGDimensionCount 2 -typedef YG_ENUM_BEGIN(YGDimension){ - YGDimensionWidth, - YGDimensionHeight, -} YG_ENUM_END(YGDimension); -WIN_EXPORT const char* YGDimensionToString(const YGDimension value); +YG_ENUM_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) #define YGDirectionCount 3 -typedef YG_ENUM_BEGIN(YGDirection){ - YGDirectionInherit, - YGDirectionLTR, - YGDirectionRTL, -} YG_ENUM_END(YGDirection); -WIN_EXPORT const char* YGDirectionToString(const YGDirection value); +YG_ENUM_DECL(YGDirection, YGDirectionInherit, YGDirectionLTR, YGDirectionRTL) #define YGDisplayCount 2 -typedef YG_ENUM_BEGIN(YGDisplay){ - YGDisplayFlex, - YGDisplayNone, -} YG_ENUM_END(YGDisplay); -WIN_EXPORT const char* YGDisplayToString(const YGDisplay value); +YG_ENUM_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) #define YGEdgeCount 9 -typedef YG_ENUM_BEGIN(YGEdge){ +YG_ENUM_DECL( + YGEdge, YGEdgeLeft, YGEdgeTop, YGEdgeRight, @@ -55,101 +46,68 @@ typedef YG_ENUM_BEGIN(YGEdge){ YGEdgeEnd, YGEdgeHorizontal, YGEdgeVertical, - YGEdgeAll, -} YG_ENUM_END(YGEdge); -WIN_EXPORT const char* YGEdgeToString(const YGEdge value); + YGEdgeAll) #define YGExperimentalFeatureCount 1 -typedef YG_ENUM_BEGIN(YGExperimentalFeature){ - YGExperimentalFeatureWebFlexBasis, -} YG_ENUM_END(YGExperimentalFeature); -WIN_EXPORT const char* YGExperimentalFeatureToString( - const YGExperimentalFeature value); +YG_ENUM_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) #define YGFlexDirectionCount 4 -typedef YG_ENUM_BEGIN(YGFlexDirection){ +YG_ENUM_DECL( + YGFlexDirection, YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, - YGFlexDirectionRowReverse, -} YG_ENUM_END(YGFlexDirection); -WIN_EXPORT const char* YGFlexDirectionToString(const YGFlexDirection value); + YGFlexDirectionRowReverse) #define YGJustifyCount 6 -typedef YG_ENUM_BEGIN(YGJustify){ +YG_ENUM_DECL( + YGJustify, YGJustifyFlexStart, YGJustifyCenter, YGJustifyFlexEnd, YGJustifySpaceBetween, YGJustifySpaceAround, - YGJustifySpaceEvenly, -} YG_ENUM_END(YGJustify); -WIN_EXPORT const char* YGJustifyToString(const YGJustify value); + YGJustifySpaceEvenly) #define YGLogLevelCount 6 -typedef YG_ENUM_BEGIN(YGLogLevel){ +YG_ENUM_DECL( + YGLogLevel, YGLogLevelError, YGLogLevelWarn, YGLogLevelInfo, YGLogLevelDebug, YGLogLevelVerbose, - YGLogLevelFatal, -} YG_ENUM_END(YGLogLevel); -WIN_EXPORT const char* YGLogLevelToString(const YGLogLevel value); + YGLogLevelFatal) #define YGMeasureModeCount 3 -typedef YG_ENUM_BEGIN(YGMeasureMode){ +YG_ENUM_DECL( + YGMeasureMode, YGMeasureModeUndefined, YGMeasureModeExactly, - YGMeasureModeAtMost, -} YG_ENUM_END(YGMeasureMode); -WIN_EXPORT const char* YGMeasureModeToString(const YGMeasureMode value); + YGMeasureModeAtMost) #define YGNodeTypeCount 2 -typedef YG_ENUM_BEGIN(YGNodeType){ - YGNodeTypeDefault, - YGNodeTypeText, -} YG_ENUM_END(YGNodeType); -WIN_EXPORT const char* YGNodeTypeToString(const YGNodeType value); +YG_ENUM_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) #define YGOverflowCount 3 -typedef YG_ENUM_BEGIN(YGOverflow){ - YGOverflowVisible, - YGOverflowHidden, - YGOverflowScroll, -} YG_ENUM_END(YGOverflow); -WIN_EXPORT const char* YGOverflowToString(const YGOverflow value); +YG_ENUM_DECL(YGOverflow, YGOverflowVisible, YGOverflowHidden, YGOverflowScroll) #define YGPositionTypeCount 2 -typedef YG_ENUM_BEGIN(YGPositionType){ - YGPositionTypeRelative, - YGPositionTypeAbsolute, -} YG_ENUM_END(YGPositionType); -WIN_EXPORT const char* YGPositionTypeToString(const YGPositionType value); +YG_ENUM_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) #define YGPrintOptionsCount 3 -typedef YG_ENUM_BEGIN(YGPrintOptions){ +YG_ENUM_DECL( + YGPrintOptions, YGPrintOptionsLayout = 1, YGPrintOptionsStyle = 2, - YGPrintOptionsChildren = 4, -} YG_ENUM_END(YGPrintOptions); -WIN_EXPORT const char* YGPrintOptionsToString(const YGPrintOptions value); + YGPrintOptionsChildren = 4) #define YGUnitCount 4 -typedef YG_ENUM_BEGIN(YGUnit){ - YGUnitUndefined, - YGUnitPoint, - YGUnitPercent, - YGUnitAuto, -} YG_ENUM_END(YGUnit); -WIN_EXPORT const char* YGUnitToString(const YGUnit value); +YG_ENUM_DECL(YGUnit, YGUnitUndefined, YGUnitPoint, YGUnitPercent, YGUnitAuto) #define YGWrapCount 3 -typedef YG_ENUM_BEGIN(YGWrap){ - YGWrapNoWrap, - YGWrapWrap, - YGWrapWrapReverse, -} YG_ENUM_END(YGWrap); -WIN_EXPORT const char* YGWrapToString(const YGWrap value); +YG_ENUM_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) YG_EXTERN_C_END + +#undef YG_ENUM_DECL From efac22a508bb5be9ac80b04f854d46f681a3c639 Mon Sep 17 00:00:00 2001 From: Marko Novakovic Date: Tue, 8 Jan 2019 16:16:59 -0800 Subject: [PATCH 157/189] Using ENUM_BITFIELDS_NOT_SUPPORTED for enum bitfields Reviewed By: davidaurelio Differential Revision: D13556160 fbshipit-source-id: e6d373a4e1dd702509b5d63606c08fae9cdb5498 --- yoga/YGStyle.h | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 05d594b1..9193c69d 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -13,6 +13,12 @@ #include "Yoga-internal.h" #include "Yoga.h" +#if !defined(ENUM_BITFIELDS_NOT_SUPPORTED) +#define BITFIELD_ENUM_SIZED(num) : num +#else +#define BITFIELD_ENUM_SIZED(num) +#endif + constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; @@ -25,16 +31,18 @@ public: using Dimensions = facebook::yoga::detail::Values<2>; using Edges = facebook::yoga::detail::Values; - YGDirection direction : 2; - YGFlexDirection flexDirection : 2; - YGJustify justifyContent : 3; - YGAlign alignContent : 3; - YGAlign alignItems : 3; - YGAlign alignSelf : 3; - YGPositionType positionType : 1; - YGWrap flexWrap : 2; - YGOverflow overflow : 2; - YGDisplay display : 1; + /* Some platforms don't support enum bitfields, + so please use BITFIELD_ENUM_SIZED(BITS_COUNT) */ + YGDirection direction BITFIELD_ENUM_SIZED(2); + YGFlexDirection flexDirection BITFIELD_ENUM_SIZED(2); + YGJustify justifyContent BITFIELD_ENUM_SIZED(3); + YGAlign alignContent BITFIELD_ENUM_SIZED(3); + YGAlign alignItems BITFIELD_ENUM_SIZED(3); + YGAlign alignSelf BITFIELD_ENUM_SIZED(3); + YGPositionType positionType BITFIELD_ENUM_SIZED(1); + YGWrap flexWrap BITFIELD_ENUM_SIZED(2); + YGOverflow overflow BITFIELD_ENUM_SIZED(2); + YGDisplay display BITFIELD_ENUM_SIZED(1); YGFloatOptional flex = {}; YGFloatOptional flexGrow = {}; YGFloatOptional flexShrink = {}; From ef2c693b05bb4d43506be83438d8c1bca92bde76 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 10 Jan 2019 07:35:55 -0800 Subject: [PATCH 158/189] Remove enum count macros Summary: @public Removes all `YG...Count` macros for enums and replaces them with `facebook::yoga::enums::count()`. This removes the need to manually maintain enum counts. Reviewed By: shergin Differential Revision: D13597449 fbshipit-source-id: edcee225ada4058e94f3a727246763e3cc45873d --- yoga/YGConfig.h | 3 +- yoga/YGEnums.h | 99 ++++++++++++++++++++++++++++++-------------- yoga/YGNode.cpp | 3 +- yoga/YGNodePrint.cpp | 7 ++-- yoga/YGStyle.h | 4 +- yoga/Yoga-internal.h | 3 +- yoga/Yoga.cpp | 14 +++---- 7 files changed, 86 insertions(+), 47 deletions(-) diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index c9b871fe..00415ce9 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -10,7 +10,8 @@ #include "Yoga.h" struct YGConfig { - std::array experimentalFeatures = {}; + std::array()> + experimentalFeatures = {}; bool useWebDefaults = false; bool useLegacyStretchBehaviour = false; bool shouldDiffLayoutWithoutLegacyStretchBehaviour = false; diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index 00be5044..ea4e1882 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -8,14 +8,52 @@ #include "YGMacros.h" +#ifdef __cplusplus +namespace facebook { +namespace yoga { +namespace enums { + +template +constexpr int count() = delete; + +namespace detail { +template +constexpr int n() { + return sizeof...(xs); +} +} // namespace detail + +} // namespace enums +} // namespace yoga +} // namespace facebook +#endif + #define YG_ENUM_DECL(NAME, ...) \ typedef YG_ENUM_BEGIN(NAME){__VA_ARGS__} YG_ENUM_END(NAME); \ WIN_EXPORT const char* NAME##ToString(NAME); +#ifdef __cplusplus +#define YG_ENUM_SEQ_DECL(NAME, ...) \ + YG_ENUM_DECL(NAME, __VA_ARGS__) \ + YG_EXTERN_C_END \ + namespace facebook { \ + namespace yoga { \ + namespace enums { \ + template <> \ + constexpr int count() { \ + return detail::n<__VA_ARGS__>(); \ + } \ + } \ + } \ + } \ + YG_EXTERN_C_BEGIN +#else +#define YG_ENUM_SEQ_DECL YG_ENUM_DECL +#endif + YG_EXTERN_C_BEGIN -#define YGAlignCount 8 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGAlign, YGAlignAuto, YGAlignFlexStart, @@ -26,17 +64,17 @@ YG_ENUM_DECL( YGAlignSpaceBetween, YGAlignSpaceAround); -#define YGDimensionCount 2 -YG_ENUM_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) +YG_ENUM_SEQ_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) -#define YGDirectionCount 3 -YG_ENUM_DECL(YGDirection, YGDirectionInherit, YGDirectionLTR, YGDirectionRTL) +YG_ENUM_SEQ_DECL( + YGDirection, + YGDirectionInherit, + YGDirectionLTR, + YGDirectionRTL) -#define YGDisplayCount 2 -YG_ENUM_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) +YG_ENUM_SEQ_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) -#define YGEdgeCount 9 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGEdge, YGEdgeLeft, YGEdgeTop, @@ -48,19 +86,16 @@ YG_ENUM_DECL( YGEdgeVertical, YGEdgeAll) -#define YGExperimentalFeatureCount 1 -YG_ENUM_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) +YG_ENUM_SEQ_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) -#define YGFlexDirectionCount 4 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGFlexDirection, YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, YGFlexDirectionRowReverse) -#define YGJustifyCount 6 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGJustify, YGJustifyFlexStart, YGJustifyCenter, @@ -69,8 +104,7 @@ YG_ENUM_DECL( YGJustifySpaceAround, YGJustifySpaceEvenly) -#define YGLogLevelCount 6 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGLogLevel, YGLogLevelError, YGLogLevelWarn, @@ -79,35 +113,38 @@ YG_ENUM_DECL( YGLogLevelVerbose, YGLogLevelFatal) -#define YGMeasureModeCount 3 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGMeasureMode, YGMeasureModeUndefined, YGMeasureModeExactly, YGMeasureModeAtMost) -#define YGNodeTypeCount 2 -YG_ENUM_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) +YG_ENUM_SEQ_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) -#define YGOverflowCount 3 -YG_ENUM_DECL(YGOverflow, YGOverflowVisible, YGOverflowHidden, YGOverflowScroll) +YG_ENUM_SEQ_DECL( + YGOverflow, + YGOverflowVisible, + YGOverflowHidden, + YGOverflowScroll) -#define YGPositionTypeCount 2 -YG_ENUM_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) +YG_ENUM_SEQ_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) -#define YGPrintOptionsCount 3 YG_ENUM_DECL( YGPrintOptions, YGPrintOptionsLayout = 1, YGPrintOptionsStyle = 2, YGPrintOptionsChildren = 4) -#define YGUnitCount 4 -YG_ENUM_DECL(YGUnit, YGUnitUndefined, YGUnitPoint, YGUnitPercent, YGUnitAuto) +YG_ENUM_SEQ_DECL( + YGUnit, + YGUnitUndefined, + YGUnitPoint, + YGUnitPercent, + YGUnitAuto) -#define YGWrapCount 3 -YG_ENUM_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) +YG_ENUM_SEQ_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) YG_EXTERN_C_END #undef YG_ENUM_DECL +#undef YG_ENUM_SEQ_DECL diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 022e6067..255db920 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -313,7 +313,8 @@ YGValue YGNode::resolveFlexBasisPtr() const { } void YGNode::resolveDimension() { - for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) { + using namespace yoga; + for (int dim = YGDimensionWidth; dim < enums::count(); dim++) { if (!getStyle().maxDimensions[dim].isUndefined() && YGValueEqual( getStyle().maxDimensions[dim], style_.minDimensions[dim])) { diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 1c0c2708..4e02deee 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -20,8 +20,7 @@ static void indent(string& base, uint32_t level) { } } -static bool areFourValuesEqual( - const facebook::yoga::detail::Values& four) { +static bool areFourValuesEqual(const YGStyle::Edges& four) { return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) && YGValueEqual(four[0], four[3]); } @@ -86,7 +85,7 @@ static void appendNumberIfNotZero( static void appendEdges( string& base, const string& key, - const facebook::yoga::detail::Values& edges) { + const YGStyle::Edges& edges) { if (areFourValuesEqual(edges)) { appendNumberIfNotZero(base, key, edges[YGEdgeLeft]); } else { @@ -100,7 +99,7 @@ static void appendEdges( static void appendEdgeIfNotUndefined( string& base, const string& str, - const facebook::yoga::detail::Values& edges, + const YGStyle::Edges& edges, const YGEdge edge) { appendNumberIfNotUndefined( base, diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 9193c69d..e540635d 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -9,6 +9,7 @@ #include #include #include "CompactValue.h" +#include "YGEnums.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -29,7 +30,8 @@ private: public: using Dimensions = facebook::yoga::detail::Values<2>; - using Edges = facebook::yoga::detail::Values; + using Edges = + facebook::yoga::detail::Values()>; /* Some platforms don't support enum bitfields, so please use BITFIELD_ENUM_SIZED(BITS_COUNT) */ diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 50d96dc2..1932cf1a 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -149,6 +149,7 @@ static const float kWebDefaultFlexShrink = 1.0f; extern bool YGFloatsEqual(const float a, const float b); extern bool YGValueEqual(const YGValue a, const YGValue b); extern facebook::yoga::detail::CompactValue YGComputedEdgeValue( - const facebook::yoga::detail::Values& edges, + const facebook::yoga::detail::Values< + facebook::yoga::enums::count()>& edges, YGEdge edge, facebook::yoga::detail::CompactValue defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index fc9bb0da..0d11c7a3 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -105,7 +105,7 @@ bool YGFloatIsUndefined(const float value) { } detail::CompactValue YGComputedEdgeValue( - const facebook::yoga::detail::Values& edges, + const YGStyle::Edges& edges, YGEdge edge, detail::CompactValue defaultValue) { if (!edges[edge].isUndefined()) { @@ -3546,14 +3546,12 @@ static const char* YGSpacer(const unsigned long level) { static const char* YGMeasureModeName( const YGMeasureMode mode, const bool performLayout) { - const char* kMeasureModeNames[YGMeasureModeCount] = { - "UNDEFINED", "EXACTLY", "AT_MOST"}; - const char* kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", - "LAY_EXACTLY", - "LAY_AT_" - "MOST"}; + constexpr auto N = enums::count(); + const char* kMeasureModeNames[N] = {"UNDEFINED", "EXACTLY", "AT_MOST"}; + const char* kLayoutModeNames[N] = { + "LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_MOST"}; - if (mode >= YGMeasureModeCount) { + if (mode >= N) { return ""; } From 34673088749ce252afd392f0ed1eb60246aed945 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Thu, 10 Jan 2019 19:57:40 -0800 Subject: [PATCH 159/189] Reformat xplat build files according to new formatting rules. Summary: drop-conflicts Reviewed By: zertosh Differential Revision: D13610808 fbshipit-source-id: 52c2a90bba3d9b0ac383f6e4a76b4fb3e60bf382 --- android/sample/BUCK | 2 +- csharp/BUCK | 2 +- lib/appcompat/BUCK | 2 +- lib/soloader/BUCK | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/sample/BUCK b/android/sample/BUCK index 7a408bb9..0989fcd6 100644 --- a/android/sample/BUCK +++ b/android/sample/BUCK @@ -4,8 +4,8 @@ # This source code is licensed under the license found in the # LICENSE-examples file in the root directory of this source tree. -load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource") load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load("//tools/build_defs/oss:yoga_defs.bzl", "ANDROID_RES_TARGET", "ANDROID_SAMPLE_JAVA_TARGET", "ANDROID_SAMPLE_RES_TARGET", "yoga_android_binary", "yoga_android_resource") yoga_android_binary( name = "sample", diff --git a/csharp/BUCK b/csharp/BUCK index 0df9bea4..81b570e5 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -3,6 +3,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:fb_native_wrapper.bzl", "fb_native") load( "//tools/build_defs/oss:yoga_defs.bzl", "BASE_COMPILER_FLAGS", @@ -10,7 +11,6 @@ load( "yoga_cxx_library", "yoga_dep", ) -load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"] diff --git a/lib/appcompat/BUCK b/lib/appcompat/BUCK index 670c5f20..b3262494 100644 --- a/lib/appcompat/BUCK +++ b/lib/appcompat/BUCK @@ -3,8 +3,8 @@ # 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") load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") fb_native.android_prebuilt_aar( name = "appcompat", diff --git a/lib/soloader/BUCK b/lib/soloader/BUCK index 5f3cc331..04e2f5ff 100644 --- a/lib/soloader/BUCK +++ b/lib/soloader/BUCK @@ -3,8 +3,8 @@ # 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") load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load("//tools/build_defs/oss:yoga_defs.bzl", "YOGA_ROOTS") fb_native.android_prebuilt_aar( name = "soloader", From 866bf101b2fe029bb4665a8b431d08e47ba027ce Mon Sep 17 00:00:00 2001 From: Amir Shalem Date: Thu, 10 Jan 2019 23:48:36 -0800 Subject: [PATCH 160/189] Revert D13597449: [Yoga][cleanup] Remove enum count macros Differential Revision: D13597449 Original commit changeset: edcee225ada4 fbshipit-source-id: 1afc24833c8657a8a198bc4529d98c8f605b7fbd --- yoga/YGConfig.h | 3 +- yoga/YGEnums.h | 99 ++++++++++++++------------------------------ yoga/YGNode.cpp | 3 +- yoga/YGNodePrint.cpp | 7 ++-- yoga/YGStyle.h | 4 +- yoga/Yoga-internal.h | 3 +- yoga/Yoga.cpp | 14 ++++--- 7 files changed, 47 insertions(+), 86 deletions(-) diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index 00415ce9..c9b871fe 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -10,8 +10,7 @@ #include "Yoga.h" struct YGConfig { - std::array()> - experimentalFeatures = {}; + std::array experimentalFeatures = {}; bool useWebDefaults = false; bool useLegacyStretchBehaviour = false; bool shouldDiffLayoutWithoutLegacyStretchBehaviour = false; diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index ea4e1882..00be5044 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -8,52 +8,14 @@ #include "YGMacros.h" -#ifdef __cplusplus -namespace facebook { -namespace yoga { -namespace enums { - -template -constexpr int count() = delete; - -namespace detail { -template -constexpr int n() { - return sizeof...(xs); -} -} // namespace detail - -} // namespace enums -} // namespace yoga -} // namespace facebook -#endif - #define YG_ENUM_DECL(NAME, ...) \ typedef YG_ENUM_BEGIN(NAME){__VA_ARGS__} YG_ENUM_END(NAME); \ WIN_EXPORT const char* NAME##ToString(NAME); -#ifdef __cplusplus -#define YG_ENUM_SEQ_DECL(NAME, ...) \ - YG_ENUM_DECL(NAME, __VA_ARGS__) \ - YG_EXTERN_C_END \ - namespace facebook { \ - namespace yoga { \ - namespace enums { \ - template <> \ - constexpr int count() { \ - return detail::n<__VA_ARGS__>(); \ - } \ - } \ - } \ - } \ - YG_EXTERN_C_BEGIN -#else -#define YG_ENUM_SEQ_DECL YG_ENUM_DECL -#endif - YG_EXTERN_C_BEGIN -YG_ENUM_SEQ_DECL( +#define YGAlignCount 8 +YG_ENUM_DECL( YGAlign, YGAlignAuto, YGAlignFlexStart, @@ -64,17 +26,17 @@ YG_ENUM_SEQ_DECL( YGAlignSpaceBetween, YGAlignSpaceAround); -YG_ENUM_SEQ_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) +#define YGDimensionCount 2 +YG_ENUM_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) -YG_ENUM_SEQ_DECL( - YGDirection, - YGDirectionInherit, - YGDirectionLTR, - YGDirectionRTL) +#define YGDirectionCount 3 +YG_ENUM_DECL(YGDirection, YGDirectionInherit, YGDirectionLTR, YGDirectionRTL) -YG_ENUM_SEQ_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) +#define YGDisplayCount 2 +YG_ENUM_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) -YG_ENUM_SEQ_DECL( +#define YGEdgeCount 9 +YG_ENUM_DECL( YGEdge, YGEdgeLeft, YGEdgeTop, @@ -86,16 +48,19 @@ YG_ENUM_SEQ_DECL( YGEdgeVertical, YGEdgeAll) -YG_ENUM_SEQ_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) +#define YGExperimentalFeatureCount 1 +YG_ENUM_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) -YG_ENUM_SEQ_DECL( +#define YGFlexDirectionCount 4 +YG_ENUM_DECL( YGFlexDirection, YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, YGFlexDirectionRowReverse) -YG_ENUM_SEQ_DECL( +#define YGJustifyCount 6 +YG_ENUM_DECL( YGJustify, YGJustifyFlexStart, YGJustifyCenter, @@ -104,7 +69,8 @@ YG_ENUM_SEQ_DECL( YGJustifySpaceAround, YGJustifySpaceEvenly) -YG_ENUM_SEQ_DECL( +#define YGLogLevelCount 6 +YG_ENUM_DECL( YGLogLevel, YGLogLevelError, YGLogLevelWarn, @@ -113,38 +79,35 @@ YG_ENUM_SEQ_DECL( YGLogLevelVerbose, YGLogLevelFatal) -YG_ENUM_SEQ_DECL( +#define YGMeasureModeCount 3 +YG_ENUM_DECL( YGMeasureMode, YGMeasureModeUndefined, YGMeasureModeExactly, YGMeasureModeAtMost) -YG_ENUM_SEQ_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) +#define YGNodeTypeCount 2 +YG_ENUM_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) -YG_ENUM_SEQ_DECL( - YGOverflow, - YGOverflowVisible, - YGOverflowHidden, - YGOverflowScroll) +#define YGOverflowCount 3 +YG_ENUM_DECL(YGOverflow, YGOverflowVisible, YGOverflowHidden, YGOverflowScroll) -YG_ENUM_SEQ_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) +#define YGPositionTypeCount 2 +YG_ENUM_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) +#define YGPrintOptionsCount 3 YG_ENUM_DECL( YGPrintOptions, YGPrintOptionsLayout = 1, YGPrintOptionsStyle = 2, YGPrintOptionsChildren = 4) -YG_ENUM_SEQ_DECL( - YGUnit, - YGUnitUndefined, - YGUnitPoint, - YGUnitPercent, - YGUnitAuto) +#define YGUnitCount 4 +YG_ENUM_DECL(YGUnit, YGUnitUndefined, YGUnitPoint, YGUnitPercent, YGUnitAuto) -YG_ENUM_SEQ_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) +#define YGWrapCount 3 +YG_ENUM_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) YG_EXTERN_C_END #undef YG_ENUM_DECL -#undef YG_ENUM_SEQ_DECL diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 255db920..022e6067 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -313,8 +313,7 @@ YGValue YGNode::resolveFlexBasisPtr() const { } void YGNode::resolveDimension() { - using namespace yoga; - for (int dim = YGDimensionWidth; dim < enums::count(); dim++) { + for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) { if (!getStyle().maxDimensions[dim].isUndefined() && YGValueEqual( getStyle().maxDimensions[dim], style_.minDimensions[dim])) { diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 4e02deee..1c0c2708 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -20,7 +20,8 @@ static void indent(string& base, uint32_t level) { } } -static bool areFourValuesEqual(const YGStyle::Edges& four) { +static bool areFourValuesEqual( + const facebook::yoga::detail::Values& four) { return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) && YGValueEqual(four[0], four[3]); } @@ -85,7 +86,7 @@ static void appendNumberIfNotZero( static void appendEdges( string& base, const string& key, - const YGStyle::Edges& edges) { + const facebook::yoga::detail::Values& edges) { if (areFourValuesEqual(edges)) { appendNumberIfNotZero(base, key, edges[YGEdgeLeft]); } else { @@ -99,7 +100,7 @@ static void appendEdges( static void appendEdgeIfNotUndefined( string& base, const string& str, - const YGStyle::Edges& edges, + const facebook::yoga::detail::Values& edges, const YGEdge edge) { appendNumberIfNotUndefined( base, diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index e540635d..9193c69d 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -9,7 +9,6 @@ #include #include #include "CompactValue.h" -#include "YGEnums.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -30,8 +29,7 @@ private: public: using Dimensions = facebook::yoga::detail::Values<2>; - using Edges = - facebook::yoga::detail::Values()>; + using Edges = facebook::yoga::detail::Values; /* Some platforms don't support enum bitfields, so please use BITFIELD_ENUM_SIZED(BITS_COUNT) */ diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 1932cf1a..50d96dc2 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -149,7 +149,6 @@ static const float kWebDefaultFlexShrink = 1.0f; extern bool YGFloatsEqual(const float a, const float b); extern bool YGValueEqual(const YGValue a, const YGValue b); extern facebook::yoga::detail::CompactValue YGComputedEdgeValue( - const facebook::yoga::detail::Values< - facebook::yoga::enums::count()>& edges, + const facebook::yoga::detail::Values& edges, YGEdge edge, facebook::yoga::detail::CompactValue defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 0d11c7a3..fc9bb0da 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -105,7 +105,7 @@ bool YGFloatIsUndefined(const float value) { } detail::CompactValue YGComputedEdgeValue( - const YGStyle::Edges& edges, + const facebook::yoga::detail::Values& edges, YGEdge edge, detail::CompactValue defaultValue) { if (!edges[edge].isUndefined()) { @@ -3546,12 +3546,14 @@ static const char* YGSpacer(const unsigned long level) { static const char* YGMeasureModeName( const YGMeasureMode mode, const bool performLayout) { - constexpr auto N = enums::count(); - const char* kMeasureModeNames[N] = {"UNDEFINED", "EXACTLY", "AT_MOST"}; - const char* kLayoutModeNames[N] = { - "LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_MOST"}; + const char* kMeasureModeNames[YGMeasureModeCount] = { + "UNDEFINED", "EXACTLY", "AT_MOST"}; + const char* kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", + "LAY_EXACTLY", + "LAY_AT_" + "MOST"}; - if (mode >= N) { + if (mode >= YGMeasureModeCount) { return ""; } From 4840495d3f6ae80cee54fd5d061fb252187f3363 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 11 Jan 2019 03:09:11 -0800 Subject: [PATCH 161/189] Remove enum count macros Summary: @public Removes all `YG...Count` macros for enums and replaces them with `facebook::yoga::enums::count()`. This removes the need to manually maintain enum counts. Same as D13597449, working around a defect in clang < 3.9 Reviewed By: amir-shalem Differential Revision: D13634622 fbshipit-source-id: 344dc70e167b0caf746fe396cedd200f54e52219 --- yoga/YGConfig.h | 3 +- yoga/YGEnums.h | 99 ++++++++++++++++++++++++++++++-------------- yoga/YGNode.cpp | 3 +- yoga/YGNodePrint.cpp | 7 ++-- yoga/YGStyle.h | 4 +- yoga/Yoga-internal.h | 3 +- yoga/Yoga.cpp | 14 +++---- 7 files changed, 86 insertions(+), 47 deletions(-) diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h index c9b871fe..00415ce9 100644 --- a/yoga/YGConfig.h +++ b/yoga/YGConfig.h @@ -10,7 +10,8 @@ #include "Yoga.h" struct YGConfig { - std::array experimentalFeatures = {}; + std::array()> + experimentalFeatures = {}; bool useWebDefaults = false; bool useLegacyStretchBehaviour = false; bool shouldDiffLayoutWithoutLegacyStretchBehaviour = false; diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index 00be5044..f06b0e04 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -8,14 +8,52 @@ #include "YGMacros.h" +#ifdef __cplusplus +namespace facebook { +namespace yoga { +namespace enums { + +template +constexpr int count(); // can't use `= delete` due to a defect in clang < 3.9 + +namespace detail { +template +constexpr int n() { + return sizeof...(xs); +} +} // namespace detail + +} // namespace enums +} // namespace yoga +} // namespace facebook +#endif + #define YG_ENUM_DECL(NAME, ...) \ typedef YG_ENUM_BEGIN(NAME){__VA_ARGS__} YG_ENUM_END(NAME); \ WIN_EXPORT const char* NAME##ToString(NAME); +#ifdef __cplusplus +#define YG_ENUM_SEQ_DECL(NAME, ...) \ + YG_ENUM_DECL(NAME, __VA_ARGS__) \ + YG_EXTERN_C_END \ + namespace facebook { \ + namespace yoga { \ + namespace enums { \ + template <> \ + constexpr int count() { \ + return detail::n<__VA_ARGS__>(); \ + } \ + } \ + } \ + } \ + YG_EXTERN_C_BEGIN +#else +#define YG_ENUM_SEQ_DECL YG_ENUM_DECL +#endif + YG_EXTERN_C_BEGIN -#define YGAlignCount 8 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGAlign, YGAlignAuto, YGAlignFlexStart, @@ -26,17 +64,17 @@ YG_ENUM_DECL( YGAlignSpaceBetween, YGAlignSpaceAround); -#define YGDimensionCount 2 -YG_ENUM_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) +YG_ENUM_SEQ_DECL(YGDimension, YGDimensionWidth, YGDimensionHeight) -#define YGDirectionCount 3 -YG_ENUM_DECL(YGDirection, YGDirectionInherit, YGDirectionLTR, YGDirectionRTL) +YG_ENUM_SEQ_DECL( + YGDirection, + YGDirectionInherit, + YGDirectionLTR, + YGDirectionRTL) -#define YGDisplayCount 2 -YG_ENUM_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) +YG_ENUM_SEQ_DECL(YGDisplay, YGDisplayFlex, YGDisplayNone) -#define YGEdgeCount 9 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGEdge, YGEdgeLeft, YGEdgeTop, @@ -48,19 +86,16 @@ YG_ENUM_DECL( YGEdgeVertical, YGEdgeAll) -#define YGExperimentalFeatureCount 1 -YG_ENUM_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) +YG_ENUM_SEQ_DECL(YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis) -#define YGFlexDirectionCount 4 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGFlexDirection, YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, YGFlexDirectionRowReverse) -#define YGJustifyCount 6 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGJustify, YGJustifyFlexStart, YGJustifyCenter, @@ -69,8 +104,7 @@ YG_ENUM_DECL( YGJustifySpaceAround, YGJustifySpaceEvenly) -#define YGLogLevelCount 6 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGLogLevel, YGLogLevelError, YGLogLevelWarn, @@ -79,35 +113,38 @@ YG_ENUM_DECL( YGLogLevelVerbose, YGLogLevelFatal) -#define YGMeasureModeCount 3 -YG_ENUM_DECL( +YG_ENUM_SEQ_DECL( YGMeasureMode, YGMeasureModeUndefined, YGMeasureModeExactly, YGMeasureModeAtMost) -#define YGNodeTypeCount 2 -YG_ENUM_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) +YG_ENUM_SEQ_DECL(YGNodeType, YGNodeTypeDefault, YGNodeTypeText) -#define YGOverflowCount 3 -YG_ENUM_DECL(YGOverflow, YGOverflowVisible, YGOverflowHidden, YGOverflowScroll) +YG_ENUM_SEQ_DECL( + YGOverflow, + YGOverflowVisible, + YGOverflowHidden, + YGOverflowScroll) -#define YGPositionTypeCount 2 -YG_ENUM_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) +YG_ENUM_SEQ_DECL(YGPositionType, YGPositionTypeRelative, YGPositionTypeAbsolute) -#define YGPrintOptionsCount 3 YG_ENUM_DECL( YGPrintOptions, YGPrintOptionsLayout = 1, YGPrintOptionsStyle = 2, YGPrintOptionsChildren = 4) -#define YGUnitCount 4 -YG_ENUM_DECL(YGUnit, YGUnitUndefined, YGUnitPoint, YGUnitPercent, YGUnitAuto) +YG_ENUM_SEQ_DECL( + YGUnit, + YGUnitUndefined, + YGUnitPoint, + YGUnitPercent, + YGUnitAuto) -#define YGWrapCount 3 -YG_ENUM_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) +YG_ENUM_SEQ_DECL(YGWrap, YGWrapNoWrap, YGWrapWrap, YGWrapWrapReverse) YG_EXTERN_C_END #undef YG_ENUM_DECL +#undef YG_ENUM_SEQ_DECL diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 022e6067..255db920 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -313,7 +313,8 @@ YGValue YGNode::resolveFlexBasisPtr() const { } void YGNode::resolveDimension() { - for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) { + using namespace yoga; + for (int dim = YGDimensionWidth; dim < enums::count(); dim++) { if (!getStyle().maxDimensions[dim].isUndefined() && YGValueEqual( getStyle().maxDimensions[dim], style_.minDimensions[dim])) { diff --git a/yoga/YGNodePrint.cpp b/yoga/YGNodePrint.cpp index 1c0c2708..4e02deee 100644 --- a/yoga/YGNodePrint.cpp +++ b/yoga/YGNodePrint.cpp @@ -20,8 +20,7 @@ static void indent(string& base, uint32_t level) { } } -static bool areFourValuesEqual( - const facebook::yoga::detail::Values& four) { +static bool areFourValuesEqual(const YGStyle::Edges& four) { return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) && YGValueEqual(four[0], four[3]); } @@ -86,7 +85,7 @@ static void appendNumberIfNotZero( static void appendEdges( string& base, const string& key, - const facebook::yoga::detail::Values& edges) { + const YGStyle::Edges& edges) { if (areFourValuesEqual(edges)) { appendNumberIfNotZero(base, key, edges[YGEdgeLeft]); } else { @@ -100,7 +99,7 @@ static void appendEdges( static void appendEdgeIfNotUndefined( string& base, const string& str, - const facebook::yoga::detail::Values& edges, + const YGStyle::Edges& edges, const YGEdge edge) { appendNumberIfNotUndefined( base, diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index 9193c69d..e540635d 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -9,6 +9,7 @@ #include #include #include "CompactValue.h" +#include "YGEnums.h" #include "YGFloatOptional.h" #include "Yoga-internal.h" #include "Yoga.h" @@ -29,7 +30,8 @@ private: public: using Dimensions = facebook::yoga::detail::Values<2>; - using Edges = facebook::yoga::detail::Values; + using Edges = + facebook::yoga::detail::Values()>; /* Some platforms don't support enum bitfields, so please use BITFIELD_ENUM_SIZED(BITS_COUNT) */ diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 50d96dc2..1932cf1a 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -149,6 +149,7 @@ static const float kWebDefaultFlexShrink = 1.0f; extern bool YGFloatsEqual(const float a, const float b); extern bool YGValueEqual(const YGValue a, const YGValue b); extern facebook::yoga::detail::CompactValue YGComputedEdgeValue( - const facebook::yoga::detail::Values& edges, + const facebook::yoga::detail::Values< + facebook::yoga::enums::count()>& edges, YGEdge edge, facebook::yoga::detail::CompactValue defaultValue); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index fc9bb0da..0d11c7a3 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -105,7 +105,7 @@ bool YGFloatIsUndefined(const float value) { } detail::CompactValue YGComputedEdgeValue( - const facebook::yoga::detail::Values& edges, + const YGStyle::Edges& edges, YGEdge edge, detail::CompactValue defaultValue) { if (!edges[edge].isUndefined()) { @@ -3546,14 +3546,12 @@ static const char* YGSpacer(const unsigned long level) { static const char* YGMeasureModeName( const YGMeasureMode mode, const bool performLayout) { - const char* kMeasureModeNames[YGMeasureModeCount] = { - "UNDEFINED", "EXACTLY", "AT_MOST"}; - const char* kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", - "LAY_EXACTLY", - "LAY_AT_" - "MOST"}; + constexpr auto N = enums::count(); + const char* kMeasureModeNames[N] = {"UNDEFINED", "EXACTLY", "AT_MOST"}; + const char* kLayoutModeNames[N] = { + "LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_MOST"}; - if (mode >= YGMeasureModeCount) { + if (mode >= N) { return ""; } From 7fa0816d8144c8dfe79c7d5795ef028950bf3b58 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 16 Jan 2019 08:39:57 -0800 Subject: [PATCH 162/189] Fix URLs to CSS spec in comments Summary: @public These URLs probably have been changed when CSSLayout was renamed to Yoga by search & replacing Reviewed By: SidharthGuglani Differential Revision: D13690829 fbshipit-source-id: 44dbd8fe256fc286006d164390609a7c3de6c4e6 --- yoga/Yoga.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 0d11c7a3..0a049e6b 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2336,7 +2336,7 @@ static void YGDistributeFreeSpaceFirstPass( // // This two pass approach for resolving min/max constraints deviates from // the spec. The -// spec (https://www.w3.org/TR/YG-flexbox-1/#resolve-flexible-lengths) +// spec (https://www.w3.org/TR/CSS-flexbox-1/#resolve-flexible-lengths) // describes a process // that needs to be repeated a variable number of times. The algorithm // implemented here @@ -2609,7 +2609,7 @@ static void YGJustifyMainAxis( // // This is the main routine that implements a subset of the flexbox layout // algorithm -// described in the W3C YG documentation: https://www.w3.org/TR/YG3-flexbox/. +// described in the W3C YG documentation: https://www.w3.org/TR/CSS3-flexbox/. // // Limitations of this algorithm, compared to the full standard: // * Display property is always assumed to be 'flex' except for Text nodes, @@ -2682,7 +2682,7 @@ static void YGJustifyMainAxis( // support default // minimum main sizes (see above for details). Each of our measure modes maps // to a layout mode -// from the spec (https://www.w3.org/TR/YG3-sizing/#terms): +// from the spec (https://www.w3.org/TR/CSS3-sizing/#terms): // - YGMeasureModeUndefined: max content // - YGMeasureModeExactly: fill available // - YGMeasureModeAtMost: fit content From 71321f763a6142c4531684ada6a87954b12bd362 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 16 Jan 2019 08:39:58 -0800 Subject: [PATCH 163/189] Reflow comments Summary: @public Repeated application and alternation of Clang Format rules has lead to unfortunate block comment formatting. Here, we reflow comments Reviewed By: SidharthGuglani Differential Revision: D13677242 fbshipit-source-id: 3f1f5e38693eb15e9705f24fd363fc1618c78974 --- yoga/CompactValue.h | 4 +- yoga/Utils.h | 26 ++--- yoga/YGLayout.h | 4 +- yoga/YGMarker.h | 4 +- yoga/YGNode.cpp | 4 +- yoga/YGNode.h | 7 +- yoga/Yoga.cpp | 231 ++++++++++++++++++-------------------------- yoga/Yoga.h | 42 ++++---- 8 files changed, 140 insertions(+), 182 deletions(-) diff --git a/yoga/CompactValue.h b/yoga/CompactValue.h index 22b9624e..9c9a92e0 100644 --- a/yoga/CompactValue.h +++ b/yoga/CompactValue.h @@ -149,8 +149,8 @@ private: static constexpr uint32_t BIAS = 0x20000000; static constexpr uint32_t PERCENT_BIT = 0x40000000; - // these are signaling NaNs with specific bit pattern as payload - // they will be silenced whenever going through an FPU operation on ARM + x86 + // these are signaling NaNs with specific bit pattern as payload they will be + // silenced whenever going through an FPU operation on ARM + x86 static constexpr uint32_t AUTO_BITS = 0x7faaaaaa; static constexpr uint32_t ZERO_BITS_POINT = 0x7f8f0f0f; static constexpr uint32_t ZERO_BITS_PERCENT = 0x7f80f0f0; diff --git a/yoga/Utils.h b/yoga/Utils.h index 7e5a8636..a27b62a1 100644 --- a/yoga/Utils.h +++ b/yoga/Utils.h @@ -9,31 +9,31 @@ #include "Yoga-internal.h" #include "CompactValue.h" -// This struct is an helper model to hold the data for step 4 of flexbox -// algo, which is collecting the flex items in a line. +// This struct is an helper model to hold the data for step 4 of flexbox algo, +// which is collecting the flex items in a line. // // - itemsOnLine: Number of items which can fit in a line considering the -// available Inner dimension, the flex items computed flexbasis and their -// margin. It may be different than the difference between start and end -// indicates because we skip over absolute-positioned items. +// available Inner dimension, the flex items computed flexbasis and their +// margin. It may be different than the difference between start and end +// indicates because we skip over absolute-positioned items. // // - sizeConsumedOnCurrentLine: It is accumulation of the dimensions and margin -// of all the children on the current line. This will be used in order to either -// set the dimensions of the node if none already exist or to compute the -// remaining space left for the flexible children. +// of all the children on the current line. This will be used in order to +// either set the dimensions of the node if none already exist or to compute +// the remaining space left for the flexible children. // // - totalFlexGrowFactors: total flex grow factors of flex items which are to be -// layed in the current line +// layed in the current line // // - totalFlexShrinkFactors: total flex shrink factors of flex items which are -// to be layed in the current line +// to be layed in the current line // // - endOfLineIndex: Its the end index of the last flex item which was examined -// and it may or may not be part of the current line(as it may be absolutely -// positioned or inculding it may have caused to overshoot availableInnerDim) +// and it may or may not be part of the current line(as it may be absolutely +// positioned or inculding it may have caused to overshoot availableInnerDim) // // - relativeChildren: Maintain a vector of the child nodes that can shrink -// and/or grow. +// and/or grow. struct YGCollectFlexItemsRowValues { uint32_t itemsOnLine; diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 4a68d86a..4daa28ed 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -25,8 +25,8 @@ struct YGLayout { uint32_t computedFlexBasisGeneration = 0; YGFloatOptional computedFlexBasis = {}; - // Instead of recomputing the entire layout every single time, we - // cache some information to break early when nothing changed + // Instead of recomputing the entire layout every single time, we cache some + // information to break early when nothing changed uint32_t generationCount = 0; YGDirection lastOwnerDirection = (YGDirection) -1; diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 3eb665fe..d4f4de64 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -23,8 +23,8 @@ typedef struct { // accepts marker type, a node ref, and marker data (depends on marker type) // can return a handle or id that Yoga will pass to endMarker void* (*startMarker)(YGMarkerType, YGNodeRef, YGMarkerData); - // accepts marker type, a node ref, marker data, and marker id as returned - // by startMarker + // accepts marker type, a node ref, marker data, and marker id as returned by + // startMarker void (*endMarker)(YGMarkerType, YGNodeRef, YGMarkerData, void* id); } YGMarkerCallbacks; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 255db920..0b7fc3c7 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -206,8 +206,8 @@ void YGNode::setLayoutDimension(float dimension, int index) { layout_.dimensions[index] = dimension; } -// If both left and right are defined, then use left. Otherwise return -// +left or -right depending on which is defined. +// If both left and right are defined, then use left. Otherwise return +left or +// -right depending on which is defined. YGFloatOptional YGNode::relativePosition( const YGFlexDirection axis, const float axisSize) const { diff --git a/yoga/YGNode.h b/yoga/YGNode.h index db1e7d42..ffb01832 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -102,10 +102,9 @@ public: } // returns the YGNodeRef that owns this YGNode. An owner is used to identify - // the YogaTree that a YGNode belongs to. - // This method will return the parent of the YGNode when a YGNode only belongs - // to one YogaTree or nullptr when the YGNode is shared between two or more - // YogaTrees. + // the YogaTree that a YGNode belongs to. This method will return the parent + // of the YGNode when a YGNode only belongs to one YogaTree or nullptr when + // the YGNode is shared between two or more YogaTrees. YGNodeRef getOwner() const { return owner_; } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 0a049e6b..38287e76 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1322,8 +1322,8 @@ static void YGNodeComputeFlexBasisForChild( child->getResolvedDimension(YGDimensionHeight), ownerHeight), paddingAndBorder)); } else { - // Compute the flex basis and hypothetical main size (i.e. the clamped - // flex basis). + // Compute the flex basis and hypothetical main size (i.e. the clamped flex + // basis). childWidth = YGUndefined; childHeight = YGUndefined; childWidthMeasureMode = YGMeasureModeUndefined; @@ -1351,8 +1351,8 @@ static void YGNodeComputeFlexBasisForChild( childHeightMeasureMode = YGMeasureModeExactly; } - // The W3C spec doesn't say anything about the 'overflow' property, - // but all major browsers appear to implement the following logic. + // The W3C spec doesn't say anything about the 'overflow' property, but all + // major browsers appear to implement the following logic. if ((!isMainAxisRow && node->getStyle().overflow == YGOverflowScroll) || node->getStyle().overflow != YGOverflowScroll) { if (YGFloatIsUndefined(childWidth) && !YGFloatIsUndefined(width)) { @@ -1383,9 +1383,8 @@ static void YGNodeComputeFlexBasisForChild( } } - // If child has no defined size in the cross axis and is set to stretch, - // set the cross - // axis to be measured exactly with the available inner width + // If child has no defined size in the cross axis and is set to stretch, set + // the cross axis to be measured exactly with the available inner width const bool hasExactWidth = !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly; @@ -1484,9 +1483,8 @@ static void YGNodeAbsoluteLayoutChild( .unwrap() + marginRow; } else { - // If the child doesn't have a specified width, compute the width based - // on the left/right - // offsets if they're defined. + // If the child doesn't have a specified width, compute the width based on + // the left/right offsets if they're defined. if (child->isLeadingPositionDefined(YGFlexDirectionRow) && child->isTrailingPosDefined(YGFlexDirectionRow)) { childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] - @@ -1506,9 +1504,8 @@ static void YGNodeAbsoluteLayoutChild( .unwrap() + marginColumn; } else { - // If the child doesn't have a specified height, compute the height - // based on the top/bottom - // offsets if they're defined. + // If the child doesn't have a specified height, compute the height based on + // the top/bottom offsets if they're defined. if (child->isLeadingPositionDefined(YGFlexDirectionColumn) && child->isTrailingPosDefined(YGFlexDirectionColumn)) { childHeight = node->getLayout().measuredDimensions[YGDimensionHeight] - @@ -1961,8 +1958,8 @@ static float YGNodeComputeFlexBasisForChildren( // This function assumes that all the children of node have their // computedFlexBasis properly computed(To do this use -// YGNodeComputeFlexBasisForChildren function). -// This function calculates YGCollectFlexItemsRowMeasurement +// YGNodeComputeFlexBasisForChildren function). This function calculates +// YGCollectFlexItemsRowMeasurement static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( const YGNodeRef& node, const YGDirection ownerDirection, @@ -1998,10 +1995,9 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( mainAxisownerSize) .unwrap(); - // If this is a multi-line flow and this item pushes us over the - // available size, we've - // hit the end of the current line. Break out of the loop and lay out - // the current line. + // If this is a multi-line flow and this item pushes us over the available + // size, we've hit the end of the current line. Break out of the loop and + // lay out the current line. if (sizeConsumedOnCurrentLineIncludingMinConstraint + flexBasisWithMinAndMaxConstraints + childMarginMainAxis > availableInnerMainDim && @@ -2276,12 +2272,10 @@ static void YGDistributeFreeSpaceFirstPass( if (!YGFloatIsUndefined(baseMainSize) && !YGFloatIsUndefined(boundMainSize) && baseMainSize != boundMainSize) { - // By excluding this item's size and flex factor from remaining, - // this item's - // min/max constraints should also trigger in the second pass - // resulting in the - // item's size calculation being identical in the first and second - // passes. + // By excluding this item's size and flex factor from remaining, this + // item's min/max constraints should also trigger in the second pass + // resulting in the item's size calculation being identical in the + // first and second passes. deltaFreeSpace += boundMainSize - childFlexBasis; collectedFlexItemsValues.totalFlexShrinkScaledFactors -= flexShrinkScaledFactor; @@ -2307,12 +2301,10 @@ static void YGDistributeFreeSpaceFirstPass( if (!YGFloatIsUndefined(baseMainSize) && !YGFloatIsUndefined(boundMainSize) && baseMainSize != boundMainSize) { - // By excluding this item's size and flex factor from remaining, - // this item's - // min/max constraints should also trigger in the second pass - // resulting in the - // item's size calculation being identical in the first and second - // passes. + // By excluding this item's size and flex factor from remaining, this + // item's min/max constraints should also trigger in the second pass + // resulting in the item's size calculation being identical in the + // first and second passes. deltaFreeSpace += boundMainSize - childFlexBasis; collectedFlexItemsValues.totalFlexGrowFactors -= flexGrowFactor; } @@ -2324,25 +2316,22 @@ static void YGDistributeFreeSpaceFirstPass( // Do two passes over the flex items to figure out how to distribute the // remaining space. -// The first pass finds the items whose min/max constraints trigger, -// freezes them at those -// sizes, and excludes those sizes from the remaining space. The second -// pass sets the size -// of each flexible item. It distributes the remaining space amongst the -// items whose min/max -// constraints didn't trigger in pass 1. For the other items, it sets -// their sizes by forcing -// their min/max constraints to trigger again. // -// This two pass approach for resolving min/max constraints deviates from -// the spec. The -// spec (https://www.w3.org/TR/CSS-flexbox-1/#resolve-flexible-lengths) -// describes a process -// that needs to be repeated a variable number of times. The algorithm -// implemented here -// won't handle all cases but it was simpler to implement and it mitigates -// performance -// concerns because we know exactly how many passes it'll do. +// The first pass finds the items whose min/max constraints trigger, freezes +// them at those sizes, and excludes those sizes from the remaining space. +// +// The second pass sets the size of each flexible item. It distributes the +// remaining space amongst the items whose min/max constraints didn't trigger in +// the first pass. For the other items, it sets their sizes by forcing their +// min/max constraints to trigger again. +// +// This two pass approach for resolving min/max constraints deviates from the +// spec. The spec +// (https://www.w3.org/TR/CSS-flexbox-1/#resolve-flexible-lengths) describes a +// process that needs to be repeated a variable number of times. The algorithm +// implemented here won't handle all cases but it was simpler to implement and +// it mitigates performance concerns because we know exactly how many passes +// it'll do. // // At the end of this function the child nodes would have the proper size // assigned to them. @@ -2451,9 +2440,9 @@ static void YGJustifyMainAxis( } } - // In order to position the elements in the main axis, we have two - // controls. The space between the beginning and the first element - // and the space between each two elements. + // In order to position the elements in the main axis, we have two controls. + // The space between the beginning and the first element and the space between + // each two elements. float leadingMainDim = 0; float betweenMainDim = 0; const YGJustify justifyContent = node->getStyle().justifyContent; @@ -2512,8 +2501,8 @@ static void YGJustifyMainAxis( child->isLeadingPositionDefined(mainAxis)) { if (performLayout) { // In case the child is position absolute and has left/top being - // defined, we override the position to whatever the user said - // (and margin/border). + // defined, we override the position to whatever the user said (and + // margin/border). child->setLayoutPosition( child->getLeadingPosition(mainAxis, availableInnerMainDim) .unwrap() + @@ -2523,8 +2512,8 @@ static void YGJustifyMainAxis( } } else { // Now that we placed the element, we need to update the variables. - // We need to do that only for relative elements. Absolute elements - // do not take part in that phase. + // We need to do that only for relative elements. Absolute elements do not + // take part in that phase. if (childStyle.positionType == YGPositionTypeRelative) { if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) { collectedFlexItemsValues.mainDim += @@ -2547,9 +2536,8 @@ static void YGJustifyMainAxis( bool canSkipFlex = !performLayout && measureModeCrossDim == YGMeasureModeExactly; if (canSkipFlex) { - // If we skipped the flex step, then we can't rely on the - // measuredDims because - // they weren't computed. This means we can't call + // If we skipped the flex step, then we can't rely on the measuredDims + // because they weren't computed. This means we can't call // YGNodeDimWithMargin. collectedFlexItemsValues.mainDim += betweenMainDim + child->getMarginForAxis(mainAxis, availableInnerWidth).unwrap() + @@ -2608,81 +2596,61 @@ static void YGJustifyMainAxis( // // This is the main routine that implements a subset of the flexbox layout -// algorithm -// described in the W3C YG documentation: https://www.w3.org/TR/CSS3-flexbox/. +// algorithm described in the W3C CSS documentation: +// https://www.w3.org/TR/CSS3-flexbox/. // // Limitations of this algorithm, compared to the full standard: // * Display property is always assumed to be 'flex' except for Text nodes, -// which -// are assumed to be 'inline-flex'. +// which are assumed to be 'inline-flex'. // * The 'zIndex' property (or any form of z ordering) is not supported. Nodes -// are -// stacked in document order. +// are stacked in document order. // * The 'order' property is not supported. The order of flex items is always -// defined -// by document order. +// defined by document order. // * The 'visibility' property is always assumed to be 'visible'. Values of -// 'collapse' -// and 'hidden' are not supported. +// 'collapse' and 'hidden' are not supported. // * There is no support for forced breaks. // * It does not support vertical inline directions (top-to-bottom or -// bottom-to-top text). +// bottom-to-top text). // // Deviations from standard: // * Section 4.5 of the spec indicates that all flex items have a default -// minimum -// main size. For text blocks, for example, this is the width of the widest -// word. -// Calculating the minimum width is expensive, so we forego it and assume a -// default -// minimum main size of 0. +// minimum main size. For text blocks, for example, this is the width of the +// widest word. Calculating the minimum width is expensive, so we forego it +// and assume a default minimum main size of 0. // * Min/Max sizes in the main axis are not honored when resolving flexible -// lengths. +// lengths. // * The spec indicates that the default value for 'flexDirection' is 'row', -// but -// the algorithm below assumes a default of 'column'. +// but the algorithm below assumes a default of 'column'. // // Input parameters: // - node: current node to be sized and layed out // - availableWidth & availableHeight: available size to be used for sizing -// the node -// or YGUndefined if the size is not available; interpretation depends on -// layout -// flags +// the node or YGUndefined if the size is not available; interpretation +// depends on layout flags // - ownerDirection: the inline (text) direction within the owner -// (left-to-right or -// right-to-left) +// (left-to-right or right-to-left) // - widthMeasureMode: indicates the sizing rules for the width (see below -// for explanation) +// for explanation) // - heightMeasureMode: indicates the sizing rules for the height (see below -// for explanation) +// for explanation) // - performLayout: specifies whether the caller is interested in just the -// dimensions -// of the node or it requires the entire node and its subtree to be layed -// out -// (with final positions) +// dimensions of the node or it requires the entire node and its subtree to +// be layed out (with final positions) // // Details: // This routine is called recursively to lay out subtrees of flexbox -// elements. It uses the -// information in node.style, which is treated as a read-only input. It is -// responsible for -// setting the layout.direction and layout.measuredDimensions fields for the -// input node as well -// as the layout.position and layout.lineIndex fields for its child nodes. -// The +// elements. It uses the information in node.style, which is treated as a +// read-only input. It is responsible for setting the layout.direction and +// layout.measuredDimensions fields for the input node as well as the +// layout.position and layout.lineIndex fields for its child nodes. The // layout.measuredDimensions field includes any border or padding for the -// node but does -// not include margins. +// node but does not include margins. // // The spec describes four different layout modes: "fill available", "max -// content", "min -// content", -// and "fit content". Of these, we don't use "min content" because we don't -// support default -// minimum main sizes (see above for details). Each of our measure modes maps -// to a layout mode -// from the spec (https://www.w3.org/TR/CSS3-sizing/#terms): +// content", "min content", and "fit content". Of these, we don't use "min +// content" because we don't support default minimum main sizes (see above +// for details). Each of our measure modes maps to a layout mode from the +// spec (https://www.w3.org/TR/CSS3-sizing/#terms): // - YGMeasureModeUndefined: max content // - YGMeasureModeExactly: fill available // - YGMeasureModeAtMost: fit content @@ -2924,9 +2892,9 @@ static void YGNodelayoutImpl( !performLayout && measureModeCrossDim == YGMeasureModeExactly; // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS - // Calculate the remaining available space that needs to be allocated. - // If the main dimension size isn't known, it is computed based on - // the line length, so there's no more space left to distribute. + // Calculate the remaining available space that needs to be allocated. If + // the main dimension size isn't known, it is computed based on the line + // length, so there's no more space left to distribute. bool sizeBasedOnContent = false; // If we don't measure with exact main dimension we want to ensure we don't @@ -2998,11 +2966,9 @@ static void YGNodelayoutImpl( // STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION // At this point, all the children have their dimensions set in the main - // axis. - // Their dimensions are also set in the cross axis with the exception of - // items - // that are aligned "stretch". We need to compute these stretch values and - // set the final positions. + // axis. Their dimensions are also set in the cross axis with the exception + // of items that are aligned "stretch". We need to compute these stretch + // values and set the final positions. YGJustifyMainAxis( node, @@ -3058,8 +3024,8 @@ static void YGNodelayoutImpl( } if (child->getStyle().positionType == YGPositionTypeAbsolute) { // If the child is absolutely positioned and has a - // top/left/bottom/right set, override - // all the previously computed positions to set it correctly. + // top/left/bottom/right set, override all the previously computed + // positions to set it correctly. const bool isChildLeadingPosDefined = child->isLeadingPositionDefined(crossAxis); if (isChildLeadingPosDefined) { @@ -3090,9 +3056,8 @@ static void YGNodelayoutImpl( const YGAlign alignItem = YGNodeAlignItem(node, child); // If the child uses align stretch, we need to lay it out one more - // time, this time - // forcing the cross-axis size to be the computed cross size for the - // current line. + // time, this time forcing the cross-axis size to be the computed + // cross size for the current line. if (alignItem == YGAlignStretch && child->marginLeadingValue(crossAxis).unit != YGUnitAuto && child->marginTrailingValue(crossAxis).unit != YGUnitAuto) { @@ -3713,8 +3678,8 @@ bool YGNodeCanUseCachedMeasurement( } // -// This is a wrapper around the YGNodelayoutImpl function. It determines -// whether the layout request is redundant and can be skipped. +// This is a wrapper around the YGNodelayoutImpl function. It determines whether +// the layout request is redundant and can be skipped. // // Parameters: // Input parameters are the same as YGNodelayoutImpl (see above) @@ -3753,16 +3718,12 @@ bool YGLayoutNodeInternal( // Determine whether the results are already cached. We maintain a separate // cache for layouts and measurements. A layout operation modifies the - // positions - // and dimensions for nodes in the subtree. The algorithm assumes that each - // node - // gets layed out a maximum of one time per tree layout, but multiple - // measurements - // may be required to resolve all of the flex dimensions. - // We handle nodes with measure functions specially here because they are the - // most - // expensive to measure, so it's worth avoiding redundant measurements if at - // all possible. + // positions and dimensions for nodes in the subtree. The algorithm assumes + // that each node gets layed out a maximum of one time per tree layout, but + // multiple measurements may be required to resolve all of the flex + // dimensions. We handle nodes with measure functions specially here because + // they are the most expensive to measure, so it's worth avoiding redundant + // measurements if at all possible. if (node->getMeasure() != nullptr) { const float marginAxisRow = node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); @@ -4058,10 +4019,8 @@ void YGNodeCalculateLayout( const float ownerHeight, const YGDirection ownerDirection) { // Increment the generation count. This will force the recursive routine to - // visit - // all dirty nodes at least once. Subsequent visits will be skipped if the - // input - // parameters don't change. + // visit all dirty nodes at least once. Subsequent visits will be skipped if + // the input parameters don't change. gCurrentGenerationCount++; node->resolveDimension(); float width = YGUndefined; diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 0c45cbe1..afb4c9be 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -104,16 +104,16 @@ WIN_EXPORT void YGNodeCalculateLayout( // Mark a node as dirty. Only valid for nodes with a custom measure function // set. -// YG knows when to mark all other nodes as dirty but because nodes with -// measure functions -// depends on information not known to YG they must perform this dirty -// marking manually. +// +// Yoga knows when to mark all other nodes as dirty but because nodes with +// measure functions depend on information not known to Yoga they must perform +// this dirty marking manually. WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node); -// This function marks the current node and all its descendants as dirty. This -// function is added to test yoga benchmarks. This function is not expected to -// be used in production as calling `YGCalculateLayout` will cause the -// recalculation of each and every node. +// Marks the current node and all its descendants as dirty. +// +// Intended to be used for Uoga benchmarks. Don't use in production, as calling +// `YGCalculateLayout` will cause the recalculation of each and every node. WIN_EXPORT void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node); WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options); @@ -317,20 +317,20 @@ WIN_EXPORT void YGNodeStyleSetMaxHeightPercent( const float maxHeight); WIN_EXPORT YGValue YGNodeStyleGetMaxHeight(const YGNodeRef node); -// Yoga specific properties, not compatible with flexbox specification -// Aspect ratio control the size of the undefined dimension of a node. -// Aspect ratio is encoded as a floating point value width/height. e.g. A value -// of 2 leads to a node with a width twice the size of its height while a value -// of 0.5 gives the opposite effect. +// Yoga specific properties, not compatible with flexbox specification Aspect +// ratio control the size of the undefined dimension of a node. Aspect ratio is +// encoded as a floating point value width/height. e.g. A value of 2 leads to a +// node with a width twice the size of its height while a value of 0.5 gives the +// opposite effect. // // - On a node with a set width/height aspect ratio control the size of the -// unset dimension +// unset dimension // - On a node with a set flex basis aspect ratio controls the size of the node -// in the cross axis if unset +// in the cross axis if unset // - On a node with a measure function aspect ratio works as though the measure -// function measures the flex basis +// function measures the flex basis // - On a node with flex grow/shrink aspect ratio controls the size of the node -// in the cross axis if unset +// in the cross axis if unset // - Aspect ratio takes min/max dimensions into account WIN_EXPORT void YGNodeStyleSetAspectRatio( const YGNodeRef node, @@ -377,8 +377,8 @@ WIN_EXPORT void YGAssertWithConfig( const YGConfigRef config, const bool condition, const char* message); -// Set this to number of pixels in 1 point to round calculation results -// If you want to avoid rounding - set PointScaleFactor to 0 +// Set this to number of pixels in 1 point to round calculation results If you +// want to avoid rounding - set PointScaleFactor to 0 WIN_EXPORT void YGConfigSetPointScaleFactor( const YGConfigRef config, const float pixelsInPoint); @@ -409,8 +409,8 @@ WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled( const YGConfigRef config, const YGExperimentalFeature feature); -// Using the web defaults is the prefered configuration for new projects. -// Usage of non web defaults should be considered as legacy. +// Using the web defaults is the prefered configuration for new projects. Usage +// of non web defaults should be considered as legacy. WIN_EXPORT void YGConfigSetUseWebDefaults( const YGConfigRef config, const bool enabled); From 604a9a98a972ae11590e0de4e3e9faac385302fd Mon Sep 17 00:00:00 2001 From: Eduardo Roman Date: Wed, 16 Jan 2019 11:53:04 -0800 Subject: [PATCH 164/189] guard against INF values in CompactValue Summary: After this diff D13403925 that got rid of `-ffast-math` we started to have a very odd behavior on Yoga when using release builds. After digging a while we found that certain set of conditions on O2 and O3 optimization levels was causing Origami to set some `INFINITE` values on Yoga. We found the root of the problem and fix it on Origami side. But I'm wondering if guarding agains `INFINITE` on Yoga side would be good too. Since now Yoga it's not using `-ffast-math` anymore, and I think infinite is not a a valid value anywhere on Yoga side, it seems to support the reason to guard against it. I'm happy to abandon this diff if you guys think this is not a good solution. Reviewed By: davidaurelio Differential Revision: D13679319 fbshipit-source-id: 061448fea9d1a8496362ff07dc46b546e7f1ffa3 --- tests/CompactValueTest.cpp | 12 ++++++++++++ yoga/CompactValue.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/CompactValueTest.cpp b/tests/CompactValueTest.cpp index 7d2afc13..d0a2c669 100644 --- a/tests/CompactValueTest.cpp +++ b/tests/CompactValueTest.cpp @@ -29,6 +29,18 @@ TEST(YogaTest, compact_value_can_represent_undefined) { ASSERT_FALSE(c.isAuto()); } +TEST(YogaTest, compact_value_manages_infinity_as_undefined) { + auto c = CompactValue{ + YGValue{std::numeric_limits::infinity(), YGUnitUndefined}}; + YGValue v = c; + ASSERT_EQ(v, YGValueUndefined); + ASSERT_NE(v, YGValueAuto); + ASSERT_NE(v, (YGValue{-1.25, YGUnitPoint})); + ASSERT_NE(v, (YGValue{25, YGUnitPercent})); + ASSERT_TRUE(c.isUndefined()); + ASSERT_FALSE(c.isAuto()); +} + TEST(YogaTest, compact_value_can_represent_auto) { auto c = CompactValue{YGValue{0, YGUnitAuto}}; YGValue v = c; diff --git a/yoga/CompactValue.h b/yoga/CompactValue.h index 9c9a92e0..3cc36a48 100644 --- a/yoga/CompactValue.h +++ b/yoga/CompactValue.h @@ -70,7 +70,8 @@ public: template static CompactValue ofMaybe(float value) noexcept { - return std::isnan(value) ? ofUndefined() : of(value); + return std::isnan(value) || std::isinf(value) ? ofUndefined() + : of(value); } static constexpr CompactValue ofZero() noexcept { From 8b8932811e3306c5ed35e566135893ffc72e2617 Mon Sep 17 00:00:00 2001 From: Amir Shalem Date: Thu, 17 Jan 2019 07:33:24 -0800 Subject: [PATCH 165/189] Make Yoga's libfb code to be gcc7 compatible Summary: Make the libfb jni code to be compatible with gcc7 compiler Reviewed By: davidaurelio Differential Revision: D13711390 fbshipit-source-id: 9a378a3ee4feb7e928dd97dae7d79a41f0658992 --- lib/fb/src/main/cpp/jni/Exceptions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fb/src/main/cpp/jni/Exceptions.cpp b/lib/fb/src/main/cpp/jni/Exceptions.cpp index 8688dfbf..73166c04 100644 --- a/lib/fb/src/main/cpp/jni/Exceptions.cpp +++ b/lib/fb/src/main/cpp/jni/Exceptions.cpp @@ -219,11 +219,11 @@ void translatePendingCppExceptionToJavaException() noexcept { setJavaExceptionAndAbortOnFailure(previous); } catch (std::exception& e) { FBLOGE("unexpected exception in translatePendingCppExceptionToJavaException: %s", e.what()); - // rethrow the exception and let the noexcept handling abort. - throw; + // std::terminate will print the message of the pending exception e + std::terminate(); } catch (...) { FBLOGE("unexpected exception in translatePendingCppExceptionToJavaException"); - throw; + std::terminate(); } } From 5a9f29debbe9cfe4a40576143647861fa56664f2 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 24 Jan 2019 06:28:01 -0800 Subject: [PATCH 166/189] Delete functionality for shared childen Summary: @public Removes `YGNodeInsertSharedChild` / `addSharedChildAt`. This functionality is unused, and can cause memory leaks. Reviewed By: SidharthGuglani Differential Revision: D13711105 fbshipit-source-id: 86206c05393b3f1a497e6b046006f94ead88c6ce --- java/com/facebook/yoga/YogaNode.java | 20 +++--------- java/jni/YGJNI.cpp | 9 ------ .../tests/com/facebook/yoga/YogaNodeTest.java | 32 +++---------------- yoga/Yoga.cpp | 14 -------- yoga/Yoga.h | 10 ------ 5 files changed, 8 insertions(+), 77 deletions(-) diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 7dd26947..a8168cf1 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -1,9 +1,8 @@ -/* - * Copyright (c) Facebook, Inc. - * - * This source code is licensed under the MIT license found in the LICENSE - * file in the root directory of this source tree. +/** + * 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; @@ -174,17 +173,6 @@ public class YogaNode implements Cloneable { jni_YGNodeInsertChild(mNativePointer, child.mNativePointer, i); } - private static native void jni_YGNodeInsertSharedChild(long nativePointer, long childPointer, int index); - - public void addSharedChildAt(YogaNode child, int i) { - if (mChildren == null) { - mChildren = new ArrayList<>(4); - } - mChildren.add(i, child); - child.mOwner = null; - jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i); - } - private static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline); public void setIsReferenceBaseline(boolean isReferenceBaseline) { diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index ea0d9d07..915876b5 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -359,14 +359,6 @@ void jni_YGNodeInsertChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } -void jni_YGNodeInsertSharedChild( - jlong nativePointer, - jlong childPointer, - jint index) { - YGNodeInsertSharedChild( - _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); -} - void jni_YGNodeRemoveChild(jlong nativePointer, jlong childPointer) { YGNodeRemoveChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); @@ -672,7 +664,6 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeCriticalNativeMethod(jni_YGNodeReset), YGMakeCriticalNativeMethod(jni_YGNodeClearChildren), YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), - YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline), YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline), diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index a792fe52..4b8a2ce5 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -1,9 +1,8 @@ -/* - * 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. +/** + * 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; @@ -280,29 +279,6 @@ public class YogaNodeTest { assertEquals(1, child.getChildCount()); } - @Test - public void testAddSharedChildCloneWithNewChildren() throws Exception { - YogaConfig config = new YogaConfig(); - YogaNode root = createNode(config); - YogaNode child = createNode(config); - YogaNode grandChild = createNode(config); - root.addChildAt(child, 0); - child.addChildAt(grandChild, 0); - child.setFlexDirection(YogaFlexDirection.ROW); - - YogaNode clonedChild = child.cloneWithNewChildren(); - - assertNotSame(clonedChild, child); - assertEquals(YogaFlexDirection.ROW, clonedChild.getFlexDirection()); - assertEquals(child.getFlexDirection(), clonedChild.getFlexDirection()); - assertEquals(0, clonedChild.getChildCount()); - assertEquals(1, child.getChildCount()); - - clonedChild.addSharedChildAt(grandChild, 0); - assertEquals(1, clonedChild.getChildCount()); - assertNull(grandChild.getOwner()); - } - @Test public void testCloneNodeListener() throws Exception { final AtomicBoolean onNodeClonedExecuted = new AtomicBoolean(false); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 38287e76..357e137b 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -402,20 +402,6 @@ void YGNodeInsertChild( node->markDirtyAndPropogate(); } -void YGNodeInsertSharedChild( - const YGNodeRef node, - const YGNodeRef child, - const uint32_t index) { - YGAssertWithNode( - node, - node->getMeasure() == nullptr, - "Cannot add child: Nodes with measure functions cannot have children."); - - node->insertChild(child, index); - child->setOwner(nullptr); - node->markDirtyAndPropogate(); -} - void YGNodeRemoveChild(const YGNodeRef owner, const YGNodeRef excludedChild) { // This algorithm is a forked variant from cloneChildrenIfNeeded in YGNode // that excludes a child. diff --git a/yoga/Yoga.h b/yoga/Yoga.h index afb4c9be..b15f8bb2 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -69,16 +69,6 @@ WIN_EXPORT void YGNodeInsertChild( const YGNodeRef child, const uint32_t index); -// This function inserts the child YGNodeRef as a children of the node received -// by parameter and set the Owner of the child object to null. This function is -// expected to be called when using Yoga in persistent mode in order to share a -// YGNodeRef object as a child of two different Yoga trees. The child YGNodeRef -// is expected to be referenced from its original owner and from a clone of its -// original owner. -WIN_EXPORT void YGNodeInsertSharedChild( - const YGNodeRef node, - const YGNodeRef child, - const uint32_t index); WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child); WIN_EXPORT void YGNodeRemoveAllChildren(const YGNodeRef node); WIN_EXPORT YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index); From 79355ab72d351e6cbcd0799b2d164fae4bb51262 Mon Sep 17 00:00:00 2001 From: Cameron Rollheiser Date: Tue, 29 Jan 2019 03:10:56 -0800 Subject: [PATCH 167/189] Spelling Fix (#851) Summary: Corrects the spelling of `corss-compiled` to `cross-compiled`. Pull Request resolved: https://github.com/facebook/yoga/pull/851 Reviewed By: SidharthGuglani Differential Revision: D13848545 Pulled By: davidaurelio fbshipit-source-id: 84b7d2a738f0faf863717818e8784acd5b5c8156 --- website/contents/getting-started/standalone.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/contents/getting-started/standalone.md b/website/contents/getting-started/standalone.md index 1b28654b..b94b3602 100644 --- a/website/contents/getting-started/standalone.md +++ b/website/contents/getting-started/standalone.md @@ -20,7 +20,7 @@ dependencies { The JavaScript bindings for Yoga can be used from node.js and within the browser. When using Yoga from node.js the native library is used, in browesers a pure JS -version is used (corss-compiled using [emscripten](http://kripken.github.io/emscripten-site/)). +version is used (cross-compiled using [emscripten](http://kripken.github.io/emscripten-site/)). ``` $> yarn add yoga-layout From e0eb37fce0a03ffe1ce872d9404adf91f4c4458a Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 03:48:30 -0800 Subject: [PATCH 168/189] Rename `YGMarkerType` to `YGMarker` Summary: @public this will lead to nicer enum member names. Reviewed By: SidharthGuglani Differential Revision: D13817587 fbshipit-source-id: 85355328f7977b4fb29a9474532f2d578a3cbf79 --- yoga/YGMarker.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index d4f4de64..df51d3b1 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -12,8 +12,8 @@ YG_EXTERN_C_BEGIN typedef struct YGNode* YGNodeRef; -typedef YG_ENUM_BEGIN(YGMarkerType) {} -YG_ENUM_END(YGMarkerType); +typedef YG_ENUM_BEGIN(YGMarker) {} +YG_ENUM_END(YGMarker); typedef union { int unused; @@ -22,10 +22,10 @@ typedef union { typedef struct { // accepts marker type, a node ref, and marker data (depends on marker type) // can return a handle or id that Yoga will pass to endMarker - void* (*startMarker)(YGMarkerType, YGNodeRef, YGMarkerData); + void* (*startMarker)(YGMarker, YGNodeRef, YGMarkerData); // accepts marker type, a node ref, marker data, and marker id as returned by // startMarker - void (*endMarker)(YGMarkerType, YGNodeRef, YGMarkerData, void* id); + void (*endMarker)(YGMarker, YGNodeRef, YGMarkerData, void* id); } YGMarkerCallbacks; YG_EXTERN_C_END From 96dfe068ee1ad6554384cf8d8cc77dd4ae2f2a00 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 03:48:31 -0800 Subject: [PATCH 169/189] Add `YGMarkerLayout` Summary: @public adds a first `YGMarker`, and the accompanying data type. Reviewed By: SidharthGuglani Differential Revision: D13817588 fbshipit-source-id: 6007eb09d19cf4021989bad5b5e880adb16364a0 --- yoga/YGMarker.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index df51d3b1..b7904ef1 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -12,11 +12,16 @@ YG_EXTERN_C_BEGIN typedef struct YGNode* YGNodeRef; -typedef YG_ENUM_BEGIN(YGMarker) {} -YG_ENUM_END(YGMarker); +typedef YG_ENUM_BEGIN(YGMarker){ + YGMarkerLayout, +} YG_ENUM_END(YGMarker); + +typedef struct { + int unused; +} YGMarkerLayoutData; typedef union { - int unused; + YGMarkerLayoutData* layout; } YGMarkerData; typedef struct { From 390fade8c01bdf9f6181cf4eb81752e204aa5535 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 03:48:31 -0800 Subject: [PATCH 170/189] Add function to set marker callbacks Summary: @public Adds a function to allow to configure markers. The function is declared in `YGMarker.h` Reviewed By: SidharthGuglani Differential Revision: D13819111 fbshipit-source-id: f9158b3d4e5727da4e151c84b523c7c7e8158620 --- yoga/YGMarker.cpp | 14 ++++++++++++++ yoga/YGMarker.h | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 yoga/YGMarker.cpp diff --git a/yoga/YGMarker.cpp b/yoga/YGMarker.cpp new file mode 100644 index 00000000..21a8d1f6 --- /dev/null +++ b/yoga/YGMarker.cpp @@ -0,0 +1,14 @@ +/** + * 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 "YGMarker.h" +#include "YGConfig.h" + +void YGConfigSetMarkerCallbacks( + YGConfigRef config, + YGMarkerCallbacks markerCallbacks) { + config->markerCallbacks = markerCallbacks; +} diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index b7904ef1..28fc3fff 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -11,6 +11,7 @@ YG_EXTERN_C_BEGIN typedef struct YGNode* YGNodeRef; +typedef struct YGConfig* YGConfigRef; typedef YG_ENUM_BEGIN(YGMarker){ YGMarkerLayout, @@ -33,4 +34,6 @@ typedef struct { void (*endMarker)(YGMarker, YGNodeRef, YGMarkerData, void* id); } YGMarkerCallbacks; +void YGConfigSetMarkerCallbacks(YGConfigRef, YGMarkerCallbacks); + YG_EXTERN_C_END From 3de3575ac468f8840c165b3184843a785cef8a3b Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 04:08:36 -0800 Subject: [PATCH 171/189] Remove unused constexpr Summary: @public Removes unused constexpr variables from YGStyle. Not polluting the global namespace is a good thing. Reviewed By: SidharthGuglani Differential Revision: D13816817 fbshipit-source-id: e4c27a8f2de466ccb759bbe52cdaea6fe451b961 --- yoga/YGStyle.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index e540635d..3af75c44 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -20,10 +20,6 @@ #define BITFIELD_ENUM_SIZED(num) #endif -constexpr YGValue kYGValueUndefined = {0, YGUnitUndefined}; - -constexpr YGValue kYGValueAuto = {0, YGUnitAuto}; - struct YGStyle { private: using CompactValue = facebook::yoga::detail::CompactValue; From 58f0cca7c728b4eca5616d77df23207235fe1bfa Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 10:30:11 -0800 Subject: [PATCH 172/189] Add `MarkerSection` Summary: @public Adds a class for triggering markers. This calls `startMarker()` on construction, and `endMarker()` on destruction, thus being usable like a "scope guard": the object is instantiated, and automatically destroyed when going out of scope. Reviewed By: SidharthGuglani Differential Revision: D13817589 fbshipit-source-id: fd88884af970c1c0933d9ca6843f3f8f5d28b9e6 --- tests/InstrumentationTest.cpp | 124 ++++++++++++++++++++++++++++++++++ yoga/YGMarker.h | 22 ++++++ yoga/instrumentation.h | 44 ++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 tests/InstrumentationTest.cpp create mode 100644 yoga/instrumentation.h diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp new file mode 100644 index 00000000..167e782e --- /dev/null +++ b/tests/InstrumentationTest.cpp @@ -0,0 +1,124 @@ +/** + * 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 +#include +#include +#include + +#include +#include +#include +#include + +namespace facebook { +namespace yoga { +namespace marker { +namespace test { + +template +using uniquePtr = std::unique_ptr>; + +struct MarkerTest : public ::testing::Test { + struct Data { + YGMarker marker; + YGNodeRef node; + YGMarkerData markerData; + }; + + struct EndData { + Data data; + void* cookie; + }; + + static struct { + Data start; + EndData end; + } markerCookie; + + static void* startMarker(YGMarker, YGNodeRef, YGMarkerData); + static void endMarker(YGMarker, YGNodeRef, YGMarkerData, void*); + static uniquePtr makeConfig(); + static uniquePtr makeNode(uniquePtr&); + + void SetUp() override; +}; + +TEST_F(MarkerTest, marker_start_works) { + auto config = makeConfig(); + auto root = makeNode(config); + + decltype(MarkerSection::data)* dataAddress; + { + MarkerSection marker{root.get()}; + dataAddress = &marker.data; + } + + ASSERT_EQ(markerCookie.start.marker, YGMarkerLayout) + << "wrong marker type passed to `startMarker`"; + ASSERT_EQ(markerCookie.start.node, root.get()) + << "wrong node pointer passed to `startMarker`"; + ASSERT_EQ(markerCookie.start.markerData.layout, dataAddress) + << "wrong pointer to marker data passed to `startMarker`"; +} + +TEST_F(MarkerTest, marker_end_works) { + auto config = makeConfig(); + auto root = makeNode(config); + + { MarkerSection marker{root.get()}; } + + ASSERT_EQ(markerCookie.end.data.marker, markerCookie.start.marker) + << "marker type passed to `endMarker` differs from type passed to " + "`startMarker`"; + ASSERT_EQ(markerCookie.end.data.node, markerCookie.start.node) + << "node passed to `endMarker` differs from node passed to `startMarker`"; + ASSERT_EQ( + markerCookie.end.data.markerData.layout, + markerCookie.start.markerData.layout) + << "marker data pointer passed to `endMarker` differs from pointer " + "passed to `startMarker`"; + ASSERT_EQ(markerCookie.end.cookie, &markerCookie) + << "pointer returned by `startMarker` was not passed to `endMarker`"; +} + +void* MarkerTest::startMarker( + YGMarker marker, + YGNodeRef node, + YGMarkerData data) { + markerCookie.start = {marker, node, data}; + return &markerCookie; +} + +void MarkerTest::endMarker( + YGMarker marker, + YGNodeRef node, + YGMarkerData data, + void* id) { + markerCookie.end = {{marker, node, data}, id}; +} + +uniquePtr MarkerTest::makeConfig() { + auto c = uniquePtr{YGConfigNew(), &YGConfigFree}; + YGConfigSetMarkerCallbacks(c.get(), {startMarker, endMarker}); + return c; +} + +uniquePtr MarkerTest::makeNode(uniquePtr& config) { + auto n = uniquePtr{YGNodeNewWithConfig(config.get()), &YGNodeFree}; + return n; +} + +void MarkerTest::SetUp() { + markerCookie = {}; +} + +decltype(MarkerTest::markerCookie) MarkerTest::markerCookie = {}; + +} // namespace test +} // namespace marker +} // namespace yoga +} // namespace facebook diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 28fc3fff..f7da1b58 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -37,3 +37,25 @@ typedef struct { void YGConfigSetMarkerCallbacks(YGConfigRef, YGMarkerCallbacks); YG_EXTERN_C_END + +#ifdef __cplusplus + +namespace facebook { +namespace yoga { +namespace marker { +namespace detail { + +template +struct MarkerData; + +template <> +struct MarkerData { + using type = YGMarkerLayoutData; +}; + +} // namespace detail +} // namespace marker +} // namespace yoga +} // namespace facebook + +#endif // __cplusplus diff --git a/yoga/instrumentation.h b/yoga/instrumentation.h new file mode 100644 index 00000000..670fc2bd --- /dev/null +++ b/yoga/instrumentation.h @@ -0,0 +1,44 @@ +/** + * 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 "YGConfig.h" +#include "YGMarker.h" +#include "YGNode.h" + +namespace facebook { +namespace yoga { +namespace marker { + +template +class MarkerSection { +public: + MarkerSection(YGNodeRef node) : MarkerSection{node, node->getConfig()} {} + ~MarkerSection() { + if (endMarker_) { + endMarker_(MarkerType, node_, {&data}, userData_); + } + } + + typename detail::MarkerData::type data = {}; + +private: + decltype(YGMarkerCallbacks{}.endMarker) endMarker_; + YGNodeRef node_; + void* userData_; + + MarkerSection(YGNodeRef node, YGConfigRef config) + : MarkerSection{node, config ? &config->markerCallbacks : nullptr} {} + MarkerSection(YGNodeRef node, YGMarkerCallbacks* callbacks) + : endMarker_{callbacks ? callbacks->endMarker : nullptr}, + node_{node}, + userData_{callbacks && callbacks->startMarker + ? callbacks->startMarker(MarkerType, node, {&data}) + : nullptr} {} +}; + +} // namespace marker +} // namespace yoga +} // namespace facebook From 74dd627495aa38ddf1c792d3774b7500375c2ff4 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 10:30:11 -0800 Subject: [PATCH 173/189] Introduce first marker Summary: @public Adds a marker section for a complete layout pass Reviewed By: SidharthGuglani Differential Revision: D13819447 fbshipit-source-id: 21a80f0fe3d325d804a968508761d115c50d3dc1 --- tests/InstrumentationTest.cpp | 10 ++++++++++ yoga/Yoga.cpp | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index 167e782e..be988ec0 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -85,6 +85,16 @@ TEST_F(MarkerTest, marker_end_works) { << "pointer returned by `startMarker` was not passed to `endMarker`"; } +TEST_F(MarkerTest, layout_marker) { + auto config = makeConfig(); + auto root = makeNode(config); + + YGNodeCalculateLayout(root.get(), YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(markerCookie.start.marker, YGMarkerLayout); + ASSERT_EQ(markerCookie.start.node, root.get()); +} + void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 357e137b..210c6637 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -12,6 +12,7 @@ #include "YGNode.h" #include "YGNodePrint.h" #include "Yoga-internal.h" +#include "instrumentation.h" #ifdef _MSC_VER #include @@ -4004,6 +4005,8 @@ void YGNodeCalculateLayout( const float ownerWidth, const float ownerHeight, const YGDirection ownerDirection) { + marker::MarkerSection marker{node}; + // Increment the generation count. This will force the recursive routine to // visit all dirty nodes at least once. Subsequent visits will be skipped if // the input parameters don't change. @@ -4118,8 +4121,9 @@ void YGNodeCalculateLayout( 0.0f); // Set whether the two layouts are different or not. - node->setLayoutDoesLegacyFlagAffectsLayout( - !originalNode->isLayoutTreeEqualToNode(*node)); + auto neededLegacyStretchBehaviour = + !originalNode->isLayoutTreeEqualToNode(*node); + node->setLayoutDoesLegacyFlagAffectsLayout(neededLegacyStretchBehaviour); if (originalNode->getConfig()->printTree) { YGNodePrint( From b4b009c2d85c1eaddf9f5aee81700f7b79f9e0a8 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 10:30:11 -0800 Subject: [PATCH 174/189] Pass layout marker data along Summary: pubic Passes layout marker data through the recursive calls of the layout algorithm, in order to allow for collecting metrics. Reviewed By: SidharthGuglani Differential Revision: D13819444 fbshipit-source-id: cdca04964fba6a03ca3eeaca4d169107019ba457 --- yoga/Yoga.cpp | 67 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 210c6637..6b91b7e1 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1021,7 +1021,8 @@ bool YGLayoutNodeInternal( const float ownerHeight, const bool performLayout, const char* reason, - const YGConfigRef config); + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData); static void YGNodePrintInternal( const YGNodeRef node, @@ -1260,7 +1261,8 @@ static void YGNodeComputeFlexBasisForChild( const float ownerHeight, const YGMeasureMode heightMode, const YGDirection direction, - const YGConfigRef config) { + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData) { const YGFlexDirection mainAxis = YGResolveFlexDirection(node->getStyle().flexDirection, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); @@ -1433,7 +1435,8 @@ static void YGNodeComputeFlexBasisForChild( ownerHeight, false, "measure", - config); + config, + layoutMarkerData); child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax( child->getLayout().measuredDimensions[dim[mainAxis]], @@ -1449,7 +1452,8 @@ static void YGNodeAbsoluteLayoutChild( const YGMeasureMode widthMode, const float height, const YGDirection direction, - const YGConfigRef config) { + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData) { const YGFlexDirection mainAxis = YGResolveFlexDirection(node->getStyle().flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); @@ -1553,7 +1557,8 @@ static void YGNodeAbsoluteLayoutChild( childHeight, false, "abs-measure", - config); + config, + layoutMarkerData); childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + child->getMarginForAxis(YGFlexDirectionRow, width).unwrap(); childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] + @@ -1571,7 +1576,8 @@ static void YGNodeAbsoluteLayoutChild( childHeight, true, "abs-layout", - config); + config, + layoutMarkerData); if (child->isTrailingPosDefined(mainAxis) && !child->isLeadingPositionDefined(mainAxis)) { @@ -1867,7 +1873,8 @@ static float YGNodeComputeFlexBasisForChildren( YGDirection direction, YGFlexDirection mainAxis, const YGConfigRef config, - bool performLayout) { + bool performLayout, + YGMarkerLayoutData& layoutMarkerData) { float totalOuterFlexBasis = 0.0f; YGNodeRef singleFlexChild = nullptr; YGVector children = node->getChildren(); @@ -1931,7 +1938,8 @@ static float YGNodeComputeFlexBasisForChildren( availableInnerHeight, heightMeasureMode, direction, - config); + config, + layoutMarkerData); } totalOuterFlexBasis += @@ -2043,7 +2051,8 @@ static float YGDistributeFreeSpaceSecondPass( const bool flexBasisOverflows, const YGMeasureMode measureModeCrossDim, const bool performLayout, - const YGConfigRef config) { + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData) { float childFlexBasis = 0; float flexShrinkScaledFactor = 0; float flexGrowFactor = 0; @@ -2207,7 +2216,8 @@ static float YGDistributeFreeSpaceSecondPass( availableInnerHeight, performLayout && !requiresStretchLayout, "flex", - config); + config, + layoutMarkerData); node->setLayoutHadOverflow( node->getLayout().hadOverflow | currentRelativeChild->getLayout().hadOverflow); @@ -2336,7 +2346,8 @@ static void YGResolveFlexibleLength( const bool flexBasisOverflows, const YGMeasureMode measureModeCrossDim, const bool performLayout, - const YGConfigRef config) { + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData) { const float originalFreeSpace = collectedFlexItemsValues.remainingFreeSpace; // First pass: detect the flex items whose min/max constraints trigger YGDistributeFreeSpaceFirstPass( @@ -2360,7 +2371,8 @@ static void YGResolveFlexibleLength( flexBasisOverflows, measureModeCrossDim, performLayout, - config); + config, + layoutMarkerData); collectedFlexItemsValues.remainingFreeSpace = originalFreeSpace - distributedFreeSpace; @@ -2656,7 +2668,8 @@ static void YGNodelayoutImpl( const float ownerWidth, const float ownerHeight, const bool performLayout, - const YGConfigRef config) { + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData) { YGAssertWithNode( node, YGFloatIsUndefined(availableWidth) @@ -2837,7 +2850,8 @@ static void YGNodelayoutImpl( direction, mainAxis, config, - performLayout); + performLayout, + layoutMarkerData); const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined ? false @@ -2943,7 +2957,8 @@ static void YGNodelayoutImpl( flexBasisOverflows, measureModeCrossDim, performLayout, - config); + config, + layoutMarkerData); } node->setLayoutHadOverflow( @@ -3108,7 +3123,8 @@ static void YGNodelayoutImpl( availableInnerHeight, true, "stretch", - config); + config, + layoutMarkerData); } } else { const float remainingCrossDim = containerCrossAxis - @@ -3314,7 +3330,8 @@ static void YGNodelayoutImpl( availableInnerHeight, true, "multiline-stretch", - config); + config, + layoutMarkerData); } } break; @@ -3451,7 +3468,8 @@ static void YGNodelayoutImpl( isMainAxisRow ? measureModeMainDim : measureModeCrossDim, availableInnerHeight, direction, - config); + config, + layoutMarkerData); } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN @@ -3683,7 +3701,8 @@ bool YGLayoutNodeInternal( const float ownerHeight, const bool performLayout, const char* reason, - const YGConfigRef config) { + const YGConfigRef config, + YGMarkerLayoutData& layoutMarkerData) { YGLayout* layout = &node->getLayout(); gDepth++; @@ -3837,7 +3856,8 @@ bool YGLayoutNodeInternal( ownerWidth, ownerHeight, performLayout, - config); + config, + layoutMarkerData); if (gPrintChanges) { YGLog( @@ -4067,7 +4087,8 @@ void YGNodeCalculateLayout( ownerHeight, true, "initial", - node->getConfig())) { + node->getConfig(), + marker.data)) { node->setPosition( node->getLayout().direction, ownerWidth, ownerHeight, ownerWidth); YGRoundToPixelGrid(node, node->getConfig()->pointScaleFactor, 0.0f, 0.0f); @@ -4097,6 +4118,7 @@ void YGNodeCalculateLayout( gCurrentGenerationCount++; // Rerun the layout, and calculate the diff originalNode->setAndPropogateUseLegacyFlag(false); + YGMarkerLayoutData layoutMarkerData; if (YGLayoutNodeInternal( originalNode, width, @@ -4108,7 +4130,8 @@ void YGNodeCalculateLayout( ownerHeight, true, "initial", - originalNode->getConfig())) { + originalNode->getConfig(), + layoutMarkerData)) { originalNode->setPosition( originalNode->getLayout().direction, ownerWidth, From cbea5d44b8efe6e69df44676f67b823d01e2cf49 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 10:30:11 -0800 Subject: [PATCH 175/189] Layout marker metadata Summary: @public Adds marker meta data to `YGMarkerLayout`: the number of measures, and the numbers of layouts for all nodes in the tree. Reviewed By: SidharthGuglani Differential Revision: D13838975 fbshipit-source-id: d575c26a3d5a4f0b66834eb6bedecadc3f3ca265 --- tests/InstrumentationTest.cpp | 41 ++++++++++++++++++++++++++++++++++- yoga/YGMarker.h | 12 +++++++++- yoga/Yoga.cpp | 2 ++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index be988ec0..42e36efa 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -32,6 +32,9 @@ struct MarkerTest : public ::testing::Test { struct EndData { Data data; void* cookie; + union { + YGMarkerLayoutData layout; + } markerData; }; static struct { @@ -43,6 +46,7 @@ struct MarkerTest : public ::testing::Test { static void endMarker(YGMarker, YGNodeRef, YGMarkerData, void*); static uniquePtr makeConfig(); static uniquePtr makeNode(uniquePtr&); + static uniquePtr makeNode(uniquePtr&, uniquePtr&); void SetUp() override; }; @@ -95,6 +99,28 @@ TEST_F(MarkerTest, layout_marker) { ASSERT_EQ(markerCookie.start.node, root.get()); } +TEST_F(MarkerTest, layout_marker_counts_single_node_layout) { + auto config = makeConfig(); + auto root = makeNode(config); + + YGNodeCalculateLayout(root.get(), YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(markerCookie.end.markerData.layout.layouts, 1); + ASSERT_EQ(markerCookie.end.markerData.layout.measures, 0); +} + +TEST_F(MarkerTest, layout_marker_counts_multi_node_layout) { + auto config = makeConfig(); + auto root = makeNode(config); + auto childA = makeNode(config, root); + auto childB = makeNode(config, root); + + YGNodeCalculateLayout(root.get(), YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(markerCookie.end.markerData.layout.layouts, 3); + ASSERT_EQ(markerCookie.end.markerData.layout.measures, 4); +} + void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, @@ -108,7 +134,12 @@ void MarkerTest::endMarker( YGNodeRef node, YGMarkerData data, void* id) { - markerCookie.end = {{marker, node, data}, id}; + markerCookie.end = {{marker, node, data}, id, {}}; + switch (marker) { + case YGMarkerLayout: + markerCookie.end.markerData.layout = *marker::data(data); + break; + }; } uniquePtr MarkerTest::makeConfig() { @@ -122,6 +153,14 @@ uniquePtr MarkerTest::makeNode(uniquePtr& config) { return n; } +uniquePtr MarkerTest::makeNode( + uniquePtr& config, + uniquePtr& owner) { + auto n = makeNode(config); + YGNodeInsertChild(owner.get(), n.get(), YGNodeGetChildCount(owner.get())); + return n; +} + void MarkerTest::SetUp() { markerCookie = {}; } diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index f7da1b58..15280927 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -18,7 +18,8 @@ typedef YG_ENUM_BEGIN(YGMarker){ } YG_ENUM_END(YGMarker); typedef struct { - int unused; + int layouts; + int measures; } YGMarkerLayoutData; typedef union { @@ -54,6 +55,15 @@ struct MarkerData { }; } // namespace detail + +template +typename detail::MarkerData::type* data(YGMarkerData) = delete; + +template <> +inline YGMarkerLayoutData* data(YGMarkerData d) { + return d.layout; +} + } // namespace marker } // namespace yoga } // namespace facebook diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 6b91b7e1..9461bb3f 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2685,6 +2685,8 @@ static void YGNodelayoutImpl( "availableHeight is indefinite so heightMeasureMode must be " "YGMeasureModeUndefined"); + (performLayout ? layoutMarkerData.layouts : layoutMarkerData.measures) += 1; + // Set the resolved resolution in the node's layout. const YGDirection direction = node->resolveDirection(ownerDirection); node->setLayoutDirection(direction); From 460370b7d311df829ae76a47245ef2b59726378b Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 10:30:14 -0800 Subject: [PATCH 176/189] More readable instrumentation test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public Evolves setup and helpers in `InstrumentationTest` to avoid repetition across test cases, and allow for more readable test by hiding default values where they don’t matter. Reviewed By: SidharthGuglani Differential Revision: D13839521 fbshipit-source-id: 7f7ad49fec84e0bbb09ad746dd8c28bd34de25b2 --- tests/InstrumentationTest.cpp | 81 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index 42e36efa..cb02bd99 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -14,6 +14,9 @@ #include #include +bool operator==(const YGMarkerLayoutData&, const YGMarkerLayoutData&); +void PrintTo(const YGMarkerLayoutData, std::ostream*); + namespace facebook { namespace yoga { namespace marker { @@ -44,16 +47,19 @@ struct MarkerTest : public ::testing::Test { static void* startMarker(YGMarker, YGNodeRef, YGMarkerData); static void endMarker(YGMarker, YGNodeRef, YGMarkerData, void*); - static uniquePtr makeConfig(); - static uniquePtr makeNode(uniquePtr&); - static uniquePtr makeNode(uniquePtr&, uniquePtr&); + uniquePtr makeNode(); + uniquePtr addChild(uniquePtr& owner); + static void calculateLayout( + uniquePtr& node, + float width = YGUndefined, + float height = YGUndefined); void SetUp() override; + uniquePtr config; }; TEST_F(MarkerTest, marker_start_works) { - auto config = makeConfig(); - auto root = makeNode(config); + auto root = makeNode(); decltype(MarkerSection::data)* dataAddress; { @@ -70,8 +76,7 @@ TEST_F(MarkerTest, marker_start_works) { } TEST_F(MarkerTest, marker_end_works) { - auto config = makeConfig(); - auto root = makeNode(config); + auto root = makeNode(); { MarkerSection marker{root.get()}; } @@ -90,35 +95,34 @@ TEST_F(MarkerTest, marker_end_works) { } TEST_F(MarkerTest, layout_marker) { - auto config = makeConfig(); - auto root = makeNode(config); + auto root = makeNode(); - YGNodeCalculateLayout(root.get(), YGUndefined, YGUndefined, YGDirectionLTR); + calculateLayout(root); ASSERT_EQ(markerCookie.start.marker, YGMarkerLayout); ASSERT_EQ(markerCookie.start.node, root.get()); } TEST_F(MarkerTest, layout_marker_counts_single_node_layout) { - auto config = makeConfig(); - auto root = makeNode(config); + auto root = makeNode(); - YGNodeCalculateLayout(root.get(), YGUndefined, YGUndefined, YGDirectionLTR); + calculateLayout(root); - ASSERT_EQ(markerCookie.end.markerData.layout.layouts, 1); - ASSERT_EQ(markerCookie.end.markerData.layout.measures, 0); + ASSERT_EQ( + markerCookie.end.markerData.layout, + (YGMarkerLayoutData{.layouts = 1, .measures = 0})); } TEST_F(MarkerTest, layout_marker_counts_multi_node_layout) { - auto config = makeConfig(); - auto root = makeNode(config); - auto childA = makeNode(config, root); - auto childB = makeNode(config, root); + auto root = makeNode(); + auto childA = addChild(root); + auto childB = addChild(root); - YGNodeCalculateLayout(root.get(), YGUndefined, YGUndefined, YGDirectionLTR); + calculateLayout(root); - ASSERT_EQ(markerCookie.end.markerData.layout.layouts, 3); - ASSERT_EQ(markerCookie.end.markerData.layout.measures, 4); + ASSERT_EQ( + markerCookie.end.markerData.layout, + (YGMarkerLayoutData{.layouts = 3, .measures = 4})); } void* MarkerTest::startMarker( @@ -142,27 +146,29 @@ void MarkerTest::endMarker( }; } -uniquePtr MarkerTest::makeConfig() { - auto c = uniquePtr{YGConfigNew(), &YGConfigFree}; - YGConfigSetMarkerCallbacks(c.get(), {startMarker, endMarker}); - return c; -} - -uniquePtr MarkerTest::makeNode(uniquePtr& config) { +uniquePtr MarkerTest::makeNode() { auto n = uniquePtr{YGNodeNewWithConfig(config.get()), &YGNodeFree}; return n; } -uniquePtr MarkerTest::makeNode( - uniquePtr& config, - uniquePtr& owner) { - auto n = makeNode(config); +uniquePtr MarkerTest::addChild(uniquePtr& owner) { + auto n = makeNode(); YGNodeInsertChild(owner.get(), n.get(), YGNodeGetChildCount(owner.get())); return n; } +void MarkerTest::calculateLayout( + uniquePtr& node, + float width, + float height) { + YGNodeCalculateLayout(node.get(), width, height, YGDirectionLTR); +} + void MarkerTest::SetUp() { markerCookie = {}; + + config = uniquePtr{YGConfigNew(), &YGConfigFree}; + YGConfigSetMarkerCallbacks(config.get(), {startMarker, endMarker}); } decltype(MarkerTest::markerCookie) MarkerTest::markerCookie = {}; @@ -171,3 +177,12 @@ decltype(MarkerTest::markerCookie) MarkerTest::markerCookie = {}; } // namespace marker } // namespace yoga } // namespace facebook + +bool operator==(const YGMarkerLayoutData& lhs, const YGMarkerLayoutData& rhs) { + return lhs.layouts == rhs.layouts && lhs.measures == rhs.measures; +} + +void PrintTo(const YGMarkerLayoutData data, std::ostream* os) { + *os << "YGMarkerLayoutData{ layouts = " << data.layouts + << ", measures = " << data.measures << " }"; +} From 59446294b35300c27fa321584790203eac38dc58 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 10:30:14 -0800 Subject: [PATCH 177/189] count cache hits Summary: @public Adds cache hit counts to layout stats. Reviewed By: SidharthGuglani Differential Revision: D13844022 fbshipit-source-id: 906b4ec5fe3314287911cee2c37d77c4aac76455 --- tests/InstrumentationTest.cpp | 39 +++++++++++++++++++++++++++++++++-- yoga/YGMarker.h | 2 ++ yoga/Yoga.cpp | 3 +++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index cb02bd99..4c948285 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -125,6 +125,37 @@ TEST_F(MarkerTest, layout_marker_counts_multi_node_layout) { (YGMarkerLayoutData{.layouts = 3, .measures = 4})); } +TEST_F(MarkerTest, layout_marker_counts_cache_hits_single_node_layout) { + auto root = makeNode(); + calculateLayout(root); + + calculateLayout(root); + + ASSERT_EQ( + markerCookie.end.markerData.layout, + (YGMarkerLayoutData{.layouts = 0, + .measures = 0, + .cachedLayouts = 1, + .cachedMeasures = 0})); +} + +TEST_F(MarkerTest, layout_marker_counts_cache_hits_multi_node_layout) { + auto root = makeNode(); + auto childA = addChild(root); + auto childB = addChild(root); + calculateLayout(root, 987, 654); + calculateLayout(root, 123, 456); + + calculateLayout(root, 987, 654); + + ASSERT_EQ( + markerCookie.end.markerData.layout, + (YGMarkerLayoutData{.layouts = 3, + .measures = 0, + .cachedLayouts = 0, + .cachedMeasures = 4})); +} + void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, @@ -179,10 +210,14 @@ decltype(MarkerTest::markerCookie) MarkerTest::markerCookie = {}; } // namespace facebook bool operator==(const YGMarkerLayoutData& lhs, const YGMarkerLayoutData& rhs) { - return lhs.layouts == rhs.layouts && lhs.measures == rhs.measures; + return lhs.layouts == rhs.layouts && lhs.measures == rhs.measures && + lhs.cachedLayouts == rhs.cachedLayouts && + lhs.cachedMeasures == rhs.cachedMeasures; } void PrintTo(const YGMarkerLayoutData data, std::ostream* os) { *os << "YGMarkerLayoutData{ layouts = " << data.layouts - << ", measures = " << data.measures << " }"; + << ", measures = " << data.measures + << ", cachedLayouts = " << data.cachedLayouts + << ", cachedMeasures = " << data.cachedMeasures << " }"; } diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 15280927..60de5120 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -20,6 +20,8 @@ typedef YG_ENUM_BEGIN(YGMarker){ typedef struct { int layouts; int measures; + int cachedLayouts; + int cachedMeasures; } YGMarkerLayoutData; typedef union { diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 9461bb3f..9ae16401 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -3803,6 +3803,9 @@ bool YGLayoutNodeInternal( layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight; + (performLayout ? layoutMarkerData.cachedLayouts + : layoutMarkerData.cachedMeasures) += 1; + if (gPrintChanges && gPrintSkips) { YGLog( node, From 68f7001ed4cd8f19f7e20e714dfe2f5d0a1190ab Mon Sep 17 00:00:00 2001 From: CangZhu Date: Tue, 29 Jan 2019 12:20:33 -0800 Subject: [PATCH 178/189] feat: expose flex prop to YogaKit (#844) Summary: This exposes `yoga` property to `YogaKit` Pull Request resolved: https://github.com/facebook/yoga/pull/844 Reviewed By: SidharthGuglani Differential Revision: D13849076 Pulled By: davidaurelio fbshipit-source-id: 560986c2235dfd28d287f61b2e784c9eef6c5eda --- YogaKit/Source/YGLayout.h | 1 + YogaKit/Source/YGLayout.m | 1 + 2 files changed, 2 insertions(+) diff --git a/YogaKit/Source/YGLayout.h b/YogaKit/Source/YGLayout.h index 8aff3b5e..c8ee2e84 100644 --- a/YogaKit/Source/YGLayout.h +++ b/YogaKit/Source/YGLayout.h @@ -62,6 +62,7 @@ typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) { @property (nonatomic, readwrite, assign) YGOverflow overflow; @property (nonatomic, readwrite, assign) YGDisplay display; +@property (nonatomic, readwrite, assign) CGFloat flex; @property (nonatomic, readwrite, assign) CGFloat flexGrow; @property (nonatomic, readwrite, assign) CGFloat flexShrink; @property (nonatomic, readwrite, assign) YGValue flexBasis; diff --git a/YogaKit/Source/YGLayout.m b/YogaKit/Source/YGLayout.m index 7779c437..e333765f 100644 --- a/YogaKit/Source/YGLayout.m +++ b/YogaKit/Source/YGLayout.m @@ -229,6 +229,7 @@ YG_PROPERTY(YGWrap, flexWrap, FlexWrap) YG_PROPERTY(YGOverflow, overflow, Overflow) YG_PROPERTY(YGDisplay, display, Display) +YG_PROPERTY(CGFloat, flex, Flex) YG_PROPERTY(CGFloat, flexGrow, FlexGrow) YG_PROPERTY(CGFloat, flexShrink, FlexShrink) YG_AUTO_VALUE_PROPERTY(flexBasis, FlexBasis) From 1bc97a5e48b9a5766e33ea9fc06b207b1067b614 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 29 Jan 2019 14:44:55 -0800 Subject: [PATCH 179/189] Track how much measure cache entries are used Summary: @public Adds the maximum number of measure cache entries in use to the metrics for `YGMarkerLayout` Reviewed By: SidharthGuglani Differential Revision: D13844731 fbshipit-source-id: fa66dbf1b7a1799494f72ecc17dfaef04d0b56e4 --- tests/InstrumentationTest.cpp | 22 ++++++++++++++++++++-- yoga/YGMarker.h | 1 + yoga/Yoga.cpp | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index 4c948285..dc3afb50 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -110,7 +110,7 @@ TEST_F(MarkerTest, layout_marker_counts_single_node_layout) { ASSERT_EQ( markerCookie.end.markerData.layout, - (YGMarkerLayoutData{.layouts = 1, .measures = 0})); + (YGMarkerLayoutData{.layouts = 1, .measures = 0, .maxMeasureCache = 1})); } TEST_F(MarkerTest, layout_marker_counts_multi_node_layout) { @@ -122,7 +122,7 @@ TEST_F(MarkerTest, layout_marker_counts_multi_node_layout) { ASSERT_EQ( markerCookie.end.markerData.layout, - (YGMarkerLayoutData{.layouts = 3, .measures = 4})); + (YGMarkerLayoutData{.layouts = 3, .measures = 4, .maxMeasureCache = 3})); } TEST_F(MarkerTest, layout_marker_counts_cache_hits_single_node_layout) { @@ -152,10 +152,26 @@ TEST_F(MarkerTest, layout_marker_counts_cache_hits_multi_node_layout) { markerCookie.end.markerData.layout, (YGMarkerLayoutData{.layouts = 3, .measures = 0, + .maxMeasureCache = 5, .cachedLayouts = 0, .cachedMeasures = 4})); } +TEST_F(MarkerTest, layout_marker_has_max_measure_cache) { + auto root = makeNode(); + auto a = addChild(root); + auto b = addChild(root); + YGNodeStyleSetFlexBasis(a.get(), 10.0f); + + for (auto s : {20, 30, 40}) { + calculateLayout(root, s, s); + } + + ASSERT_EQ( + markerCookie.end.markerData.layout, + (YGMarkerLayoutData{.layouts = 3, .measures = 3, .maxMeasureCache = 7})); +} + void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, @@ -211,6 +227,7 @@ decltype(MarkerTest::markerCookie) MarkerTest::markerCookie = {}; bool operator==(const YGMarkerLayoutData& lhs, const YGMarkerLayoutData& rhs) { return lhs.layouts == rhs.layouts && lhs.measures == rhs.measures && + lhs.maxMeasureCache == rhs.maxMeasureCache && lhs.cachedLayouts == rhs.cachedLayouts && lhs.cachedMeasures == rhs.cachedMeasures; } @@ -218,6 +235,7 @@ bool operator==(const YGMarkerLayoutData& lhs, const YGMarkerLayoutData& rhs) { void PrintTo(const YGMarkerLayoutData data, std::ostream* os) { *os << "YGMarkerLayoutData{ layouts = " << data.layouts << ", measures = " << data.measures + << ", maxMeasureCache = " << data.maxMeasureCache << ", cachedLayouts = " << data.cachedLayouts << ", cachedMeasures = " << data.cachedMeasures << " }"; } diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 60de5120..63f2c40f 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -20,6 +20,7 @@ typedef YG_ENUM_BEGIN(YGMarker){ typedef struct { int layouts; int measures; + int maxMeasureCache; int cachedLayouts; int cachedMeasures; } YGMarkerLayoutData; diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 9ae16401..0d576d59 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -3889,6 +3889,11 @@ bool YGLayoutNodeInternal( layout->lastOwnerDirection = ownerDirection; if (cachedResults == nullptr) { + if (layout->nextCachedMeasurementsIndex + 1 > + (uint32_t) layoutMarkerData.maxMeasureCache) { + layoutMarkerData.maxMeasureCache = + layout->nextCachedMeasurementsIndex + 1; + } if (layout->nextCachedMeasurementsIndex == YG_MAX_CACHED_RESULT_COUNT) { if (gPrintChanges) { YGLog(node, YGLogLevelVerbose, "Out of cache entries!\n"); From 0846439c8e94a43be451bb12451725e561151aee Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 31 Jan 2019 22:59:19 +0100 Subject: [PATCH 180/189] Bring github and internal back in sync --- tools/build_defs/fb_native_wrapper.bzl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/build_defs/fb_native_wrapper.bzl b/tools/build_defs/fb_native_wrapper.bzl index 3d246dee..4e251dc0 100644 --- a/tools/build_defs/fb_native_wrapper.bzl +++ b/tools/build_defs/fb_native_wrapper.bzl @@ -1,8 +1,3 @@ -# 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. - fb_native = struct( android_aar = native.android_aar, android_app_modularity = native.android_app_modularity, From 31ce3ab86602a2c78cdc566a3cf8027b3dfe10b6 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 30 Jan 2019 08:37:08 -0800 Subject: [PATCH 181/189] Add license header to `fb_native_wrapper.bzl` Summary: Github and fbsource got out of sync, we have a PR to fix this: https://github.com/facebook/yoga/pull/843 This updates the internal-only file to match the PR, so that we can merge it without hassle. Reviewed By: cuva Differential Revision: D13879526 fbshipit-source-id: f83115617e580e118a5f4e0f37e877db38a8fcac --- tools/build_defs/fb_native_wrapper.bzl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/build_defs/fb_native_wrapper.bzl b/tools/build_defs/fb_native_wrapper.bzl index 4e251dc0..3d246dee 100644 --- a/tools/build_defs/fb_native_wrapper.bzl +++ b/tools/build_defs/fb_native_wrapper.bzl @@ -1,3 +1,8 @@ +# 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. + fb_native = struct( android_aar = native.android_aar, android_app_modularity = native.android_app_modularity, From 4a6b1e19b8f8b130d3f6423f0d4ca59ddabaafc1 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 31 Jan 2019 08:03:07 -0800 Subject: [PATCH 182/189] `InstrumentationTest`: allow to record multiple markers Summary: @public Extends `InstrumentationTest` with the ability to record more than one marker. Instead of overwriting any previously recorder marker, we collect them in a `std::deque`. `std::deque` was chosen, because it keeps pointers to elements stable. Reviewed By: SidharthGuglani Differential Revision: D13880777 fbshipit-source-id: f6f6606ac8625bdd90c06459fdb967c3478265e7 --- tests/InstrumentationTest.cpp | 81 ++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index dc3afb50..585073ff 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -10,9 +10,11 @@ #include #include +#include +#include #include #include -#include +#include bool operator==(const YGMarkerLayoutData&, const YGMarkerLayoutData&); void PrintTo(const YGMarkerLayoutData, std::ostream*); @@ -40,10 +42,14 @@ struct MarkerTest : public ::testing::Test { } markerData; }; - static struct { + struct MarkerCookie { Data start; EndData end; - } markerCookie; + }; + + // std::deque will keep pointers stable on reallocation, whereas std::vector + // does not + static std::deque markerCookies; static void* startMarker(YGMarker, YGNodeRef, YGMarkerData); static void endMarker(YGMarker, YGNodeRef, YGMarkerData, void*); @@ -53,8 +59,11 @@ struct MarkerTest : public ::testing::Test { uniquePtr& node, float width = YGUndefined, float height = YGUndefined); + static MarkerCookie& findMarker(YGMarker); + static MarkerCookie& findLastMarker(YGMarker); void SetUp() override; + void TearDown() override; uniquePtr config; }; @@ -67,6 +76,8 @@ TEST_F(MarkerTest, marker_start_works) { dataAddress = &marker.data; } + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ(markerCookie.start.marker, YGMarkerLayout) << "wrong marker type passed to `startMarker`"; ASSERT_EQ(markerCookie.start.node, root.get()) @@ -80,6 +91,8 @@ TEST_F(MarkerTest, marker_end_works) { { MarkerSection marker{root.get()}; } + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ(markerCookie.end.data.marker, markerCookie.start.marker) << "marker type passed to `endMarker` differs from type passed to " "`startMarker`"; @@ -99,6 +112,8 @@ TEST_F(MarkerTest, layout_marker) { calculateLayout(root); + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ(markerCookie.start.marker, YGMarkerLayout); ASSERT_EQ(markerCookie.start.node, root.get()); } @@ -108,6 +123,8 @@ TEST_F(MarkerTest, layout_marker_counts_single_node_layout) { calculateLayout(root); + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ( markerCookie.end.markerData.layout, (YGMarkerLayoutData{.layouts = 1, .measures = 0, .maxMeasureCache = 1})); @@ -120,6 +137,8 @@ TEST_F(MarkerTest, layout_marker_counts_multi_node_layout) { calculateLayout(root); + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ( markerCookie.end.markerData.layout, (YGMarkerLayoutData{.layouts = 3, .measures = 4, .maxMeasureCache = 3})); @@ -131,6 +150,8 @@ TEST_F(MarkerTest, layout_marker_counts_cache_hits_single_node_layout) { calculateLayout(root); + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ( markerCookie.end.markerData.layout, (YGMarkerLayoutData{.layouts = 0, @@ -148,6 +169,8 @@ TEST_F(MarkerTest, layout_marker_counts_cache_hits_multi_node_layout) { calculateLayout(root, 987, 654); + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ( markerCookie.end.markerData.layout, (YGMarkerLayoutData{.layouts = 3, @@ -167,6 +190,8 @@ TEST_F(MarkerTest, layout_marker_has_max_measure_cache) { calculateLayout(root, s, s); } + auto& markerCookie = findLastMarker(YGMarkerLayout); + ASSERT_EQ( markerCookie.end.markerData.layout, (YGMarkerLayoutData{.layouts = 3, .measures = 3, .maxMeasureCache = 7})); @@ -176,8 +201,10 @@ void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, YGMarkerData data) { - markerCookie.start = {marker, node, data}; - return &markerCookie; + markerCookies.emplace_back(); + MarkerCookie* cookie = &markerCookies.back(); + cookie->start = {marker, node, data}; + return cookie; } void MarkerTest::endMarker( @@ -185,10 +212,11 @@ void MarkerTest::endMarker( YGNodeRef node, YGMarkerData data, void* id) { - markerCookie.end = {{marker, node, data}, id, {}}; + auto cookie = static_cast(id); + cookie->end = {{marker, node, data}, id, {}}; switch (marker) { case YGMarkerLayout: - markerCookie.end.markerData.layout = *marker::data(data); + cookie->end.markerData.layout = *marker::data(data); break; }; } @@ -211,14 +239,47 @@ void MarkerTest::calculateLayout( YGNodeCalculateLayout(node.get(), width, height, YGDirectionLTR); } -void MarkerTest::SetUp() { - markerCookie = {}; +namespace { +const char* markerTypeName(YGMarker type) { + switch (type) { + case YGMarkerLayout: + return "YGMarkerLayout"; + } +} + +template +MarkerTest::MarkerCookie& find(It begin, It end, YGMarker type) { + auto result = std::find_if(begin, end, [type](MarkerTest::MarkerCookie& c) { + return c.start.marker == type; + }); + if (result == end) { + throw std::runtime_error{std::string{"No marker recorded for type: "} + + markerTypeName(type)}; + } + return *result; +} + +} // namespace + +MarkerTest::MarkerCookie& MarkerTest::findMarker(YGMarker markerType) { + return find(markerCookies.begin(), markerCookies.end(), markerType); +} + +MarkerTest::MarkerCookie& MarkerTest::findLastMarker(YGMarker markerType) { + return find(markerCookies.rbegin(), markerCookies.rend(), markerType); +} + +void MarkerTest::SetUp() { config = uniquePtr{YGConfigNew(), &YGConfigFree}; YGConfigSetMarkerCallbacks(config.get(), {startMarker, endMarker}); } -decltype(MarkerTest::markerCookie) MarkerTest::markerCookie = {}; +void MarkerTest::TearDown() { + markerCookies.resize(0); +} + +decltype(MarkerTest::markerCookies) MarkerTest::markerCookies = {}; } // namespace test } // namespace marker From 8691cdaed66d4fefe63fdb81d1240ca5b59028b7 Mon Sep 17 00:00:00 2001 From: Reinier Hartog Date: Thu, 31 Jan 2019 09:06:57 -0800 Subject: [PATCH 183/189] Expose dirtied func in Javascript bindings (#842) Summary: Yoga currently has the concept of a 'dirtied func', which is called when a Node becomes dirty, which can be useful to trigger a repaint. This PR exposes that functionality in the Javascript bindings. Pull Request resolved: https://github.com/facebook/yoga/pull/842 Reviewed By: SidharthGuglani Differential Revision: D13847093 Pulled By: davidaurelio fbshipit-source-id: 41913abd6eedc46ee7d66929140e08a084f23972 --- javascript/sources/Node.cc | 27 +++ javascript/sources/Node.hh | 11 +- javascript/sources/nbind.cc | 3 + .../tests/Facebook.Yoga/YGDirtiedTest.js | 168 ++++++++++++++++++ 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 javascript/tests/Facebook.Yoga/YGDirtiedTest.js diff --git a/javascript/sources/Node.cc b/javascript/sources/Node.cc index 108bc4b5..748a6cd0 100644 --- a/javascript/sources/Node.cc +++ b/javascript/sources/Node.cc @@ -23,6 +23,13 @@ static YGSize globalMeasureFunc(YGNodeRef nodeRef, float width, YGMeasureMode wi return ygSize; } +static void globalDirtiedFunc(YGNodeRef nodeRef) +{ + Node const & node = *reinterpret_cast(YGNodeGetContext(nodeRef)); + + node.callDirtiedFunc(); +} + /* static */ Node * Node::createDefault(void) { return new Node(nullptr); @@ -46,6 +53,7 @@ static YGSize globalMeasureFunc(YGNodeRef nodeRef, float width, YGMeasureMode wi Node::Node(Config * config) : m_node(config != nullptr ? YGNodeNewWithConfig(config->m_config) : YGNodeNew()) , m_measureFunc(nullptr) +, m_dirtiedFunc(nullptr) { YGNodeSetContext(m_node, reinterpret_cast(this)); } @@ -58,6 +66,7 @@ Node::~Node(void) void Node::reset(void) { m_measureFunc.reset(nullptr); + m_dirtiedFunc.reset(nullptr); YGNodeReset(m_node); } @@ -429,6 +438,24 @@ Size Node::callMeasureFunc(double width, int widthMode, double height, int heigh return m_measureFunc->call(width, widthMode, height, heightMode); } +void Node::setDirtiedFunc(nbind::cbFunction & dirtiedFunc) +{ + m_dirtiedFunc.reset(new nbind::cbFunction(dirtiedFunc)); + + YGNodeSetDirtiedFunc(m_node, &globalDirtiedFunc); +} + +void Node::unsetDirtiedFunc(void) { + m_dirtiedFunc.reset(nullptr); + + YGNodeSetDirtiedFunc(m_node, nullptr); +} + +void Node::callDirtiedFunc(void) const +{ + m_dirtiedFunc->call(); +} + void Node::markDirty(void) { YGNodeMarkDirty(m_node); diff --git a/javascript/sources/Node.hh b/javascript/sources/Node.hh index 593745b2..a3114505 100644 --- a/javascript/sources/Node.hh +++ b/javascript/sources/Node.hh @@ -161,6 +161,15 @@ class Node { Size callMeasureFunc(double width, int widthMode, double height, int heightMode) const; + public: // Dirtied func mutators + + void setDirtiedFunc(nbind::cbFunction & dirtiedFunc); + void unsetDirtiedFunc(void); + + public: // Dirtied func inspectors + + void callDirtiedFunc(void) const; + public: // Dirtiness accessors void markDirty(void); @@ -194,5 +203,5 @@ class Node { YGNodeRef m_node; std::unique_ptr m_measureFunc; - + std::unique_ptr m_dirtiedFunc; }; diff --git a/javascript/sources/nbind.cc b/javascript/sources/nbind.cc index c778fe8a..7f1aac0f 100644 --- a/javascript/sources/nbind.cc +++ b/javascript/sources/nbind.cc @@ -155,6 +155,9 @@ NBIND_CLASS(Node) method(setMeasureFunc); method(unsetMeasureFunc); + method(setDirtiedFunc); + method(unsetDirtiedFunc); + method(markDirty); method(isDirty); diff --git a/javascript/tests/Facebook.Yoga/YGDirtiedTest.js b/javascript/tests/Facebook.Yoga/YGDirtiedTest.js new file mode 100644 index 00000000..20320c43 --- /dev/null +++ b/javascript/tests/Facebook.Yoga/YGDirtiedTest.js @@ -0,0 +1,168 @@ +/** + * 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. + */ + +var Yoga = Yoga || require("../../sources/entry-" + process.env.TEST_ENTRY); + +it("dirtied", function() { + var root = Yoga.Node.create(); + root.setAlignItems(Yoga.ALIGN_FLEX_START); + root.setWidth(100); + root.setHeight(100); + + root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR); + + let dirtied = 0; + root.setDirtiedFunc(function() { dirtied++; }); + // only nodes with a measure function can be marked dirty + root.setMeasureFunc(function() {}); + + console.assert(0 === dirtied, "0 === dirtied"); + + // dirtied func MUST be called in case of explicit dirtying. + root.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + // dirtied func MUST be called ONCE. + root.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + if (typeof root !== "undefined") + root.freeRecursive(); + + typeof gc !== "undefined" && gc(); + console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")"); +}); + +it("dirtied_propagation", function() { + var root = Yoga.Node.create(); + root.setAlignItems(Yoga.ALIGN_FLEX_START); + root.setWidth(100); + root.setHeight(100); + + var root_child0 = Yoga.Node.create(); + root_child0.setAlignItems(Yoga.ALIGN_FLEX_START); + root_child0.setWidth(50); + root_child0.setHeight(20); + root_child0.setMeasureFunc(function() {}); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(); + root_child1.setAlignItems(Yoga.ALIGN_FLEX_START); + root_child1.setWidth(50); + root_child1.setHeight(20); + root.insertChild(root_child1, 0); + + root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR); + + let dirtied = 0; + root.setDirtiedFunc(function() { dirtied++; }); + + console.assert(0 === dirtied, "0 === dirtied"); + + // dirtied func MUST be called for the first time. + root_child0.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + // dirtied func must NOT be called for the second time. + root_child0.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + if (typeof root !== "undefined") + root.freeRecursive(); + + typeof gc !== "undefined" && gc(); + console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")"); +}); + +it("dirtied_hierarchy", function() { + var root = Yoga.Node.create(); + root.setAlignItems(Yoga.ALIGN_FLEX_START); + root.setWidth(100); + root.setHeight(100); + + var root_child0 = Yoga.Node.create(); + root_child0.setAlignItems(Yoga.ALIGN_FLEX_START); + root_child0.setWidth(50); + root_child0.setHeight(20); + root_child0.setMeasureFunc(function() {}); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(); + root_child1.setAlignItems(Yoga.ALIGN_FLEX_START); + root_child1.setWidth(50); + root_child1.setHeight(20); + root_child1.setMeasureFunc(function() {}); + root.insertChild(root_child1, 0); + + root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR); + + let dirtied = 0; + root_child0.setDirtiedFunc(function() { + dirtied++; + }); + + console.assert(0 === dirtied, "0 === dirtied"); + + // dirtied func must NOT be called for descendants. + // NOTE: nodes without a measure function cannot be marked dirty manually, + // but nodes with a measure function can not have children. + // Update the width to dirty the node instead. + root.setWidth(110); + console.assert(0 === dirtied, "0 === dirtied"); + + // dirtied func MUST be called in case of explicit dirtying. + root_child0.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + if (typeof root !== "undefined") + root.freeRecursive(); + + typeof gc !== "undefined" && gc(); + console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")"); +}); + +it("dirtied_reset", function() { + var root = Yoga.Node.create(); + root.setAlignItems(Yoga.ALIGN_FLEX_START); + root.setWidth(100); + root.setHeight(100); + root.setMeasureFunc(function() {}); + + root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR); + + let dirtied = 0; + root.setDirtiedFunc(function() { + dirtied++; + }); + + console.assert(0 === dirtied, "0 === dirtied"); + + // dirtied func MUST be called in case of explicit dirtying. + root.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + // recalculate so the root is no longer dirty + root.calculateLayout(undefined, undefined, Yoga.DIRECTION_LTR); + + root.reset(); + root.setAlignItems(Yoga.ALIGN_FLEX_START); + root.setWidth(100); + root.setHeight(100); + root.setMeasureFunc(function() {}); + + root.markDirty(); + + // dirtied func must NOT be called after reset. + root.markDirty(); + console.assert(1 === dirtied, "1 === dirtied"); + + if (typeof root !== "undefined") + root.freeRecursive(); + + typeof gc !== "undefined" && gc(); + console.assert(0 === Yoga.getInstanceCount(), "0 === Yoga.getInstanceCount() (" + Yoga.getInstanceCount() + ")"); +}); From 307cf09434afed52ee071f74312f168e6639a48f Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Thu, 31 Jan 2019 09:29:12 -0800 Subject: [PATCH 184/189] Adds fixes for react-native-windows UWP (#848) Summary: Specifically, updates the UWP .vcxproj for MSBuild and also exposes the UseLegacyStretchBehaviour API for use with react-native-windows. Pull Request resolved: https://github.com/facebook/yoga/pull/848 Reviewed By: SidharthGuglani Differential Revision: D13848609 Pulled By: davidaurelio fbshipit-source-id: eab046ff3c47e49706f515e209d8aaf750c2198f --- csharp/Facebook.Yoga/Native.cs | 34 ++++++------ csharp/Facebook.Yoga/YogaConfig.cs | 15 +++++- csharp/Facebook.Yoga/YogaNode.Spacing.cs | 50 ++++++++--------- csharp/Facebook.Yoga/YogaNode.cs | 16 +++--- csharp/Facebook.Yoga/YogaValue.cs | 12 ----- csharp/Yoga/Yoga.Universal.vcxproj | 46 ++++++++++------ csharp/Yoga/Yoga.Universal.vcxproj.filters | 62 +++++++++++++++++----- csharp/Yoga/Yoga.vcxproj | 12 ++--- yoga/YGMacros.h | 8 --- yoga/Yoga.cpp | 9 ++-- yoga/Yoga.h | 10 ++-- 11 files changed, 158 insertions(+), 116 deletions(-) diff --git a/csharp/Facebook.Yoga/Native.cs b/csharp/Facebook.Yoga/Native.cs index 02e9399d..7ec1ab18 100644 --- a/csharp/Facebook.Yoga/Native.cs +++ b/csharp/Facebook.Yoga/Native.cs @@ -10,12 +10,6 @@ using System.Runtime.InteropServices; namespace Facebook.Yoga { -#if WINDOWS_UWP_ARM - using YogaValueType = IntPtr; -#else - using YogaValueType = YogaValue; -#endif - internal static class Native { #if (UNITY_IOS && !UNITY_EDITOR) || __IOS__ @@ -74,6 +68,14 @@ namespace Facebook.Yoga [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern bool YGConfigGetUseWebDefaults(YGConfigHandle config); + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + public static extern void YGConfigSetUseLegacyStretchBehaviour( + YGConfigHandle config, + bool useLegacyStretchBehavior); + + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + public static extern bool YGConfigGetUseLegacyStretchBehaviour(YGConfigHandle config); + [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGConfigSetPointScaleFactor( YGConfigHandle config, @@ -226,7 +228,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetFlexBasisAuto(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetFlexBasis(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetFlexBasis(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetWidth(YGNodeHandle node, float width); @@ -238,7 +240,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetWidthAuto(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetWidth(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetWidth(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetHeight(YGNodeHandle node, float height); @@ -250,7 +252,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetHeightAuto(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetHeight(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetHeight(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetMinWidth(YGNodeHandle node, float minWidth); @@ -259,7 +261,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetMinWidthPercent(YGNodeHandle node, float minWidth); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetMinWidth(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetMinWidth(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetMinHeight(YGNodeHandle node, float minHeight); @@ -268,7 +270,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetMinHeightPercent(YGNodeHandle node, float minHeight); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetMinHeight(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetMinHeight(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetMaxWidth(YGNodeHandle node, float maxWidth); @@ -277,7 +279,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetMaxWidthPercent(YGNodeHandle node, float maxWidth); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetMaxWidth(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetMaxWidth(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetMaxHeight(YGNodeHandle node, float maxHeight); @@ -286,7 +288,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetMaxHeightPercent(YGNodeHandle node, float maxHeight); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetMaxHeight(YGNodeHandle node); + public static extern YogaValue YGNodeStyleGetMaxHeight(YGNodeHandle node); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetAspectRatio(YGNodeHandle node, float aspectRatio); @@ -305,7 +307,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetPositionPercent(YGNodeHandle node, YogaEdge edge, float position); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge); + public static extern YogaValue YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetMargin(YGNodeHandle node, YogaEdge edge, float margin); @@ -317,7 +319,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetMarginAuto(YGNodeHandle node, YogaEdge edge); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge); + public static extern YogaValue YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetPadding(YGNodeHandle node, YogaEdge edge, float padding); @@ -326,7 +328,7 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetPaddingPercent(YGNodeHandle node, YogaEdge edge, float padding); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] - public static extern YogaValueType YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge); + public static extern YogaValue YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge); [DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern void YGNodeStyleSetBorder(YGNodeHandle node, YogaEdge edge, float border); diff --git a/csharp/Facebook.Yoga/YogaConfig.cs b/csharp/Facebook.Yoga/YogaConfig.cs index 7f175725..b8e58e09 100644 --- a/csharp/Facebook.Yoga/YogaConfig.cs +++ b/csharp/Facebook.Yoga/YogaConfig.cs @@ -1,4 +1,4 @@ -/** +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -117,6 +117,19 @@ namespace Facebook.Yoga } } + public bool UseLegacyStretchBehaviour + { + get + { + return Native.YGConfigGetUseLegacyStretchBehaviour(_ygConfig); + } + + set + { + Native.YGConfigSetUseLegacyStretchBehaviour(_ygConfig, value); + } + } + public float PointScaleFactor { set diff --git a/csharp/Facebook.Yoga/YogaNode.Spacing.cs b/csharp/Facebook.Yoga/YogaNode.Spacing.cs index df9157c9..d3a8f864 100644 --- a/csharp/Facebook.Yoga/YogaNode.Spacing.cs +++ b/csharp/Facebook.Yoga/YogaNode.Spacing.cs @@ -1,4 +1,4 @@ -/** +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -13,7 +13,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Left)); + return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Left); } set @@ -26,7 +26,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Top)); + return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Top); } set @@ -39,7 +39,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Right)); + return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Right); } set @@ -52,7 +52,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Bottom)); + return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Bottom); } set @@ -65,7 +65,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Start)); + return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Start); } set @@ -78,7 +78,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.End)); + return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.End); } set @@ -103,7 +103,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Left)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Left); } set @@ -116,7 +116,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Top)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Top); } set @@ -129,7 +129,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Right)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Right); } set @@ -142,7 +142,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Bottom)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Bottom); } set @@ -155,7 +155,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Start)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Start); } set @@ -168,7 +168,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.End)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.End); } set @@ -181,7 +181,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Horizontal)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Horizontal); } set @@ -194,7 +194,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Vertical)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Vertical); } set @@ -207,7 +207,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.All)); + return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.All); } set @@ -236,7 +236,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Left)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Left); } set @@ -249,7 +249,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Top)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Top); } set @@ -262,7 +262,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Right)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Right); } set @@ -275,7 +275,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Bottom)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Bottom); } set @@ -288,7 +288,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Start)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Start); } set @@ -301,7 +301,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.End)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.End); } set @@ -314,7 +314,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Horizontal)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Horizontal); } set @@ -327,7 +327,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Vertical)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Vertical); } set @@ -340,7 +340,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.All)); + return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.All); } set diff --git a/csharp/Facebook.Yoga/YogaNode.cs b/csharp/Facebook.Yoga/YogaNode.cs index b1f30b22..f681ec89 100644 --- a/csharp/Facebook.Yoga/YogaNode.cs +++ b/csharp/Facebook.Yoga/YogaNode.cs @@ -1,4 +1,4 @@ -/** +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -271,7 +271,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetFlexBasis(_ygNode)); + return Native.YGNodeStyleGetFlexBasis(_ygNode); } set @@ -295,7 +295,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetWidth(_ygNode)); + return Native.YGNodeStyleGetWidth(_ygNode); } set @@ -319,7 +319,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetHeight(_ygNode)); + return Native.YGNodeStyleGetHeight(_ygNode); } set @@ -343,7 +343,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMaxWidth(_ygNode)); + return Native.YGNodeStyleGetMaxWidth(_ygNode); } set @@ -363,7 +363,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMaxHeight(_ygNode)); + return Native.YGNodeStyleGetMaxHeight(_ygNode); } set @@ -383,7 +383,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMinWidth(_ygNode)); + return Native.YGNodeStyleGetMinWidth(_ygNode); } set @@ -403,7 +403,7 @@ namespace Facebook.Yoga { get { - return YogaValue.MarshalValue(Native.YGNodeStyleGetMinHeight(_ygNode)); + return Native.YGNodeStyleGetMinHeight(_ygNode); } set diff --git a/csharp/Facebook.Yoga/YogaValue.cs b/csharp/Facebook.Yoga/YogaValue.cs index aca8882e..e249828d 100644 --- a/csharp/Facebook.Yoga/YogaValue.cs +++ b/csharp/Facebook.Yoga/YogaValue.cs @@ -91,17 +91,5 @@ namespace Facebook.Yoga { return Point(pointValue); } - -#if WINDOWS_UWP_ARM - internal static YogaValue MarshalValue(IntPtr ptr) - { - return Marshal.PtrToStructure(ptr); - } -#else - internal static YogaValue MarshalValue(YogaValue value) - { - return value; - } -#endif } } diff --git a/csharp/Yoga/Yoga.Universal.vcxproj b/csharp/Yoga/Yoga.Universal.vcxproj index 43d62b17..1c956466 100644 --- a/csharp/Yoga/Yoga.Universal.vcxproj +++ b/csharp/Yoga/Yoga.Universal.vcxproj @@ -1,4 +1,4 @@ - + @@ -33,47 +33,47 @@ Yoga true Windows Store - 10.0.10586.0 - 10.0.10240.0 + 10.0.14393.0 + 10.0.14393.0 10.0 DynamicLibrary true - v140 + v141 Unicode DynamicLibrary true - v140 + v141 Unicode DynamicLibrary false - v140 + v141 true Unicode DynamicLibrary false - v140 + v141 true Unicode DynamicLibrary true - v140 + v141 Unicode DynamicLibrary false - v140 + v141 true Unicode @@ -116,7 +116,7 @@ true bin\Universal\$(PlatformTarget)\$(Configuration)\ - obj\$(PlatformTarget)\$(Configuration)\ + obj\Universal\$(PlatformTarget)\$(Configuration)\ yoga @@ -242,19 +242,31 @@ + + - + + - + + + + + - - - - + + + + + + + + + false @@ -284,4 +296,4 @@ - \ No newline at end of file + diff --git a/csharp/Yoga/Yoga.Universal.vcxproj.filters b/csharp/Yoga/Yoga.Universal.vcxproj.filters index 84cee3aa..697d52c1 100644 --- a/csharp/Yoga/Yoga.Universal.vcxproj.filters +++ b/csharp/Yoga/Yoga.Universal.vcxproj.filters @@ -21,22 +21,40 @@ Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files Header Files - + Header Files - + Header Files - + Header Files - + + Header Files + + + Header Files + + Header Files @@ -47,16 +65,34 @@ Source Files - - Source Files - - - Source Files - Source Files - + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + Source Files @@ -65,4 +101,4 @@ Resource Files - \ No newline at end of file + diff --git a/csharp/Yoga/Yoga.vcxproj b/csharp/Yoga/Yoga.vcxproj index 489492cb..5899a0db 100755 --- a/csharp/Yoga/Yoga.vcxproj +++ b/csharp/Yoga/Yoga.vcxproj @@ -38,39 +38,39 @@ DynamicLibrary true - v140 + v141 Unicode DynamicLibrary true - v140 + v141 Unicode DynamicLibrary false - v140 + v141 true Unicode DynamicLibrary false - v140 + v141 true Unicode DynamicLibrary true - v140 + v141 Unicode DynamicLibrary false - v140 + v141 true Unicode diff --git a/yoga/YGMacros.h b/yoga/YGMacros.h index 0e131902..9c2989ac 100644 --- a/yoga/YGMacros.h +++ b/yoga/YGMacros.h @@ -20,14 +20,6 @@ #define WIN_EXPORT #endif -#ifdef WINARMDLL -#define WIN_STRUCT(type) type* -#define WIN_STRUCT_REF(value) &value -#else -#define WIN_STRUCT(type) type -#define WIN_STRUCT_REF(value) value -#endif - #ifdef NS_ENUM // Cannot use NSInteger as NSInteger has a different size than int (which is the // default type of a enum). Therefor when linking the Yoga C library into obj-c diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 0d576d59..f60a153e 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -602,12 +602,12 @@ inline detail::CompactValue Value::create(float) { template struct DimensionProp { template - static WIN_STRUCT(YGValue) get(YGNodeRef node) { + static YGValue get(YGNodeRef node) { YGValue value = (node->getStyle().*P)[idx]; if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { value.value = YGUndefined; } - return WIN_STRUCT_REF(value); + return value; } template @@ -690,13 +690,12 @@ struct DimensionProp { } \ } \ \ - WIN_STRUCT(type) \ - YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ + type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ YGValue value = node->getStyle().instanceName[edge]; \ if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \ value.value = YGUndefined; \ } \ - return WIN_STRUCT_REF(value); \ + return value; \ } #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ diff --git a/yoga/Yoga.h b/yoga/Yoga.h index b15f8bb2..214c5f69 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -140,11 +140,11 @@ YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node); void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc); YGPrintFunc YGNodeGetPrintFunc(YGNodeRef node); void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc); -bool YGNodeGetHasNewLayout(YGNodeRef node); -void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout); +WIN_EXPORT bool YGNodeGetHasNewLayout(YGNodeRef node); +WIN_EXPORT void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout); YGNodeType YGNodeGetNodeType(YGNodeRef node); void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType); -bool YGNodeIsDirty(YGNodeRef node); +WIN_EXPORT bool YGNodeIsDirty(YGNodeRef node); bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node); WIN_EXPORT void YGNodeStyleSetDirection( @@ -227,8 +227,8 @@ WIN_EXPORT void YGNodeStyleSetPositionPercent( const YGNodeRef node, const YGEdge edge, const float position); -WIN_EXPORT WIN_STRUCT(YGValue) - YGNodeStyleGetPosition(const YGNodeRef node, const YGEdge edge); +WIN_EXPORT YGValue +YGNodeStyleGetPosition(const YGNodeRef node, const YGEdge edge); WIN_EXPORT void YGNodeStyleSetMargin( const YGNodeRef node, From 719fa3cca3d7282293d048fcfadda01ec22fe35c Mon Sep 17 00:00:00 2001 From: Diego Muracciole Date: Fri, 1 Feb 2019 02:52:21 -0800 Subject: [PATCH 185/189] Add react-pdf to open source adoption list Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/857 Reviewed By: SidharthGuglani Differential Revision: D13915577 Pulled By: davidaurelio fbshipit-source-id: 55a9cbe96712c4fe7475665c907f650b4b2a8fb3 --- website/src/pages/index.js | 8 ++++++++ website/src/pages/logos/reactpdf.png | Bin 0 -> 87536 bytes 2 files changed, 8 insertions(+) create mode 100644 website/src/pages/logos/reactpdf.png diff --git a/website/src/pages/index.js b/website/src/pages/index.js index ad53ce16..db4257cf 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -18,6 +18,7 @@ import './index.css'; import ReactNativeLogo from './logos/reactnative.png'; import LithoLogo from './logos/litho.png'; import ComponentKitLogo from './logos/componentkit.png'; +import ReactPDFLogo from './logos/reactpdf.png'; import Link from 'gatsby-link'; import Footer from '../components/Footer'; @@ -143,6 +144,13 @@ const AboutSectionOne = () => (

React Native

+ + +

React-PDF

+
); diff --git a/website/src/pages/logos/reactpdf.png b/website/src/pages/logos/reactpdf.png new file mode 100644 index 0000000000000000000000000000000000000000..d24d81c5e261d15b785ce2fb3dee69485cbabd14 GIT binary patch literal 87536 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 ^~ng7SjPr0(^IY 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

-zpdKOAeJF70w!I;(-p=x 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 bIgbRm7=EmiO}s7xAYXTNjc=i}?W6t&O2;_^ literal 0 HcmV?d00001 From 0d026bd1a062563c16ba8dc13ca073b663950ba5 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 1 Feb 2019 03:31:12 -0800 Subject: [PATCH 186/189] Marker for measure callbacks Summary: @public Wraps measure callbacks with a marker. Reviewed By: SidharthGuglani Differential Revision: D13896745 fbshipit-source-id: d6e14fe93f666b06516be1aef7f8e1bfe45440a7 --- tests/InstrumentationTest.cpp | 18 ++++++++++++++++++ yoga/YGMarker.h | 24 +++++++++++++++++++----- yoga/Yoga.cpp | 10 ++++++++-- yoga/instrumentation.h | 26 +++++++++++++++++++++----- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index 585073ff..07053bff 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -197,6 +197,20 @@ TEST_F(MarkerTest, layout_marker_has_max_measure_cache) { (YGMarkerLayoutData{.layouts = 3, .measures = 3, .maxMeasureCache = 7})); } +TEST_F(MarkerTest, measure_functions_get_wrapped) { + auto root = makeNode(); + YGNodeSetMeasureFunc( + root.get(), [](YGNodeRef, float, YGMeasureMode, float, YGMeasureMode) { + return YGSize{}; + }); + + calculateLayout(root); + auto& markerCookie = findLastMarker(YGMarkerMeasure); + + ASSERT_EQ(markerCookie.start.marker, YGMarkerMeasure) + << "have " << markerCookies.size() << " recorded markers"; +} + void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, @@ -218,6 +232,8 @@ void MarkerTest::endMarker( case YGMarkerLayout: cookie->end.markerData.layout = *marker::data(data); break; + case YGMarkerMeasure: + break; }; } @@ -245,6 +261,8 @@ const char* markerTypeName(YGMarker type) { switch (type) { case YGMarkerLayout: return "YGMarkerLayout"; + case YGMarkerMeasure: + return "YGMarkerMeasure"; } } diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 63f2c40f..385ee9cf 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -15,6 +15,7 @@ typedef struct YGConfig* YGConfigRef; typedef YG_ENUM_BEGIN(YGMarker){ YGMarkerLayout, + YGMarkerMeasure, } YG_ENUM_END(YGMarker); typedef struct { @@ -25,8 +26,13 @@ typedef struct { int cachedMeasures; } YGMarkerLayoutData; +typedef struct { + bool _unused; +} YGMarkerNoData; + typedef union { YGMarkerLayoutData* layout; + YGMarkerNoData* noData; } YGMarkerData; typedef struct { @@ -55,16 +61,24 @@ struct MarkerData; template <> struct MarkerData { using type = YGMarkerLayoutData; + static type*& get(YGMarkerData& d) { + return d.layout; + } +}; + +template <> +struct MarkerData { + using type = YGMarkerNoData; + static type*& get(YGMarkerData& d) { + return d.noData; + } }; } // namespace detail template -typename detail::MarkerData::type* data(YGMarkerData) = delete; - -template <> -inline YGMarkerLayoutData* data(YGMarkerData d) { - return d.layout; +typename detail::MarkerData::type* data(YGMarkerData d) { + return detail::MarkerData::get(d); } } // namespace marker diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index f60a153e..eac63d9c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1688,8 +1688,14 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( YGDimensionHeight); } else { // Measure the text under the current constraints. - const YGSize measuredSize = node->getMeasure()( - node, innerWidth, widthMeasureMode, innerHeight, heightMeasureMode); + const YGSize measuredSize = marker::MarkerSection::wrap( + node, + node->getMeasure(), + node, + innerWidth, + widthMeasureMode, + innerHeight, + heightMeasureMode); node->setLayoutMeasuredDimension( YGNodeBoundAxis( diff --git a/yoga/instrumentation.h b/yoga/instrumentation.h index 670fc2bd..5cc544c5 100644 --- a/yoga/instrumentation.h +++ b/yoga/instrumentation.h @@ -14,15 +14,24 @@ namespace marker { template class MarkerSection { +private: + using Data = detail::MarkerData; + public: MarkerSection(YGNodeRef node) : MarkerSection{node, node->getConfig()} {} ~MarkerSection() { if (endMarker_) { - endMarker_(MarkerType, node_, {&data}, userData_); + endMarker_(MarkerType, node_, markerData(&data), userData_); } } - typename detail::MarkerData::type data = {}; + typename Data::type data = {}; + + template + static Ret wrap(YGNodeRef node, Ret (*fn)(Args...), Args... args) { + MarkerSection section{node}; + return fn(std::forward(args)...); + } private: decltype(YGMarkerCallbacks{}.endMarker) endMarker_; @@ -34,9 +43,16 @@ private: MarkerSection(YGNodeRef node, YGMarkerCallbacks* callbacks) : endMarker_{callbacks ? callbacks->endMarker : nullptr}, node_{node}, - userData_{callbacks && callbacks->startMarker - ? callbacks->startMarker(MarkerType, node, {&data}) - : nullptr} {} + userData_{ + callbacks && callbacks->startMarker + ? callbacks->startMarker(MarkerType, node, markerData(&data)) + : nullptr} {} + + static YGMarkerData markerData(typename Data::type* d) { + YGMarkerData markerData = {}; + Data::get(markerData) = d; + return markerData; + } }; } // namespace marker From 5121fef5d8da8b68f0da6e18d5149f32ed8215d0 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 1 Feb 2019 03:31:12 -0800 Subject: [PATCH 187/189] Marker for baseline callbacks Summary: @public Wraps baseline callbacks with a marker. Reviewed By: SidharthGuglani Differential Revision: D13896861 fbshipit-source-id: 848ec697977a0a68b9943f1159f6562d54724f89 --- tests/InstrumentationTest.cpp | 18 ++++++++++++++++++ yoga/YGMarker.h | 10 ++++++++-- yoga/Yoga.cpp | 4 +++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tests/InstrumentationTest.cpp b/tests/InstrumentationTest.cpp index 07053bff..435aabc7 100644 --- a/tests/InstrumentationTest.cpp +++ b/tests/InstrumentationTest.cpp @@ -211,6 +211,21 @@ TEST_F(MarkerTest, measure_functions_get_wrapped) { << "have " << markerCookies.size() << " recorded markers"; } +TEST_F(MarkerTest, baseline_functions_get_wrapped) { + auto root = makeNode(); + auto child = addChild(root); + YGNodeSetBaselineFunc( + child.get(), [](YGNodeRef, float, float) { return 0.0f; }); + YGNodeStyleSetFlexDirection(root.get(), YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root.get(), YGAlignBaseline); + + calculateLayout(root); + auto& markerCookie = findLastMarker(YGMarkerBaselineFn); + + ASSERT_EQ(markerCookie.start.marker, YGMarkerBaselineFn) + << "have " << markerCookies.size() << " recorded markers"; +} + void* MarkerTest::startMarker( YGMarker marker, YGNodeRef node, @@ -233,6 +248,7 @@ void MarkerTest::endMarker( cookie->end.markerData.layout = *marker::data(data); break; case YGMarkerMeasure: + case YGMarkerBaselineFn: break; }; } @@ -263,6 +279,8 @@ const char* markerTypeName(YGMarker type) { return "YGMarkerLayout"; case YGMarkerMeasure: return "YGMarkerMeasure"; + case YGMarkerBaselineFn: + return "YGMarkerBaselineFn"; } } diff --git a/yoga/YGMarker.h b/yoga/YGMarker.h index 385ee9cf..25362ff5 100644 --- a/yoga/YGMarker.h +++ b/yoga/YGMarker.h @@ -16,6 +16,7 @@ typedef struct YGConfig* YGConfigRef; typedef YG_ENUM_BEGIN(YGMarker){ YGMarkerLayout, YGMarkerMeasure, + YGMarkerBaselineFn, } YG_ENUM_END(YGMarker); typedef struct { @@ -66,14 +67,19 @@ struct MarkerData { } }; -template <> -struct MarkerData { +struct NoMarkerData { using type = YGMarkerNoData; static type*& get(YGMarkerData& d) { return d.noData; } }; +template <> +struct MarkerData : NoMarkerData {}; + +template <> +struct MarkerData : NoMarkerData {}; + } // namespace detail template diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index eac63d9c..3f65092b 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1074,7 +1074,9 @@ static inline YGAlign YGNodeAlignItem( static float YGBaseline(const YGNodeRef node) { if (node->getBaseline() != nullptr) { - const float baseline = node->getBaseline()( + const float baseline = marker::MarkerSection::wrap( + node, + node->getBaseline(), node, node->getLayout().measuredDimensions[YGDimensionWidth], node->getLayout().measuredDimensions[YGDimensionHeight]); From 80d527814e5ae7234ab26b203aed9408c5e85c1d Mon Sep 17 00:00:00 2001 From: Pablo Sichert Date: Fri, 1 Feb 2019 05:07:08 -0800 Subject: [PATCH 188/189] Allow Yoga Pod to be built on any platform (#821) Summary: Currently the CocoaPod for Yoga explicitly states platform requirements. Since the Yoga implementation doesn't depend on any platform features, it would be safe to build it on any platform. That can be configured by omitting the `platform`/`platforms` key: > The platform on which this Pod is supported. Leaving this blank means the Pod is supported on all platforms. > > http://guides.cocoapods.org/syntax/podspec.html#platform Among others, that would allow to use the pod in macOS projects Pull Request resolved: https://github.com/facebook/yoga/pull/821 Reviewed By: passy Differential Revision: D13848153 Pulled By: davidaurelio fbshipit-source-id: 5a3e81d81ca97b120f2711bafd3c8b9e0c3f8088 --- Yoga.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Yoga.podspec b/Yoga.podspec index 43e43ab4..81cd79d3 100644 --- a/Yoga.podspec +++ b/Yoga.podspec @@ -19,7 +19,7 @@ Pod::Spec.new do |spec| :git => 'https://github.com/facebook/yoga.git', :tag => spec.version.to_s, } - spec.platforms = { :ios => "8.0", :tvos => "10.0" } + spec.platforms = { :ios => "4.3", :osx => "10.7", :tvos => "10.0", :watchos => "2.0" } spec.module_name = 'yoga' spec.requires_arc = false spec.pod_target_xcconfig = { @@ -34,6 +34,6 @@ Pod::Spec.new do |spec| '-fPIC' ] spec.source_files = 'yoga/**/*.{c,h,cpp}' - spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros}.h' + spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h' end From d3e02b15fa925aab29dfe4ba7b93bc4cd7ff39cc Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Fri, 1 Feb 2019 10:37:40 -0800 Subject: [PATCH 189/189] Compile JNI bindings with `-Os` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public Compiles Yoga’s JNI bindings with `-Os`. This doesn’t have perf implications. Compressed APK size ~ -4KB, uncompressed ~ -40KB Reviewed By: astreet Differential Revision: D13862404 fbshipit-source-id: 43402478ab2b932f0ca79711c35dfb507bab818b --- java/BUCK | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/BUCK b/java/BUCK index 87a44ad6..59a1613b 100644 --- a/java/BUCK +++ b/java/BUCK @@ -17,7 +17,7 @@ yoga_cxx_library( "-fPIC", "-Wall", "-Werror", - "-O3", + "-Os", "-std=c++11", ], platforms = ANDROID,