mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
33
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc04bf3d96 | ||
|
|
8e34e7bd5f | ||
|
|
68f6799b7c | ||
|
|
2c130e6a9f | ||
|
|
21423bdf22 | ||
|
|
e5332504cc | ||
|
|
292f035ae8 | ||
|
|
a6c4ae0e75 | ||
|
|
e4b5e9ef85 | ||
|
|
732831dc27 | ||
|
|
b150fdfdce | ||
|
|
73f2007679 | ||
|
|
da2a8b365c | ||
|
|
143ecf4c62 | ||
|
|
c8d6cb9e49 | ||
|
|
0661c6f254 | ||
|
|
5f4a5388ac | ||
|
|
445dac2743 | ||
|
|
2d230bee78 | ||
|
|
382abb4b45 | ||
|
|
b0e4b89b58 | ||
|
|
0b8525847f | ||
|
|
09a923599e | ||
|
|
e7b7951c96 | ||
|
|
a91d0d8c35 | ||
|
|
47206fdd3c | ||
|
|
b02efd9e96 | ||
|
|
31894136f4 | ||
|
|
9b6639ad12 | ||
|
|
11f838f349 | ||
|
|
34787cc0eb | ||
|
|
d40bea925f | ||
|
|
692d3f72fb |
+1
-2
@@ -1,13 +1,12 @@
|
||||
|
||||
[android]
|
||||
target = android-26
|
||||
target = Google Inc.:Google APIs:23
|
||||
|
||||
[download]
|
||||
max_number_of_retries = 3
|
||||
|
||||
[maven_repositories]
|
||||
central = https://repo1.maven.org/maven2
|
||||
google = https://maven.google.com
|
||||
|
||||
[alias]
|
||||
rntester = //RNTester/android/app:app
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Circle CI
|
||||
|
||||
This directory is home to the Circle CI configuration file. Circle is our continuous integration service provider. You can see the overall status of React Native's builds at https://circleci.com/gh/facebook/react-native
|
||||
|
||||
You may also see an individual PR's build status by scrolling down to the Checks section in the PR.
|
||||
@@ -1,691 +0,0 @@
|
||||
aliases:
|
||||
# Cache Management
|
||||
- &restore-yarn-cache
|
||||
keys:
|
||||
- v1-yarn-cache-{{ arch }}-{{ checksum "package.json" }}
|
||||
- v1-yarn-cache-{{ arch }}
|
||||
- &save-yarn-cache
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
key: v1-yarn-cache-{{ arch }}-{{ checksum "package.json" }}
|
||||
|
||||
- &restore-node-modules
|
||||
keys:
|
||||
- v2-node-modules-{{ arch }}-{{ checksum "package.json" }}
|
||||
- &save-node-modules
|
||||
paths:
|
||||
- node_modules
|
||||
key: v2-node-modules-{{ arch }}-{{ checksum "package.json" }}
|
||||
|
||||
- &restore-cache-analysis
|
||||
keys:
|
||||
- v1-analysis-dependencies-{{ arch }}-{{ checksum "package.json" }}{{ checksum "bots/package.json" }}
|
||||
- &save-cache-analysis
|
||||
paths:
|
||||
- bots/node_modules
|
||||
- node_modules
|
||||
key: v1-analysis-dependencies-{{ arch }}-{{ checksum "package.json" }}{{ checksum "bots/package.json" }}
|
||||
|
||||
- &restore-cache-android-packages
|
||||
keys:
|
||||
- v1-android-sdkmanager-packages-api-26-alpha-{{ checksum "scripts/.tests.env" }}
|
||||
- &save-cache-android-packages
|
||||
paths:
|
||||
- /opt/android/sdk
|
||||
key: v1-android-sdkmanager-packages-api-26-alpha-{{ checksum "scripts/.tests.env" }}
|
||||
|
||||
- &restore-cache-gradle
|
||||
keys:
|
||||
- v1-gradle-{{ arch }}-{{ .Branch }}-{{ checksum "build.gradle" }}-{{ checksum "ReactAndroid/build.gradle" }}
|
||||
# Fallback in case checksum fails
|
||||
- v1-gradle-{{ arch }}-{{ .Branch }}-{{ checksum "build.gradle" }}-
|
||||
- v1-gradle-{{ arch }}-{{ .Branch }}-
|
||||
# Fallback in case this is a first-time run on a fork
|
||||
- v1-gradle-{{ arch }}-master-
|
||||
- &save-cache-gradle
|
||||
paths:
|
||||
- ~/.gradle
|
||||
key: v1-gradle-{{ arch }}-{{ .Branch }}-{{ checksum "build.gradle" }}-{{ checksum "ReactAndroid/build.gradle" }}
|
||||
|
||||
- &restore-cache-apt
|
||||
keys:
|
||||
- v1-apt-{{ .Branch }}-{{ checksum "scripts/circleci/apt-get-android-deps.sh" }}
|
||||
# Fallback in case this is a first-time run on a fork
|
||||
- v1-apt-master-{{ checksum "scripts/circleci/apt-get-android-deps.sh" }}
|
||||
- &save-cache-apt
|
||||
paths:
|
||||
- ~/vendor/apt
|
||||
key: v1-apt-{{ .Branch }}-{{ checksum "scripts/circleci/apt-get-android-deps.sh" }}
|
||||
|
||||
- &restore-cache-ndk
|
||||
keys:
|
||||
- v3-android-ndk-{{ arch }}-r10e-{{ checksum "scripts/android-setup.sh" }}
|
||||
- &save-cache-ndk
|
||||
paths:
|
||||
- /opt/ndk
|
||||
key: v3-android-ndk-{{ arch }}-r10e-{{ checksum "scripts/android-setup.sh" }}
|
||||
|
||||
- &restore-cache-buck
|
||||
keys:
|
||||
- v3-buck-{{ arch }}-v2018.03.26.01
|
||||
- &save-cache-buck
|
||||
paths:
|
||||
- ~/buck
|
||||
- ~/okbuck
|
||||
key: v3-buck-{{ arch }}-v2018.03.26.01
|
||||
|
||||
- &restore-cache-watchman
|
||||
keys:
|
||||
- v1-watchman-{{ arch }}-v4.9.0
|
||||
- &save-cache-watchman
|
||||
paths:
|
||||
- ~/watchman
|
||||
key: v1-watchman-{{ arch }}-v4.9.0
|
||||
|
||||
- &restore-cache-gradle-downloads
|
||||
keys:
|
||||
- v1-gradle-{{ arch }}-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }}
|
||||
- v1-gradle-{{ arch }}-
|
||||
- &save-cache-gradle-downloads
|
||||
paths:
|
||||
- ~/.gradle
|
||||
- ReactAndroid/build/downloads
|
||||
- ReactAndroid/build/third-party-ndk
|
||||
key: v1-gradle-{{ arch }}-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }}
|
||||
|
||||
# Branch Filtering
|
||||
- &filter-only-master-stable
|
||||
branches:
|
||||
only:
|
||||
- /.*-stable/
|
||||
- master
|
||||
|
||||
- &filter-only-stable
|
||||
branches:
|
||||
only:
|
||||
- /.*-stable/
|
||||
|
||||
- &filter-ignore-gh-pages
|
||||
branches:
|
||||
ignore: gh-pages
|
||||
|
||||
- &filter-ignore-master-stable
|
||||
branches:
|
||||
ignore:
|
||||
- master
|
||||
- /.*-stable/
|
||||
- gh-pages
|
||||
|
||||
# Dependency Management
|
||||
- &install-ndk
|
||||
name: Install Android NDK
|
||||
command: source scripts/android-setup.sh && getAndroidNDK
|
||||
|
||||
- &yarn
|
||||
|
|
||||
yarn install --non-interactive --cache-folder ~/.cache/yarn
|
||||
|
||||
- &install-yarn
|
||||
name: Install Yarn
|
||||
command: |
|
||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
sudo apt-get update && sudo apt-get install yarn
|
||||
|
||||
- &install-node-dependencies
|
||||
|
|
||||
npm install --no-package-lock --no-spin --no-progress
|
||||
|
||||
- &install-buck
|
||||
name: Install BUCK
|
||||
command: |
|
||||
if [[ ! -e ~/buck ]]; then
|
||||
git clone https://github.com/facebook/buck.git ~/buck --branch v2018.03.26.01 --depth=1
|
||||
fi
|
||||
cd ~/buck && ant
|
||||
buck --version
|
||||
# Install related tooling
|
||||
if [[ ! -e ~/okbuck ]]; then
|
||||
git clone https://github.com/uber/okbuck.git ~/okbuck --depth=1
|
||||
fi
|
||||
mkdir -p ~/react-native/tooling/junit
|
||||
cp -R ~/okbuck/tooling/junit/* ~/react-native/tooling/junit/.
|
||||
|
||||
|
||||
- &install-node
|
||||
name: Install Node
|
||||
command: |
|
||||
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
- &create-ndk-directory
|
||||
name: Create Android NDK Directory
|
||||
command: |
|
||||
if [[ ! -e /opt/ndk ]]; then
|
||||
sudo mkdir /opt/ndk
|
||||
fi
|
||||
sudo chown ${USER:=$(/usr/bin/id -run)}:$USER /opt/ndk
|
||||
|
||||
# CircleCI does not support interpolating env variables in the environment
|
||||
# https://circleci.com/docs/2.0/env-vars/#interpolating-environment-variables-to-set-other-environment-variables
|
||||
- &configure-android-path
|
||||
name: Configure Environment Variables
|
||||
command: |
|
||||
echo 'export PATH=${ANDROID_NDK}:~/react-native/gradle-2.9/bin:~/buck/bin:$PATH' >> $BASH_ENV
|
||||
source $BASH_ENV
|
||||
|
||||
- &install-android-packages
|
||||
name: Install Android SDK Packages
|
||||
command: source scripts/android-setup.sh && getAndroidPackages
|
||||
|
||||
- &install-android-build-dependencies
|
||||
name: Install Android Build Dependencies
|
||||
command: ./scripts/circleci/apt-get-android-deps.sh
|
||||
|
||||
- &validate-android-sdk
|
||||
name: Validate Android SDK Install
|
||||
command: ./scripts/validate-android-sdk.sh
|
||||
|
||||
- &validate-android-test-env
|
||||
name: Validate Android Test Environment
|
||||
command: ./scripts/validate-android-test-env.sh
|
||||
|
||||
# Test Definitions
|
||||
- &run-js-tests
|
||||
name: JavaScript Test Suite
|
||||
command: yarn test-ci
|
||||
|
||||
# eslint sometimes runs into trouble generating the reports
|
||||
- &run-lint-checks
|
||||
name: Lint code
|
||||
command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ~/react-native/reports/junit/eslint/results.xml
|
||||
when: always
|
||||
|
||||
- &run-flow-checks
|
||||
name: Check for errors in code using Flow
|
||||
command: yarn flow check
|
||||
when: always
|
||||
|
||||
- &run-sanity-checks
|
||||
name: Sanity checks
|
||||
command: |
|
||||
./scripts/circleci/check_license.sh
|
||||
./scripts/circleci/check_cache.sh
|
||||
when: always
|
||||
|
||||
- &gradle-download-deps
|
||||
name: Download C++ Dependencies
|
||||
command: ./scripts/circleci/gradle_download_deps.sh
|
||||
|
||||
- &build-android-app
|
||||
name: Build Android App
|
||||
command: |
|
||||
buck build ReactAndroid/src/main/java/com/facebook/react
|
||||
buck build ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
|
||||
- &create-avd
|
||||
name: Create Android Virtual Device
|
||||
command: source scripts/android-setup.sh && createAVD
|
||||
|
||||
- &launch-avd
|
||||
name: Launch Android Virtual Device in Background
|
||||
command: source scripts/android-setup.sh && launchAVD
|
||||
background: true
|
||||
|
||||
- &wait-for-avd
|
||||
name: Wait for Android Virtual Device
|
||||
command: source scripts/android-setup.sh && waitForAVD
|
||||
|
||||
- &build-js-bundle
|
||||
name: Build JavaScript Bundle
|
||||
command: node local-cli/cli.js bundle --max-workers 2 --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
|
||||
|
||||
- &compile-native-libs
|
||||
name: Compile Native Libs for Unit and Integration Tests
|
||||
command: ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=$BUILD_THREADS -Pcom.android.build.threadPoolSize=1
|
||||
no_output_timeout: 6m
|
||||
|
||||
- &run-android-unit-tests
|
||||
name: Run Unit Tests
|
||||
command: buck test ReactAndroid/src/test/... --config build.threads=$BUILD_THREADS --xml ~/react-native/reports/buck/all-results-raw.xml
|
||||
|
||||
- &run-android-instrumentation-tests
|
||||
name: Run Instrumentation Tests
|
||||
command: |
|
||||
if [[ ! -e ReactAndroid/src/androidTest/assets/AndroidTestBundle.js ]]; then
|
||||
echo "JavaScript bundle missing, cannot run instrumentation tests. Verify build-js-bundle step completed successfully."; exit 1;
|
||||
fi
|
||||
source scripts/android-setup.sh && NO_BUCKD=1 retry3 timeout 300 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=$BUILD_THREADS
|
||||
|
||||
- &collect-android-test-results
|
||||
name: Collect Test Results
|
||||
command: |
|
||||
find . -type f -regex ".*/build/test-results/debug/.*xml" -exec cp {} ~/react-native/reports/build/ \;
|
||||
find . -type f -regex ".*/outputs/androidTest-results/connected/.*xml" -exec cp {} ~/react-native/reports/outputs/ \;
|
||||
find . -type f -regex ".*/buck-out/gen/ReactAndroid/src/test/.*/.*xml" -exec cp {} ~/react-native/reports/buck/ \;
|
||||
./tooling/junit/buck_to_junit.sh ~/react-native/reports/buck/all-results-raw.xml ~/react-native/reports/junit/all-results-junit.xml
|
||||
when: always
|
||||
|
||||
- &setup-artifacts
|
||||
name: Initial Setup
|
||||
command: |
|
||||
mkdir -p ~/react-native/reports/buck/
|
||||
mkdir -p ~/react-native/reports/build/
|
||||
mkdir -p ~/react-native/reports/junit/
|
||||
mkdir -p ~/react-native/reports/outputs/
|
||||
|
||||
- &boot-simulator-iphone
|
||||
name: Boot iPhone Simulator
|
||||
command: xcrun simctl boot "iPhone 5s" || true
|
||||
|
||||
- &boot-simulator-appletv
|
||||
name: Boot Apple TV Simulator
|
||||
command: xcrun simctl boot "Apple TV" || true
|
||||
|
||||
- &run-objc-ios-tests
|
||||
name: iOS Test Suite
|
||||
command: ./scripts/objc-test-ios.sh test
|
||||
|
||||
- &run-objc-tvos-tests
|
||||
name: tvOS Test Suite
|
||||
command: ./scripts/objc-test-tvos.sh test
|
||||
|
||||
- &run-e2e-tests
|
||||
name: End-to-End Test Suite
|
||||
command: node ./scripts/run-ci-e2e-tests.js --ios --tvos --js --retries 3;
|
||||
|
||||
- &run-objc-ios-e2e-tests
|
||||
name: iOS End-to-End Test Suite
|
||||
command: node ./scripts/run-ci-e2e-tests.js --ios --retries 3;
|
||||
|
||||
- &run-objc-tvos-e2e-tests
|
||||
name: tvOS End-to-End Test Suite
|
||||
command: node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3;
|
||||
|
||||
defaults: &defaults
|
||||
working_directory: ~/react-native
|
||||
|
||||
js_defaults: &js_defaults
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
environment:
|
||||
- PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
android_defaults: &android_defaults
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/android:api-26-node8-alpha
|
||||
resource_class: "large"
|
||||
environment:
|
||||
- TERM: "dumb"
|
||||
- ADB_INSTALL_TIMEOUT: 10
|
||||
- _JAVA_OPTIONS: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"
|
||||
- GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError"'
|
||||
- ANDROID_NDK: '/opt/ndk/android-ndk-r10e'
|
||||
- BUILD_THREADS: 2
|
||||
|
||||
macos_defaults: &macos_defaults
|
||||
<<: *defaults
|
||||
macos:
|
||||
xcode: "9.4.0"
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
|
||||
# Set up a Node environment for downstream jobs
|
||||
checkout_code:
|
||||
<<: *js_defaults
|
||||
steps:
|
||||
- checkout
|
||||
- run: *setup-artifacts
|
||||
|
||||
- restore-cache: *restore-yarn-cache
|
||||
- run: *yarn
|
||||
- save-cache: *save-yarn-cache
|
||||
|
||||
# Basic checks against the checkout, cache...
|
||||
- run: *run-sanity-checks
|
||||
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: .
|
||||
|
||||
# Runs JavaScript lint and flow checks.
|
||||
# Currently will fail a PR if lint/flow raises issues.
|
||||
analyze:
|
||||
<<: *js_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: *run-lint-checks
|
||||
- run: *run-flow-checks
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
- store_artifacts:
|
||||
path: ~/react-native/yarn.lock
|
||||
|
||||
# Runs JavaScript tests on Node 8
|
||||
test_javascript:
|
||||
<<: *js_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: *run-js-tests
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Runs unit tests on iOS devices
|
||||
test_ios:
|
||||
<<: *macos_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: *boot-simulator-iphone
|
||||
- run: brew install watchman
|
||||
- run: *run-objc-ios-tests
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Runs unit tests on tvOS devices
|
||||
test_tvos:
|
||||
<<: *macos_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: *boot-simulator-appletv
|
||||
- run: brew install watchman
|
||||
- run: *run-objc-tvos-tests
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Runs end to end tests
|
||||
test_end_to_end:
|
||||
<<: *macos_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: *boot-simulator-iphone
|
||||
|
||||
- run:
|
||||
name: Configure Environment Variables
|
||||
command: |
|
||||
echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV
|
||||
source $BASH_ENV
|
||||
|
||||
- run:
|
||||
name: Install Node 8
|
||||
command: |
|
||||
brew install node@8
|
||||
brew link node@8
|
||||
node -v
|
||||
|
||||
- run: *run-objc-ios-e2e-tests
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Checks podspec
|
||||
test_podspec:
|
||||
<<: *macos_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: ./scripts/process-podspecs.sh
|
||||
|
||||
# Publishes new version onto npm
|
||||
publish_npm_package:
|
||||
<<: *android_defaults
|
||||
steps:
|
||||
# Checkout code so that we can work with `git` in publish.js
|
||||
- checkout
|
||||
|
||||
# Configure Android SDK and related dependencies
|
||||
- run: *configure-android-path
|
||||
- run: *install-android-build-dependencies
|
||||
|
||||
- restore-cache: *restore-cache-android-packages
|
||||
- run: *install-android-packages
|
||||
|
||||
# Install Android NDK
|
||||
- run: *create-ndk-directory
|
||||
- restore-cache: *restore-cache-ndk
|
||||
- run: *install-ndk
|
||||
|
||||
# Fetch dependencies using BUCK
|
||||
- restore-cache: *restore-cache-buck
|
||||
- run: *install-buck
|
||||
|
||||
- run: buck fetch ReactAndroid/src/test/java/com/facebook/react/modules
|
||||
- run: buck fetch ReactAndroid/src/main/java/com/facebook/react
|
||||
- run: buck fetch ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
- run: buck fetch ReactAndroid/src/test/...
|
||||
- run: buck fetch ReactAndroid/src/androidTest/...
|
||||
|
||||
- restore-cache: *restore-cache-gradle-downloads
|
||||
- run: *gradle-download-deps
|
||||
|
||||
- restore-cache: *restore-yarn-cache
|
||||
- run: *yarn
|
||||
|
||||
- run:
|
||||
name: Publish React Native Package
|
||||
command: |
|
||||
echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc
|
||||
git config --global user.email "reactjs-bot@users.noreply.github.com"
|
||||
git config --global user.name "npm Deployment Script"
|
||||
echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc
|
||||
node ./scripts/publish-npm.js
|
||||
|
||||
# Set up an Android environment for downstream jobs
|
||||
test_android:
|
||||
<<: *android_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
# Configure Android SDK and related dependencies
|
||||
- run: *configure-android-path
|
||||
- restore-cache: *restore-cache-apt
|
||||
- run: *install-android-build-dependencies
|
||||
- save-cache: *save-cache-apt
|
||||
|
||||
- restore-cache: *restore-cache-android-packages
|
||||
- run: *install-android-packages
|
||||
- save-cache: *save-cache-android-packages
|
||||
|
||||
- run: *validate-android-sdk
|
||||
|
||||
# Starting emulator in advance as it takes some time to boot.
|
||||
- run: *create-avd
|
||||
- run: *launch-avd
|
||||
|
||||
# Keep configuring Android dependencies while AVD boots up
|
||||
|
||||
# Install Android NDK
|
||||
- run: *create-ndk-directory
|
||||
- restore-cache: *restore-cache-ndk
|
||||
- run: *install-ndk
|
||||
- save-cache: *save-cache-ndk
|
||||
|
||||
# Fetch dependencies using BUCK
|
||||
- restore-cache: *restore-cache-buck
|
||||
- run: *install-buck
|
||||
- save-cache: *save-cache-buck
|
||||
|
||||
- run: *validate-android-test-env
|
||||
|
||||
- run: buck fetch ReactAndroid/src/test/java/com/facebook/react/modules
|
||||
- run: buck fetch ReactAndroid/src/main/java/com/facebook/react
|
||||
- run: buck fetch ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
- run: buck fetch ReactAndroid/src/test/...
|
||||
- run: buck fetch ReactAndroid/src/androidTest/...
|
||||
|
||||
- restore-cache: *restore-cache-gradle-downloads
|
||||
- run: *gradle-download-deps
|
||||
- save-cache: *save-cache-gradle-downloads
|
||||
|
||||
# Build and compile
|
||||
- run: *build-android-app
|
||||
- run: *compile-native-libs
|
||||
|
||||
# Build JavaScript Bundle for instrumentation tests
|
||||
- run: *build-js-bundle
|
||||
|
||||
# Wait for AVD to finish booting before running tests
|
||||
- run: *wait-for-avd
|
||||
|
||||
# Test Suite
|
||||
- run: *run-android-unit-tests
|
||||
- run: *run-android-instrumentation-tests
|
||||
|
||||
# Collect Results
|
||||
- run: *collect-android-test-results
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Analyze pull request and raise any lint/flow issues.
|
||||
# Issues will be posted to the PR itself via GitHub bots.
|
||||
# This workflow should only fail if the bots fail to run.
|
||||
analyze_pr:
|
||||
<<: *js_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- restore-cache: *restore-cache-analysis
|
||||
- run: *yarn
|
||||
- run:
|
||||
name: Install Additional Dependencies
|
||||
command: |
|
||||
if [ -n "$CIRCLE_PR_NUMBER" ]; then
|
||||
yarn add github@0.2.4
|
||||
cd bots
|
||||
yarn install --non-interactive --cache-folder ~/.cache/yarn
|
||||
else
|
||||
echo "Skipping dependency installation."
|
||||
fi
|
||||
- save-cache: *save-cache-analysis
|
||||
|
||||
- run:
|
||||
name: Analyze Pull Request
|
||||
command: |
|
||||
# DANGER_GITHUB_API_TOKEN=React-Linter public_repo access token
|
||||
if [ -n "$CIRCLE_PR_NUMBER" ]; then
|
||||
cd bots && DANGER_GITHUB_API_TOKEN="80aa64c50f38a267e9ba""575d41d528f9c234edb8" yarn danger
|
||||
else
|
||||
echo "Skipping pull request analysis."
|
||||
fi
|
||||
when: always
|
||||
- run:
|
||||
name: Analyze Code
|
||||
command: |
|
||||
# GITHUB_TOKEN=eslint-bot public_repo access token
|
||||
if [ -n "$CIRCLE_PR_NUMBER" ]; then
|
||||
GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" CI_USER=$CIRCLE_PROJECT_USERNAME CI_REPO=$CIRCLE_PROJECT_REPONAME PULL_REQUEST_NUMBER=$CIRCLE_PR_NUMBER scripts/circleci/analyze_code.sh
|
||||
else
|
||||
echo "Skipping code analysis."
|
||||
fi
|
||||
when: always
|
||||
|
||||
# Workflows enables us to run multiple jobs in parallel
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
tests:
|
||||
jobs:
|
||||
|
||||
# Checkout repo and run Yarn
|
||||
- checkout_code:
|
||||
filters: *filter-ignore-gh-pages
|
||||
|
||||
# Run lint, flow, and other checks
|
||||
- analyze:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
# Test JavaScript
|
||||
- test_javascript:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
# Test Android
|
||||
- test_android:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
# Test iOS & tvOS
|
||||
- test_ios:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
- test_tvos:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
# End-to-end tests
|
||||
- test_end_to_end:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
# Only runs on vX.X.X tags if all tests are green
|
||||
- publish_npm_package:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /.*-stable/
|
||||
tags:
|
||||
only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/
|
||||
requires:
|
||||
- test_javascript
|
||||
- test_ios
|
||||
- test_tvos
|
||||
- test_end_to_end
|
||||
- analyze
|
||||
|
||||
# Only runs on PRs
|
||||
analyze:
|
||||
jobs:
|
||||
# Checkout repo and run Yarn
|
||||
- checkout_code:
|
||||
filters: *filter-ignore-master-stable
|
||||
|
||||
# Run code checks
|
||||
- analyze_pr:
|
||||
filters: *filter-ignore-master-stable
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
|
||||
# These tests are flaky or are yet to be fixed. They are placed on their own
|
||||
# workflow to avoid marking benign PRs as broken.
|
||||
# To run them, uncomment the entire block and open a PR (do not merge).
|
||||
# Once a test is fixed, move the test definition to the 'tests' workflow.
|
||||
# disabled_tests:
|
||||
# jobs:
|
||||
# # Checkout repo and run Yarn (pre-req, should succeed)
|
||||
# - checkout_code:
|
||||
# filters: *filter-ignore-gh-pages
|
||||
|
||||
# # The following were DISABLED because they have not run since
|
||||
# # the migration from Travis, and they have broken since then,
|
||||
# # CocoaPods
|
||||
# - test_podspec:
|
||||
# filters: *filter-ignore-gh-pages
|
||||
# requires:
|
||||
# - checkout_code
|
||||
+5
-1
@@ -4,7 +4,11 @@
|
||||
**/main.js
|
||||
Libraries/vendor/**/*
|
||||
Libraries/Renderer/*
|
||||
website/node_modules
|
||||
pr-inactivity-bookmarklet.js
|
||||
question-bookmarklet.js
|
||||
flow/
|
||||
danger/
|
||||
website/core/metadata.js
|
||||
website/core/metadata-blog.js
|
||||
website/src/react-native/docs/
|
||||
website/src/react-native/blog/
|
||||
|
||||
@@ -3,18 +3,19 @@
|
||||
|
||||
"parser": "babel-eslint",
|
||||
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
|
||||
"env": {
|
||||
"es6": true,
|
||||
"jest": true,
|
||||
"jasmine": true,
|
||||
},
|
||||
|
||||
"plugins": [
|
||||
"eslint-comments",
|
||||
"flowtype",
|
||||
"prettier",
|
||||
"react",
|
||||
"react-native",
|
||||
"jest"
|
||||
"react"
|
||||
],
|
||||
|
||||
// Map from global var to bool specifying if it can be redefined
|
||||
@@ -56,15 +57,21 @@
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// Flow Plugin
|
||||
// The following rules are made available via `eslint-plugin-flowtype`
|
||||
"flowtype/define-flow-type": 1,
|
||||
"flowtype/use-flow-type": 1,
|
||||
|
||||
// General
|
||||
"comma-dangle": [1, "always-multiline"], // allow or disallow trailing commas
|
||||
|
||||
"comma-dangle": 0, // disallow trailing commas in object literals
|
||||
"no-cond-assign": 1, // disallow assignment in conditional expressions
|
||||
"no-console": 0, // disallow use of console (off by default in the node environment)
|
||||
"no-const-assign": 2, // disallow assignment to const-declared variables
|
||||
"no-constant-condition": 0, // disallow use of constant expressions in conditions
|
||||
"no-control-regex": 1, // disallow control characters in regular expressions
|
||||
"no-debugger": 1, // disallow use of debugger
|
||||
"no-dupe-keys": 2, // disallow duplicate keys when creating object literals
|
||||
"no-dupe-keys": 1, // disallow duplicate keys when creating object literals
|
||||
"no-empty": 0, // disallow empty statements
|
||||
"no-ex-assign": 1, // disallow assigning to the exception in a catch block
|
||||
"no-extra-boolean-cast": 1, // disallow double-negation boolean casts in a boolean context
|
||||
@@ -78,7 +85,7 @@
|
||||
"no-regex-spaces": 1, // disallow multiple spaces in a regular expression literal
|
||||
"no-reserved-keys": 0, // disallow reserved words being used as object literal keys (off by default)
|
||||
"no-sparse-arrays": 1, // disallow sparse arrays
|
||||
"no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement
|
||||
"no-unreachable": 1, // disallow unreachable statements after a return, throw, continue, or break statement
|
||||
"use-isnan": 1, // disallow comparisons with the value NaN
|
||||
"valid-jsdoc": 0, // Ensure JSDoc comments are valid (off by default)
|
||||
"valid-typeof": 1, // Ensure that the results of typeof are compared against a valid string
|
||||
@@ -99,7 +106,7 @@
|
||||
"no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression (off by default)
|
||||
"no-else-return": 0, // disallow else after a return in an if (off by default)
|
||||
"no-eq-null": 0, // disallow comparisons to null without a type-checking operator (off by default)
|
||||
"no-eval": 2, // disallow use of eval()
|
||||
"no-eval": 1, // disallow use of eval()
|
||||
"no-extend-native": 1, // disallow adding to native types
|
||||
"no-extra-bind": 1, // disallow unnecessary function binding
|
||||
"no-fallthrough": 1, // disallow fallthrough of case statements
|
||||
@@ -112,7 +119,7 @@
|
||||
"no-multi-str": 0, // disallow use of multiline strings
|
||||
"no-native-reassign": 0, // disallow reassignments of native objects
|
||||
"no-new": 1, // disallow use of new operator when not part of the assignment or comparison
|
||||
"no-new-func": 2, // disallow use of new operator for Function object
|
||||
"no-new-func": 1, // disallow use of new operator for Function object
|
||||
"no-new-wrappers": 1, // disallows creating new instances of String,Number, and Boolean
|
||||
"no-octal": 1, // disallow use of octal literals
|
||||
"no-octal-escape": 1, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
|
||||
@@ -157,18 +164,6 @@
|
||||
"no-restricted-modules": 1, // restrict usage of specified node modules (off by default)
|
||||
"no-sync": 0, // disallow use of synchronous methods (off by default)
|
||||
|
||||
// ESLint Comments Plugin
|
||||
// The following rules are made available via `eslint-plugin-eslint-comments`
|
||||
"eslint-comments/no-aggregating-enable": 1, // disallows eslint-enable comments for multiple eslint-disable comments
|
||||
"eslint-comments/no-unlimited-disable": 1, // disallows eslint-disable comments without rule names
|
||||
"eslint-comments/no-unused-disable": 1, // disallow disables that don't cover any errors
|
||||
"eslint-comments/no-unused-enable": 1, // // disallow enables that don't enable anything or enable rules that weren't disabled
|
||||
|
||||
// Flow Plugin
|
||||
// The following rules are made available via `eslint-plugin-flowtype`
|
||||
"flowtype/define-flow-type": 1,
|
||||
"flowtype/use-flow-type": 1,
|
||||
|
||||
// Prettier Plugin
|
||||
// https://github.com/prettier/eslint-plugin-prettier
|
||||
"prettier/prettier": [2, "fb", "@format"],
|
||||
@@ -178,12 +173,12 @@
|
||||
|
||||
"key-spacing": 0,
|
||||
"keyword-spacing": 1, // enforce spacing before and after keywords
|
||||
"jsx-quotes": [1, "prefer-double"], // enforces the usage of double quotes for all JSX attribute values which doesn’t contain a double quote
|
||||
"jsx-quotes": [1, "prefer-double"],
|
||||
"comma-spacing": 0,
|
||||
"no-multi-spaces": 0,
|
||||
"brace-style": 0, // enforce one true brace style (off by default)
|
||||
"camelcase": 0, // require camel case names
|
||||
"consistent-this": 1, // enforces consistent naming when capturing the current execution context (off by default)
|
||||
"consistent-this": [1, "self"], // enforces consistent naming when capturing the current execution context (off by default)
|
||||
"eol-last": 1, // enforce newline at the end of file, with no multiple empty lines
|
||||
"func-names": 0, // require function expressions to have a name (off by default)
|
||||
"func-style": 0, // enforces use of function declarations or expressions (off by default)
|
||||
@@ -191,7 +186,6 @@
|
||||
"new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments
|
||||
"no-nested-ternary": 0, // disallow nested ternary expressions (off by default)
|
||||
"no-array-constructor": 1, // disallow use of the Array constructor
|
||||
"no-empty-character-class": 1, // disallow the use of empty character classes in regular expressions
|
||||
"no-lonely-if": 0, // disallow if as the only statement in an else block (off by default)
|
||||
"no-new-object": 1, // disallow use of the Object constructor
|
||||
"no-spaced-func": 1, // disallow space between function identifier and application
|
||||
@@ -226,9 +220,8 @@
|
||||
|
||||
"react/display-name": 0,
|
||||
"react/jsx-boolean-value": 0,
|
||||
"react/jsx-no-comment-textnodes": 1,
|
||||
"react/jsx-no-duplicate-props": 2,
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-no-undef": 1,
|
||||
"react/jsx-sort-props": 0,
|
||||
"react/jsx-uses-react": 1,
|
||||
"react/jsx-uses-vars": 1,
|
||||
@@ -240,34 +233,6 @@
|
||||
"react/prop-types": 0,
|
||||
"react/react-in-jsx-scope": 1,
|
||||
"react/self-closing-comp": 1,
|
||||
"react/wrap-multilines": 0,
|
||||
|
||||
// React-Native Plugin
|
||||
// The following rules are made available via `eslint-plugin-react-native`
|
||||
|
||||
"react-native/no-inline-styles": 1,
|
||||
|
||||
// Jest Plugin
|
||||
// The following rules are made available via `eslint-plugin-jest`.
|
||||
"jest/no-disabled-tests": 1,
|
||||
"jest/no-focused-tests": 1,
|
||||
"jest/no-identical-title": 1,
|
||||
"jest/valid-expect": 1,
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"local-cli/**/*.js",
|
||||
],
|
||||
"rules": {
|
||||
"lint/extra-arrow-initializer": 0,
|
||||
"no-alert": 0,
|
||||
"no-console-disallow": 0,
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"react/wrap-multilines": 0
|
||||
}
|
||||
}
|
||||
|
||||
+8
-36
@@ -5,8 +5,8 @@
|
||||
; Ignore templates for 'react-native init'
|
||||
.*/local-cli/templates/.*
|
||||
|
||||
; Ignore the Dangerfile
|
||||
<PROJECT_ROOT>/bots/dangerfile.js
|
||||
; Ignore the website subdir
|
||||
<PROJECT_ROOT>/website/.*
|
||||
|
||||
; Ignore "BUCK" generated dirs
|
||||
<PROJECT_ROOT>/\.buckd/
|
||||
@@ -19,45 +19,16 @@
|
||||
; "node_modules/react-native" but in the source repo it is in the root
|
||||
.*/Libraries/react-native/React.js
|
||||
|
||||
; Ignore polyfills
|
||||
.*/Libraries/polyfills/.*
|
||||
|
||||
; Ignore metro
|
||||
.*/node_modules/metro/.*
|
||||
|
||||
; These should not be required directly
|
||||
; require from fbjs/lib instead: require('fbjs/lib/invariant')
|
||||
.*/node_modules/invariant/.*
|
||||
.*/node_modules/warning/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
Libraries/react-native/react-native-interface.js
|
||||
flow/
|
||||
flow-github/
|
||||
|
||||
[options]
|
||||
emoji=true
|
||||
|
||||
module.system=haste
|
||||
module.system.haste.use_name_reducers=true
|
||||
# keep the following in sync with server/haste/hasteImpl.js
|
||||
# get basename
|
||||
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
|
||||
# strip .js or .js.flow suffix
|
||||
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
|
||||
# strip .ios suffix
|
||||
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
|
||||
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
|
||||
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
|
||||
module.system.haste.paths.blacklist=.*/__tests__/.*
|
||||
module.system.haste.paths.blacklist=.*/__mocks__/.*
|
||||
module.system.haste.paths.blacklist=<PROJECT_ROOT>/Libraries/Animated/src/polyfills/.*
|
||||
module.system.haste.paths.whitelist=<PROJECT_ROOT>/Libraries/.*
|
||||
module.system.haste.paths.whitelist=<PROJECT_ROOT>/RNTester/.*
|
||||
module.system.haste.paths.whitelist=<PROJECT_ROOT>/IntegrationTests/.*
|
||||
module.system.haste.paths.blacklist=<PROJECT_ROOT>/Libraries/Animated/src/polyfills/.*
|
||||
|
||||
munge_underscores=true
|
||||
|
||||
@@ -65,13 +36,14 @@ module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|we
|
||||
|
||||
suppress_type=$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FlowFixMeProps
|
||||
suppress_type=$FlowFixMeState
|
||||
suppress_type=$FixMe
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
unsafe.enable_getters_and_setters=true
|
||||
|
||||
[version]
|
||||
^0.75.0
|
||||
^0.49.1
|
||||
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
docs/* @hramos
|
||||
blog/* @hramos
|
||||
Libraries/Animated/* @janicduplessis
|
||||
Libraries/NativeAnimation/* @janicduplessis
|
||||
Libraries/Image/* @shergin
|
||||
Libraries/Text/* @shergin
|
||||
React/Base/* @shergin
|
||||
React/Views/* @shergin
|
||||
React/Modules/* @shergin
|
||||
React/CxxBridge/* @mhorowitz
|
||||
ReactAndroid/src/main/java/com/facebook/react/animated/* @janicduplessis
|
||||
**/*.md @hramos
|
||||
package.json @hramos
|
||||
local-cli/core/* @grabbou @kureev
|
||||
local-cli/link/* @grabbou @kureev
|
||||
local-cli/unlink/* @grabbou @kureev
|
||||
website/* @hramos
|
||||
website/showcase.json @hramos
|
||||
package.json @hramos @ericnakagawa
|
||||
website/package.json @hramos @ericnakagawa
|
||||
|
||||
+123
-2
@@ -1,3 +1,124 @@
|
||||
GitHub Issues in the `facebook/react-native` repository are used exclusively for tracking bugs in React Native.
|
||||
<!--
|
||||
PLEASE DON'T DELETE THIS TEMPLATE UNTIL YOU HAVE READ THE FIRST SECTION.
|
||||
-->
|
||||
|
||||
Please take a look at the issue templates at https://github.com/facebook/react-native/issues/new/choose before submitting a new issue. Following one of the issue templates will ensure maintainers can route your request efficiently. Thanks!
|
||||
### Is this a bug report?
|
||||
|
||||
(write your answer here)
|
||||
|
||||
<!--
|
||||
If you answered "Yes":
|
||||
|
||||
We expect that it will take you about 30 minutes to produce a high-quality bug report.
|
||||
While this may seem like a lot, putting care into issues helps us fix them faster.
|
||||
For bug reports, it is REQUIRED to fill the rest of this template, or the issue will be closed.
|
||||
|
||||
If you answered "No":
|
||||
|
||||
We use GitHub Issues exclusively for tracking bugs in React Native. If you're looking for help,
|
||||
check out the How to Get In Touch section of the following guide:
|
||||
https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md#how-to-get-in-touch
|
||||
|
||||
Now scroll below!
|
||||
-->
|
||||
|
||||
|
||||
### Have you read the Bugs section of the Contributing to React Native Guide?
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
<!--
|
||||
Please read through the bug reporting guidelines thoroughly:
|
||||
https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md#bugs
|
||||
-->
|
||||
|
||||
### Environment
|
||||
|
||||
<!--
|
||||
Please fill in all the relevant fields by running these commands in terminal.
|
||||
-->
|
||||
|
||||
1. `react-native -v`:
|
||||
2. `node -v`:
|
||||
3. `npm -v`:
|
||||
4. `yarn --version` (if you use Yarn):
|
||||
|
||||
Then, specify:
|
||||
|
||||
<!-- (What platform are you building for? Choose any from iOS, Android, AppleTV.) -->
|
||||
- Target Platform:
|
||||
|
||||
<!-- Which operating system are you using? Specify macOS, Windows, or Linux, along with specific release versions -->
|
||||
- Development Operating System:
|
||||
|
||||
<!-- Include any additional relevant information. Are you using Xcode or Android Studio to build native code? Is the issue specific to a particular iOS or Android SDK? -->
|
||||
- Build tools:
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
<!--
|
||||
How would you describe your issue to someone who doesn’t know you or your project?
|
||||
Try to write a sequence of steps that anybody can repeat to see the issue.
|
||||
Be specific! If the bug cannot be reproduced, your issue may be closed.
|
||||
-->
|
||||
|
||||
(Write your steps here:)
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### Expected Behavior
|
||||
|
||||
<!--
|
||||
How did you expect your project to behave?
|
||||
It’s fine if you’re not sure your understanding is correct.
|
||||
Just write down what you thought would happen.
|
||||
-->
|
||||
|
||||
(Write what you thought would happen.)
|
||||
|
||||
### Actual Behavior
|
||||
|
||||
<!--
|
||||
Did something go wrong?
|
||||
Is something broken, or not behaving as you expected?
|
||||
Describe this section in detail, and attach screenshots if possible.
|
||||
Don't just say "it doesn't work"!
|
||||
-->
|
||||
|
||||
(Write what happened. Add screenshots!)
|
||||
|
||||
### Reproducible Demo
|
||||
|
||||
<!--
|
||||
Please share a project that reproduces the issue.
|
||||
There are two ways to do it:
|
||||
|
||||
* Create a new app using https://snack.expo.io/ and try to reproduce the issue in it.
|
||||
This is useful if you roughly know where the problem is, or can’t share the real code.
|
||||
|
||||
* Or, copy your app and remove things until you’re left with the minimal reproducible demo.
|
||||
This is useful for finding the root cause. You may then optionally create a Snack.
|
||||
|
||||
This is a good guide to creating bug demos: https://stackoverflow.com/help/mcve
|
||||
Once you’re done, copy and paste the link to the Snack or a public GitHub repository below:
|
||||
-->
|
||||
|
||||
(Paste the link to an example project and exact instructions to reproduce the issue.)
|
||||
|
||||
<!--
|
||||
What happens if you skip this step?
|
||||
|
||||
Someone will read your bug report, and maybe will be able to help you,
|
||||
but it’s unlikely that it will get much attention from the team. Eventually,
|
||||
the issue will likely get closed in favor of issues that have reproducible demos.
|
||||
|
||||
Please remember that:
|
||||
|
||||
* Issues without reproducible demos have a very low priority.
|
||||
* The person fixing the bug would have to do that anyway. Please be respectful of their time.
|
||||
* You might figure out the issues yourself as you work on extracting it.
|
||||
|
||||
Thanks for helping us help you!
|
||||
-->
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: Report a reproducible bug or regression in the core React Native library.
|
||||
---
|
||||
|
||||
<!-- Requirements: please go through this checklist before opening a new issue -->
|
||||
- [ ] Review the documentation: https://facebook.github.io/react-native
|
||||
- [ ] Search for existing issues: https://github.com/facebook/react-native/issues
|
||||
- [ ] Use the latest React Native version: https://github.com/facebook/react-native/releases
|
||||
- [ ] Run `react-native info` in your terminal and paste its contents under "Environment"
|
||||
- [ ] Let us know how to reproduce the issue. Include a code sample, share a project, or
|
||||
share an app that reproduces the issue using https://snack.expo.io/
|
||||
|
||||
## Environment
|
||||
<!-- Required. -->
|
||||
|
||||
## Description
|
||||
<!-- Describe your issue in detail. -->
|
||||
|
||||
## Steps to Reproduce
|
||||
<!-- Required. -->
|
||||
|
||||
## Expected Behavior
|
||||
<!-- Write what you thought would happen. -->
|
||||
|
||||
## Actual Behavior
|
||||
<!-- Write what happened. Include screenshots if needed. If this is a regression, let us know. -->
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
name: 🗣 Start a Discussion
|
||||
about: Use https://discuss.reactjs.org/ to propose changes or discuss feature requests.
|
||||
|
||||
guidelines: |
|
||||
If you feel strongly about starting a discussion as a GitHub Issue instead of using the discussion forum, please follow this template.
|
||||
We kindly ask that issues of this type are kept to a minimum to ensure bug reports and regressions are given the priority they require.
|
||||
Maintainers may flag an issue for Stack Overflow or kindly ask you to move the discussion to https://discuss.reactjs.org at their own discretion.
|
||||
|
||||
---
|
||||
|
||||
## For Discussion
|
||||
|
||||
<!-- Describe your issue in detail. -->
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: 📖 Documentation Issue
|
||||
about: Report issues with the docs at https://github.com/facebook/react-native-website/issues.
|
||||
|
||||
---
|
||||
|
||||
--------------^ Click "Preview" for a nicer view!
|
||||
|
||||
GitHub Issues in the `facebook/react-native` repository are used exclusively for tracking bugs in React Native.
|
||||
|
||||
If you would like to report an issue in the React Native documentation, or anything related to the [React Native website](http://facebook.github.io/react-native), please visit https://github.com/facebook/react-native-website/issues.
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
name: 💬 Question
|
||||
about: If you need help with your React Native app, the right place to go depends on the type of help that you need.
|
||||
|
||||
---
|
||||
|
||||
--------------^ Click "Preview" for a nicer view!
|
||||
|
||||
GitHub Issues in the `facebook/react-native` repository are used exclusively for tracking bugs in React Native. GitHub may not be the ideal place to ask questions about using React Native, but we have compiled a list of resources that should help.
|
||||
|
||||
### Get help with your React Native app or ask code-level questions
|
||||
|
||||
Many members of the community use Stack Overflow to ask questions. Read through the [existing questions](http://stackoverflow.com/questions/tagged/react-native?sort=frequent) tagged with **react-native** or [ask your own](http://stackoverflow.com/questions/ask?tags=react-native)!
|
||||
|
||||
### Talk about best practices or propose changes to React Native
|
||||
|
||||
For longer-form conversations about React Native, we’ve set up a [discussion forum at **discuss.reactjs.org**](https://discuss.reactjs.org/t/welcome-react-native-community-group/10239). This forum is a great place for discussion about best practices and application architecture as well as the future of React Native.
|
||||
|
||||
### Chat with React and React Native community members
|
||||
|
||||
If you need an answer right away, check out the [Reactiflux Discord](https://discord.gg/0ZcbPKXt5bZjGY5n) community. There are usually a number of React Native experts there who can help out or point you to somewhere you might want to look.
|
||||
@@ -1,53 +1,9 @@
|
||||
Thank you for sending the PR! We appreciate you spending the time to work on these changes.
|
||||
Help us understand your motivation by explaining why you decided to make this change.
|
||||
|
||||
<!--
|
||||
Required: Write your motivation here.
|
||||
If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
|
||||
-->
|
||||
|
||||
## Test Plan
|
||||
|
||||
<!--
|
||||
Required: Write your test plan here. If you changed any code, please provide us with
|
||||
clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
|
||||
-->
|
||||
|
||||
## Related PRs
|
||||
|
||||
<!--
|
||||
Does this PR require a documentation change?
|
||||
Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
|
||||
-->
|
||||
|
||||
## Release Notes
|
||||
|
||||
<!--
|
||||
Required.
|
||||
Help reviewers and the release process by writing your own release notes. See below for an example.
|
||||
-->
|
||||
|
||||
[CATEGORY] [TYPE] [LOCATION] - Message
|
||||
|
||||
<!--
|
||||
**INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**
|
||||
Thank you for sending the PR!
|
||||
|
||||
CATEGORY
|
||||
[----------] TYPE
|
||||
[ CLI ] [-------------] LOCATION
|
||||
[ DOCS ] [ BREAKING ] [-------------]
|
||||
[ GENERAL ] [ BUGFIX ] [ {Component} ]
|
||||
[ INTERNAL ] [ ENHANCEMENT ] [ {Filename} ]
|
||||
[ IOS ] [ FEATURE ] [ {Directory} ] |-----------|
|
||||
[ ANDROID ] [ MINOR ] [ {Framework} ] - | {Message} |
|
||||
[----------] [-------------] [-------------] |-----------|
|
||||
If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos!
|
||||
|
||||
EXAMPLES:
|
||||
Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native.
|
||||
|
||||
[IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
|
||||
[ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
|
||||
[CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
|
||||
[DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
|
||||
[GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
|
||||
[INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
|
||||
Happy contributing!
|
||||
-->
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 90
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 30
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- Good first issue
|
||||
- For Discussion
|
||||
- Core Team
|
||||
- "Help Wanted :octocat:"
|
||||
- ":warning:Regression"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: Stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs.
|
||||
You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open.
|
||||
Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.
|
||||
only: issues
|
||||
+2
-14
@@ -36,9 +36,6 @@ buck-out
|
||||
/ReactAndroid/src/main/jni/prebuilt/lib/x86/
|
||||
/ReactAndroid/src/main/gen
|
||||
|
||||
# Watchman
|
||||
.watchmanconfig
|
||||
|
||||
# Android
|
||||
.idea
|
||||
.gradle
|
||||
@@ -50,12 +47,6 @@ local.properties
|
||||
node_modules
|
||||
*.log
|
||||
.nvm
|
||||
/bots/node_modules/
|
||||
|
||||
# TODO: Check in yarn.lock in open source. Right now we need to keep it out
|
||||
# from the GitHub repo as importing it might conflict with internal workspaces
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
|
||||
# OS X
|
||||
.DS_Store
|
||||
@@ -67,8 +58,5 @@ package-lock.json
|
||||
/coverage
|
||||
/third-party
|
||||
|
||||
# Root dir shouldn't have Xcode project
|
||||
/*.xcodeproj
|
||||
|
||||
# ReactCommon subdir shouldn't have Xcode project
|
||||
/ReactCommon/**/*.xcodeproj
|
||||
/website/src
|
||||
/website/build
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
language: objective-c
|
||||
|
||||
osx_image: xcode8.3
|
||||
|
||||
install:
|
||||
- nvm install 7
|
||||
- rm -Rf "${TMPDIR}/jest_preprocess_cache"
|
||||
- brew install yarn --ignore-dependencies
|
||||
- yarn install
|
||||
|
||||
script:
|
||||
- if [[ "$TEST_TYPE" = objc-ios ]]; then travis_retry travis_wait 30 ./scripts/objc-test-ios.sh test; fi
|
||||
- if [[ "$TEST_TYPE" = objc-tvos ]]; then travis_retry travis_wait 30 ./scripts/objc-test-tvos.sh; fi
|
||||
- if [[ "$TEST_TYPE" = e2e-objc ]]; then node ./scripts/run-ci-e2e-tests.js --ios --js --retries 3; fi
|
||||
- if [[ ( "$TEST_TYPE" = podspecs ) && ( "$TRAVIS_PULL_REQUEST" = "false" ) ]]; then gem install cocoapods && travis_wait 30 ./scripts/process-podspecs.sh; fi
|
||||
|
||||
cache:
|
||||
- cocoapods
|
||||
- yarn
|
||||
|
||||
matrix:
|
||||
- fast_finish: true # Fail the whole build as soon as one test type fails. Should help with Travis capacity issues (very long queues).
|
||||
|
||||
# The order of these tests says which are more likely to run first and fail the whole build fast.
|
||||
env:
|
||||
- TEST_TYPE=objc-ios
|
||||
- TEST_TYPE=podspecs
|
||||
- TEST_TYPE=e2e-objc
|
||||
- TEST_TYPE=objc-tvos
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^.*-stable$/
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- douglowder@mac.com # Doug Lowder built and maintains Apple TV specific code and wants to be notified about tvOS failures.
|
||||
- eloy@artsy.net # Eloy Durán maintains the podspecs test and wants to be notified about failures.
|
||||
on_failure: change
|
||||
on_success: change
|
||||
slack:
|
||||
secure: oQL2C966v7/DtxNqfM7WowjY0R5mgLHR2qHkoucwK5iVrmaptnHr8fq01xlj7VT0kDwNLqT3n4+gtCviGw89lq71m3W76c8Pms/10jpjw+LwAfQPVizNw/Bx8MFNNmjDauK/auFxaybiLZupi7zd4xFGOZvScmFdfD4CAAp2OOA=
|
||||
on_pull_requests: false
|
||||
on_failure: change
|
||||
on_success: change
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible Node.js debug attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"program": "${workspaceRoot}/Libraries/react-native/react-native-implementation.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
# [Open Source Code of Conduct](https://code.facebook.com/codeofconduct)
|
||||
|
||||
This code of conduct outlines our expectations for participants within the **Facebook Open Source** community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community.
|
||||
|
||||
Our open source community strives to:
|
||||
|
||||
* **Be friendly and patient.**
|
||||
* **Be welcoming:** We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
|
||||
* **Be considerate:** Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.
|
||||
* **Be respectful:** Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
|
||||
* **Be careful in the words that you choose:** we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren’t acceptable. This includes, but is not limited to:
|
||||
* Violent threats or language directed against another person.
|
||||
* Discriminatory jokes and language.
|
||||
* Posting sexually explicit or violent material.
|
||||
* Posting (or threatening to post) other people’s personally identifying information (“doxing”).
|
||||
* Personal insults, especially those using racist or sexist terms.
|
||||
* Unwelcome sexual attention.
|
||||
* Advocating for, or encouraging, any of the above behavior.
|
||||
* Repeated harassment of others. In general, if someone asks you to stop, then stop.
|
||||
* **When we disagree, try to understand why:** Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively.
|
||||
* **Remember that we’re different.** The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
|
||||
|
||||
This code is not exhaustive or complete. It serves to distill our common understanding of a collaborative, shared environment, and goals. We expect it to be followed in spirit as much as in the letter.
|
||||
|
||||
## Diversity Statement
|
||||
|
||||
We encourage everyone to participate and are committed to building a community for all. Although we may not be able to satisfy everyone, we all agree that everyone is equal. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong.
|
||||
|
||||
Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected characteristics above, including participants with disabilities.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us via opensource@fb.com. All reports will be handled with discretion. In your report please include:
|
||||
|
||||
* Your contact information.
|
||||
* Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
|
||||
* Any additional information that may be helpful.
|
||||
|
||||
After filing a report, a representative will contact you personally. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. A representative will then review the incident, follow up with any additional questions, and make a decision as to how to respond. We will respect confidentiality requests for the purpose of protecting victims of abuse.
|
||||
|
||||
Anyone asked to stop unacceptable behavior is expected to comply immediately. If an individual engages in unacceptable behavior, the representative may take any action they deem appropriate, up to and including a permanent ban from our community without warning.
|
||||
|
||||
_This Code Of Conduct follows the [template](http://todogroup.org/opencodeofconduct/) established by the [TODO Group](http://todogroup.org/)._
|
||||
+68
-82
@@ -1,123 +1,108 @@
|
||||
# Contributing to React Native
|
||||
|
||||
<!-- generated_contributing_start -->
|
||||
React Native is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody using Facebook's mobile apps. If you're interested in contributing to React Native, hopefully this document makes the process for contributing clear.
|
||||
React Native is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on https://facebook.com. We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and preempts some questions you may have.
|
||||
|
||||
## [Code of Conduct](https://code.facebook.com/codeofconduct)
|
||||
## 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/codeofconduct) so that you can understand what actions will and will not be tolerated.
|
||||
|
||||
## Get involved
|
||||
|
||||
There are many ways to contribute to React Native, and many of them do not involve writing any code. Here's a few ideas to get started:
|
||||
|
||||
* Simply start using React Native. Go through the [Getting Started](https://facebook.github.io/react-native/docs/getting-started.html) guide. Does everything work as expected? If not, we're always looking for improvements. Let us know by [opening an issue](https://facebook.github.io/react-native/docs/contributing.html#reporting-new-issues).
|
||||
* Look through the [open issues](https://github.com/facebook/react-native/issues). Provide workarounds, ask for clarification, or suggest labels. Help [triage issues](https://facebook.github.io/react-native/docs/contributing.html#triaging-issues-and-pull-requests).
|
||||
* If you find an issue you would like to fix, [open a pull request](https://facebook.github.io/react-native/docs/contributing.html#your-first-pull-request). Issues tagged as [_Good first issue_](https://github.com/facebook/react-native/labels/Good%20first%20issue) are a good place to get started.
|
||||
* Read through the [React Native docs](https://facebook.github.io/react-native/docs/getting-started.html). If you find anything that is confusing or can be improved, you can make edits by clicking the "EDIT" button in the top-right corner of most docs.
|
||||
* Browse [Stack Overflow](https://stackoverflow.com/questions/tagged/react-native) and answer questions. This will help you get familiarized with common pitfalls or misunderstandings, which can be useful when contributing updates to the documentation.
|
||||
* Take a look at the [features requested](https://react-native.canny.io/feature-requests) by others in the community and consider opening a pull request if you see something you want to work on.
|
||||
|
||||
Contributions are very welcome. If you think you need help planning your contribution, please hop into [#react-native](https://discord.gg/0ZcbPKXt5bZjGY5n) and let people know you're looking for a mentor.
|
||||
|
||||
Core contributors to React Native meet monthly and post their meeting notes on the [React Native blog](https://facebook.github.io/react-native/blog). You can also find ad hoc discussions in the [React Native Core Contributors](https://www.facebook.com/groups/reactnativeoss/) Facebook group.
|
||||
|
||||
### Triaging issues and pull requests
|
||||
|
||||
One great way you can contribute to the project without writing any code is to help triage issues and pull requests as they come in.
|
||||
|
||||
* Ask for more information if the issue does not provide all the details required by the template.
|
||||
* Suggest [labels](https://github.com/facebook/react-native/labels) that can help categorize issues.
|
||||
* Flag issues that are stale or that should be closed.
|
||||
* Ask for test plans and review code.
|
||||
|
||||
You can learn more about handling issues in the [maintainer's guide](docs/maintainers.html#handling-issues).
|
||||
|
||||
## Our development process
|
||||
## Our Development Process
|
||||
|
||||
Some of the core team will be working directly on [GitHub](https://github.com/facebook/react-native). These changes will be public from the beginning. Other changesets will come via a bridge with Facebook's internal source control. This is a necessity as it allows engineers at Facebook outside of the core team to move fast and contribute from an environment they are comfortable in.
|
||||
|
||||
When a change made on GitHub is approved, it will first be imported into Facebook's internal source control. The change will eventually sync back to GitHub as a single commit once it has passed all internal tests.
|
||||
|
||||
### Branch organization
|
||||
## Branch Organization
|
||||
|
||||
We will do our best to keep `master` in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We will do our best to [communicate these changes](https://github.com/facebook/react-native/releases) and version appropriately so you can lock into a specific version if need be.
|
||||
|
||||
To see what changes are coming and provide better feedback to React Native contributors, use the [latest release candidate](https://facebook.github.io/react-native/versions.html) when possible. By the time a release candidate is released, the changes it contains will have been shipped in production Facebook apps for over two weeks.
|
||||
To see what changes are coming and provide better feedback to React Native contributors, use the [latest release candidate](http://facebook.github.io/react-native/versions.html) when possible. By the time a release candidate is released, the changes it contains will have been shipped in production Facebook apps for over two weeks.
|
||||
|
||||
## Bugs
|
||||
|
||||
We use [GitHub Issues](https://github.com/facebook/react-native/issues) for our public bugs. If you would like to report a problem, take a look around and see if someone already opened an issue about it. If you a are certain this is a new, unreported bug, you can submit a [bug report](https://facebook.github.io/react-native/docs/contributing.html#reporting-new-issues).
|
||||
#### Where to Find Known Issues
|
||||
|
||||
If you have questions about using React Native, the [Community page](https://facebook.github.io/react-native/help.html) list various resources that should help you get started.
|
||||
We are using [GitHub Issues](https://github.com/facebook/react-native/issues) for our public bugs. Before filing a new task, try to make sure your problem doesn't already exist.
|
||||
|
||||
We also have a [place where you can request features or enhancements](https://react-native.canny.io/feature-requests). If you see anything you'd like to be implemented, vote it up and explain your use case.
|
||||
Questions and feature requests are tracked elsewhere:
|
||||
|
||||
## Reporting new issues
|
||||
- Have a question? [Ask on Stack Overflow](http://stackoverflow.com/questions/tagged/react-native).
|
||||
- If you have a question regarding future plans, check out the [roadmap](https://github.com/facebook/react-native/wiki/Roadmap).
|
||||
- Have a feature request that is not covered in the roadmap? [Add it here](https://react-native.canny.io/feature-requests).
|
||||
|
||||
When [opening a new issue](https://github.com/facebook/react-native/issues/new), always make sure to fill out the [issue template](https://raw.githubusercontent.com/facebook/react-native/master/.github/ISSUE_TEMPLATE.md). **This step is very important!** Not doing so may result in your issue getting closed. Don't take this personally if this happens, and feel free to open a new issue once you've gathered all the information required by the template.
|
||||
#### Reporting New Issues
|
||||
|
||||
* **One issue, one bug:** Please report a single bug per issue.
|
||||
* **Provide a Snack:** The best way to get attention on your issue is to provide a reduced test case. You can use [Snack](https://snack.expo.io/) to demonstrate the issue.
|
||||
* **Provide reproduction steps:** List all the steps necessary to reproduce the issue. Provide a Snack or upload a sample project to GitHub. The person reading your bug report should be able to follow these steps to reproduce your issue with minimal effort.
|
||||
* **Try out the latest version:** Verify that the issue can be reproduced locally by updating your project to use [React Native from `master`](https://facebook.github.io/react-native/versions.html). The bug may have already been fixed!
|
||||
The best way to get your bug fixed is to provide a reduced test case. Please provide either a [Sketch](https://sketch.expo.io/) or a public repository with a runnable example.
|
||||
|
||||
We're not able to provide support through GitHub Issues. If you're looking for help with your code, consider asking on [Stack Overflow](https://stackoverflow.com/questions/tagged/react-native) or reaching out to the community through [other channels](https://facebook.github.io/react-native/support.html).
|
||||
Please report a single bug per issue. Always provide reproduction steps. You can use Snack in many cases to demonstrate an issue: https://snack.expo.io/. If the bug cannot be reproduced using Snack, verify that the issue can be reproduced locally by targeting the latest release candidate. Ideally, check if the issue is present in master as well.
|
||||
|
||||
### Security bugs
|
||||
Do not forget to include sample code that reproduces the issue. Only open issues for bugs affecting either the latest stable release, or the current release candidate, or master (see http://facebook.github.io/react-native/versions.html). If it is not clear from your report that the issue can be reproduced in one of these releases, your issue will be closed.
|
||||
|
||||
We're not able to provide support through GitHub Issues. If you're looking for help with your code, consider asking on Stack Overflow: http://stackoverflow.com/questions/tagged/react-native
|
||||
|
||||
#### Security Bugs
|
||||
|
||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.
|
||||
|
||||
## Pull requests
|
||||
## How to Get in Touch
|
||||
|
||||
### Your first pull request
|
||||
Many React Native users are active on [Stack Overflow](http://stackoverflow.com/questions/tagged/react-native).
|
||||
|
||||
So you have decided to contribute code back to upstream by opening a pull request. You've invested a good chunk of time, and we appreciate it. We will do our best to work with you and get the PR looked at.
|
||||
If you want to get a general sense of what React Native folks talk about, check out the [React Native Community](https://www.facebook.com/groups/react.native.community) Facebook group.
|
||||
|
||||
Working on your first Pull Request? You can learn how from this free video series:
|
||||
There is also [an active community of React and React Native users on the Discord chat platform](https://discord.gg/0ZcbPKXt5bZjGY5n) in case you need help.
|
||||
|
||||
[**How to Contribute to an Open Source Project on GitHub**](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github)
|
||||
The React Native team sends out periodical updates through the following channels:
|
||||
|
||||
We have a list of [beginner friendly issues](https://github.com/facebook/react-native/labels/Good%20first%20issue) to help you get your feet wet in the React Native codebase and familiar with our contribution process. This is a great place to get started.
|
||||
* [Blog](https://facebook.github.io/react-native/blog/)
|
||||
* [Twitter](https://www.twitter.com/reactnative)
|
||||
|
||||
### Proposing a change
|
||||
Core contributors to React Native meet monthly and post their meeting notes on the React Native blog. You can also find ad hoc discussions in the [React Native Core Contributors](https://www.facebook.com/groups/reactnativeoss/) Facebook group.
|
||||
|
||||
If you would like to request a new feature or enhancement but are not yet thinking about opening a pull request, we have a [place to track feature requests](https://react-native.canny.io/feature-requests).
|
||||
## Proposing a Change
|
||||
|
||||
If you intend to change the public API, or make any non-trivial changes to the implementation, we recommend [filing an issue](https://github.com/facebook/react-native/issues/new?title=%5BProposal%5D) that includes `[Proposal]` in the title. This lets us reach an agreement on your proposal before you put significant effort into it. These types of issues should be rare. If you have been contributing to the project long enough, you will probably already have access to the [React Native Core Contributors](https://www.facebook.com/groups/reactnativeoss/) Facebook Group, where this sort of discussion is usually held.
|
||||
If you intend to change the public API, or make any non-trivial changes to the implementation, we recommend [filing an issue](https://github.com/facebook/react-native/issues/new). This lets us reach an agreement on your proposal before you put significant effort into it.
|
||||
|
||||
If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend to file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue.
|
||||
|
||||
### Sending a pull request
|
||||
## Pull Requests
|
||||
|
||||
If you send a pull request, please do it against the master branch. We maintain stable branches for stable releases separately but we don't accept pull requests to them directly. Instead, we cherry-pick non-breaking changes from master to the latest stable version.
|
||||
|
||||
The core team will be monitoring for pull requests. When we get one, we'll run some Facebook-specific integration tests on it first. From here, we'll need to get another person to sign off on the changes and then merge the pull request. For API changes we may need to fix internal uses, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
|
||||
|
||||
Small pull requests are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
|
||||
|
||||
Please make sure the following is done when submitting a pull request:
|
||||
*Before* submitting a pull request, please make sure the following is done…
|
||||
|
||||
1. Fork [the repository](https://github.com/facebook/react-native) and create your branch from `master`.
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
2. Add the copyright notice to the top of any new files you've added.
|
||||
3. Describe your [**test plan**](https://facebook.github.io/react-native/docs/contributing.html#test-plan) in your pull request description. Make sure to [test your changes](https://facebook.github.io/react-native/docs/testing.html)!
|
||||
4. Make sure your code lints (`npm run lint`).
|
||||
5. If you haven't already, [sign the CLA](https://code.facebook.com/cla).
|
||||
|
||||
All pull requests should be opened against the `master` branch. After opening your pull request, ensure [**all tests pass**](https://facebook.github.io/react-native/docs/contributing.html#contrinuous-integration-tests) on Circle CI. If a test fails and you believe it is unrelated to your change, leave a comment on the pull request explaining why.
|
||||
3. Describe your **test plan** in your commit.
|
||||
4. Ensure **tests pass** on Travis and Circle CI.
|
||||
5. Make sure your code lints (`node linter.js <files touched>`).
|
||||
6. If you haven't already, sign the CLA: https://code.facebook.com/cla
|
||||
7. Squash your commits (`git rebase -i`).
|
||||
One intent alongside one commit makes it clearer for people to review and easier to understand your intention.
|
||||
|
||||
> **Note:** It is not necessary to keep clicking `Merge master to your branch` on the PR page. You would want to merge master if there are conflicts or tests are failing. The Facebook-GitHub-Bot ultimately squashes all commits to a single one before merging your PR.
|
||||
|
||||
#### Test plan
|
||||
|
||||
A good test plan has the exact commands you ran and their output, provides screenshots or videos if the pull request changes UI.
|
||||
A good test plan has the exact commands you ran and their output, provides screenshots or videos if the pull request changes UI or updates the website.
|
||||
|
||||
* If you've added code that should be tested, add tests!
|
||||
* If you've changed APIs, update the documentation.
|
||||
- If you've added code that should be tested, add tests!
|
||||
- If you've changed APIs, update the documentation.
|
||||
- If you've updated the docs, verify the website locally and submit screenshots if applicable (see `website/README.md`)
|
||||
|
||||
See [What is a Test Plan?](https://medium.com/@martinkonicek/what-is-a-test-plan-8bfc840ec171#.y9lcuqqi9) to learn more.
|
||||
See "What is a Test Plan?" to learn more:
|
||||
https://medium.com/@martinkonicek/what-is-a-test-plan-8bfc840ec171#.y9lcuqqi9
|
||||
|
||||
#### Continuous integration tests
|
||||
|
||||
Make sure all **tests pass** on [Circle CI][circle]. PRs that break tests are unlikely to be merged. Learn more about [testing your changes here](https://facebook.github.io/react-native/docs/testing.html).
|
||||
Make sure all **tests pass** on both [Travis][travis] and [Circle CI][circle]. PRs that break tests are unlikely to be merged.
|
||||
|
||||
[circle]: https://circleci.com/gh/facebook/react-native
|
||||
You can learn more about running tests and contributing to React Native here: https://facebook.github.io/react-native/docs/testing.html
|
||||
|
||||
[travis]: https://travis-ci.org/facebook/react-native
|
||||
[circle]: http://circleci.com/gh/facebook/react-native
|
||||
|
||||
#### Breaking changes
|
||||
|
||||
@@ -126,10 +111,10 @@ When adding a new breaking change, follow this template in your pull request:
|
||||
```
|
||||
### New breaking change here
|
||||
|
||||
* **Who does this affect**:
|
||||
* **How to migrate**:
|
||||
* **Why make this breaking change**:
|
||||
* **Severity (number of people affected x effort)**:
|
||||
- **Who does this affect**:
|
||||
- **How to migrate**:
|
||||
- **Why make this breaking change**:
|
||||
- **Severity (number of people affected x effort)**:
|
||||
```
|
||||
|
||||
If your pull request is merged, a core contributor will update the [list of breaking changes](https://github.com/facebook/react-native/wiki/Breaking-Changes) which is then used to populate the release notes.
|
||||
@@ -141,23 +126,25 @@ Copy and paste this to the top of your new file(s):
|
||||
```JS
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
```
|
||||
|
||||
#### Contributor License Agreement (CLA)
|
||||
If you've added a new module, add a `@providesModule <moduleName>` at the end of the comment. This will allow the haste package manager to find it.
|
||||
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, the Facebook GitHub Bot will reply with a link to the CLA form. You may also [complete your CLA here](https://code.facebook.com/cla).
|
||||
### Contributor License Agreement (CLA)
|
||||
|
||||
### What happens next?
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username.
|
||||
|
||||
The core team will be monitoring for pull requests. Read [what to expect from maintainers](https://facebook.github.io/react-native/docs/maintainers.html#handling-pull-requests) to understand what may happen after you open a pull request.
|
||||
Complete your CLA here: https://code.facebook.com/cla
|
||||
|
||||
## Style Guide
|
||||
|
||||
Our linter will catch most styling issues that may exist in your code. You can check the status of your code styling by simply running `npm run lint`.
|
||||
Our linter will catch most styling issues that may exist in your code. You can check the status of your code styling by simply running `node linter.js <files touched>`.
|
||||
|
||||
However, there are still some styles that the linter cannot pick up.
|
||||
|
||||
@@ -173,7 +160,7 @@ However, there are still some styles that the linter cannot pick up.
|
||||
#### JavaScript
|
||||
|
||||
* Use semicolons;
|
||||
* ES6 standards
|
||||
* `'use strict';`
|
||||
* Prefer `'` over `"`
|
||||
* Do not use the optional parameters of `setTimeout` and `setInterval`
|
||||
* 80 character line length
|
||||
@@ -206,5 +193,4 @@ However, there are still some styles that the linter cannot pick up.
|
||||
|
||||
## License
|
||||
|
||||
By contributing to React Native, you agree that your contributions will be licensed under its MIT license.
|
||||
<!-- generated_contributing_end -->
|
||||
By contributing to React Native, you agree that your contributions will be licensed under its BSD license.
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
# React Native Android Unit Tests
|
||||
#
|
||||
# This image builds upon the React Native Base Android Development Environment
|
||||
# image. Ideally, this image would be rebuilt with any new commit to the master
|
||||
# branch. Doing so will catch issues such as BUCK failing to fetch dependencies
|
||||
# or run tests, as well as unit test failures.
|
||||
FROM reactnativeci/android-base:latest
|
||||
|
||||
LABEL Description="This image prepares and runs React Native's Android tests."
|
||||
LABEL maintainer="Héctor Ramos <hector@fb.com>"
|
||||
FROM containership/android-base:latest
|
||||
|
||||
# set default environment variables
|
||||
ENV GRADLE_OPTS="-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs=\"-Xmx512m -XX:+HeapDumpOnOutOfMemoryError\""
|
||||
ENV GRADLE_OPTS="-Dorg.gradle.jvmargs=\"-Xmx512m -XX:+HeapDumpOnOutOfMemoryError\""
|
||||
ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8"
|
||||
|
||||
# add ReactAndroid directory
|
||||
@@ -18,7 +9,6 @@ ADD .buckconfig /app/.buckconfig
|
||||
ADD .buckjavaargs /app/.buckjavaargs
|
||||
ADD ReactAndroid /app/ReactAndroid
|
||||
ADD ReactCommon /app/ReactCommon
|
||||
ADD ReactNative /app/ReactNative
|
||||
ADD keystores /app/keystores
|
||||
|
||||
# set workdir
|
||||
@@ -51,12 +41,14 @@ RUN ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1 -Pcom.android.bu
|
||||
ADD . /app
|
||||
WORKDIR /app
|
||||
|
||||
# https://github.com/npm/npm/issues/13306
|
||||
RUN cd $(npm root -g)/npm && npm install fs-extra && sed -i -e s/graceful-fs/fs-extra/ -e s/fs.rename/fs.move/ ./lib/utils/rename.js
|
||||
|
||||
# build node dependencies
|
||||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||
RUN apt-get install apt-transport-https
|
||||
RUN apt-get update
|
||||
RUN apt-get install yarn
|
||||
RUN yarn
|
||||
RUN npm install
|
||||
RUN npm install github@0.2.4
|
||||
|
||||
WORKDIR /app/website
|
||||
RUN npm install
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -1,36 +1,18 @@
|
||||
# React Native Base Android Development Environment
|
||||
#
|
||||
# This image provides a base Android development environment for React Native,
|
||||
# including, but not limited to, the Android SDK, Android NDK, Node, and BUCK.
|
||||
# These are required in order to run React Native's Android unit and integration
|
||||
# tests.
|
||||
#
|
||||
# This image is not currently built automatically as part of React Native's CI
|
||||
# infrastructure. It should not be necessary to rebuild this image while the
|
||||
# Android dependencies (Android SDK version, build tools version, etc) remain
|
||||
# equal. The operations performed to build this image are those that tend to
|
||||
# remain stable across commits in any given React Native release.
|
||||
|
||||
FROM library/ubuntu:16.04
|
||||
|
||||
LABEL Description="This image provides a base Android development environment for React Native, and may be used to run tests."
|
||||
LABEL maintainer="Héctor Ramos <hector@fb.com>"
|
||||
|
||||
# set default build arguments
|
||||
ARG SDK_VERSION=sdk-tools-linux-3859397.zip
|
||||
ARG ANDROID_BUILD_VERSION=26
|
||||
ARG ANDROID_TOOLS_VERSION=26.0.3
|
||||
ARG BUCK_VERSION=v2018.03.26.01
|
||||
ARG ANDROID_VERSION=25.2.3
|
||||
ARG BUCK_VERSION=f3452a6a7ab15a60e94c962e686293acbe677473
|
||||
ARG NDK_VERSION=10e
|
||||
ARG NODE_VERSION=8.10.0
|
||||
ARG WATCHMAN_VERSION=4.9.0
|
||||
ARG NODE_VERSION=6.2.0
|
||||
ARG WATCHMAN_VERSION=4.7.0
|
||||
|
||||
# set default environment variables
|
||||
ENV ADB_INSTALL_TIMEOUT=10
|
||||
ENV PATH=${PATH}:/opt/buck/bin/
|
||||
ENV ANDROID_HOME=/opt/android
|
||||
ENV ANDROID_SDK_HOME=${ANDROID_HOME}
|
||||
ENV PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools
|
||||
ENV PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
|
||||
ENV ANDROID_NDK=/opt/ndk/android-ndk-r$NDK_VERSION
|
||||
ENV PATH=${PATH}:${ANDROID_NDK}
|
||||
|
||||
@@ -38,41 +20,82 @@ ENV PATH=${PATH}:${ANDROID_NDK}
|
||||
RUN apt-get update && apt-get install ant autoconf automake curl g++ gcc git libqt5widgets5 lib32z1 lib32stdc++6 make maven npm openjdk-8* python-dev python3-dev qml-module-qtquick-controls qtdeclarative5-dev unzip -y
|
||||
|
||||
# configure npm
|
||||
RUN npm config set spin=false && \
|
||||
npm config set progress=false
|
||||
RUN npm config set spin=false
|
||||
RUN npm config set progress=false
|
||||
|
||||
# install node
|
||||
RUN npm install n -g
|
||||
RUN n $NODE_VERSION
|
||||
|
||||
# download buck
|
||||
RUN git clone https://github.com/facebook/buck.git /opt/buck --branch $BUCK_VERSION --depth=1
|
||||
RUN git clone https://github.com/facebook/buck.git /opt/buck
|
||||
WORKDIR /opt/buck
|
||||
RUN git checkout $BUCK_VERSION
|
||||
|
||||
# build buck
|
||||
RUN ant
|
||||
|
||||
# Full reference at https://dl.google.com/android/repository/repository2-1.xml
|
||||
# download watchman
|
||||
RUN git clone https://github.com/facebook/watchman.git /opt/watchman
|
||||
WORKDIR /opt/watchman
|
||||
RUN git checkout v$WATCHMAN_VERSION
|
||||
|
||||
# build watchman
|
||||
RUN ./autogen.sh
|
||||
RUN ./configure
|
||||
RUN make
|
||||
RUN make install
|
||||
|
||||
# download and unpack android
|
||||
RUN mkdir /opt/android && \
|
||||
cd /opt/android && \
|
||||
curl --silent https://dl.google.com/android/repository/${SDK_VERSION} > android.zip && \
|
||||
unzip android.zip && \
|
||||
rm android.zip
|
||||
RUN mkdir /opt/android
|
||||
WORKDIR /opt/android
|
||||
RUN curl --silent https://dl.google.com/android/repository/tools_r$ANDROID_VERSION-linux.zip > android.zip
|
||||
RUN unzip android.zip
|
||||
RUN rm android.zip
|
||||
|
||||
# download and unpack NDK
|
||||
RUN mkdir /opt/ndk && \
|
||||
cd /opt/ndk && \
|
||||
curl --silent https://dl.google.com/android/repository/android-ndk-r$NDK_VERSION-linux-x86_64.zip > ndk.zip && \
|
||||
unzip ndk.zip && \
|
||||
rm ndk.zip
|
||||
RUN mkdir /opt/ndk
|
||||
WORKDIR /opt/ndk
|
||||
RUN curl --silent https://dl.google.com/android/repository/android-ndk-r$NDK_VERSION-linux-x86_64.zip > ndk.zip
|
||||
RUN unzip ndk.zip
|
||||
|
||||
# cleanup NDK
|
||||
RUN rm ndk.zip
|
||||
|
||||
# Add android SDK tools
|
||||
RUN sdkmanager "system-images;android-19;google_apis;armeabi-v7a" \
|
||||
"platforms;android-$ANDROID_BUILD_VERSION" \
|
||||
"build-tools;$ANDROID_TOOLS_VERSION" \
|
||||
"add-ons;addon-google_apis-google-23" \
|
||||
"extras;android;m2repository"
|
||||
|
||||
# Android SDK Platform-tools, revision 25.0.4
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android SDK Platform-tools, revision 25.0.4" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# Android SDK Build-tools, revision 23.0.1
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android SDK Build-tools, revision 23.0.1" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# SDK Platform Android 6.0, API 23, revision 3
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "SDK Platform Android 6.0, API 23" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# SDK Platform Android 4.4.2, API 19, revision 4
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "SDK Platform Android 4.4.2, API 19, revision 4" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# ARM EABI v7a System Image, Android API 19, revision 5
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "ARM EABI v7a System Image, Android API 19, revision 5" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# Intel x86 Atom System Image, Android API 19, revision 5
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Intel x86 Atom System Image, Android API 19, revision 5" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# Google APIs, Android API 23, revision 1
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Google APIs, Android API 23, revision 1" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# Android Support Repository, revision 45
|
||||
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android Support Repository" | awk '{ print $1 }' | sed 's/.$//')
|
||||
|
||||
# Link adb executable
|
||||
RUN ln -s /opt/android/platform-tools/adb /usr/bin/adb
|
||||
|
||||
# Install google-chrome
|
||||
RUN curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
|
||||
&& echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y google-chrome-stable
|
||||
|
||||
# clean up unnecessary directories
|
||||
RUN rm -rf /opt/android/system-images/android-19/default/x86
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -18,6 +20,7 @@
|
||||
* --package - com.facebook.react.tests
|
||||
* --retries [num] - how many times to retry possible flaky commands: npm install and running tests, default 1
|
||||
*/
|
||||
/*eslint-disable no-undef */
|
||||
|
||||
const argv = require('yargs').argv;
|
||||
const async = require('async');
|
||||
@@ -28,7 +31,7 @@ const path = require('path');
|
||||
const colors = {
|
||||
GREEN: '\x1b[32m',
|
||||
RED: '\x1b[31m',
|
||||
RESET: '\x1b[0m',
|
||||
RESET: '\x1b[0m'
|
||||
};
|
||||
|
||||
const test_opts = {
|
||||
@@ -41,8 +44,8 @@ const test_opts = {
|
||||
TEST_TIMEOUT: parseInt(argv['test-timeout'] || 1000 * 60 * 10),
|
||||
|
||||
OFFSET: argv.offset,
|
||||
COUNT: argv.count,
|
||||
};
|
||||
COUNT: argv.count
|
||||
}
|
||||
|
||||
let max_test_class_length = Number.NEGATIVE_INFINITY;
|
||||
|
||||
@@ -82,14 +85,14 @@ if (test_opts.COUNT != null && test_opts.OFFSET != null) {
|
||||
}
|
||||
|
||||
return async.mapSeries(testClasses, (clazz, callback) => {
|
||||
if (clazz.length > max_test_class_length) {
|
||||
if(clazz.length > max_test_class_length) {
|
||||
max_test_class_length = clazz.length;
|
||||
}
|
||||
|
||||
return async.retry(test_opts.RETRIES, (retryCb) => {
|
||||
const test_process = child_process.spawn('./ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh', [test_opts.PACKAGE, clazz], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
stdio: 'inherit'
|
||||
})
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
test_process.kill();
|
||||
@@ -103,7 +106,7 @@ return async.mapSeries(testClasses, (clazz, callback) => {
|
||||
test_process.on('exit', (code) => {
|
||||
clearTimeout(timeout);
|
||||
|
||||
if (code !== 0) {
|
||||
if(code !== 0) {
|
||||
return retryCb(new Error(`Process exited with code: ${code}`));
|
||||
}
|
||||
|
||||
@@ -112,7 +115,7 @@ return async.mapSeries(testClasses, (clazz, callback) => {
|
||||
}, (err) => {
|
||||
return callback(null, {
|
||||
name: clazz,
|
||||
status: err ? 'failure' : 'success',
|
||||
status: err ? 'failure' : 'success'
|
||||
});
|
||||
});
|
||||
}, (err, results) => {
|
||||
@@ -135,16 +138,16 @@ function print_test_suite_results(results) {
|
||||
function pad_output(num_chars) {
|
||||
let i = 0;
|
||||
|
||||
while (i < num_chars) {
|
||||
while(i < num_chars) {
|
||||
process.stdout.write(' ');
|
||||
i++;
|
||||
}
|
||||
}
|
||||
results.forEach((test) => {
|
||||
if (test.status === 'success') {
|
||||
if(test.status === 'success') {
|
||||
color = colors.GREEN;
|
||||
passing_suites++;
|
||||
} else if (test.status === 'failure') {
|
||||
} else if(test.status === 'failure') {
|
||||
color = colors.RED;
|
||||
failing_suites++;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ watchman shutdown-server
|
||||
node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
|
||||
|
||||
# build test APK
|
||||
source ./scripts/android-setup.sh && NO_BUCKD=1 retry3 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1
|
||||
source ./scripts/circle-ci-android-setup.sh && NO_BUCKD=1 retry3 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1
|
||||
|
||||
# run installed apk with tests
|
||||
node ./ContainerShip/scripts/run-android-ci-instrumentation-tests.js $*
|
||||
|
||||
@@ -230,13 +230,13 @@ function e2e_suite() {
|
||||
# js tests
|
||||
if [ $RUN_JS -ne 0 ]; then
|
||||
# Check the packager produces a bundle (doesn't throw an error)
|
||||
react-native bundle --max-workers 1 --platform android --dev true --entry-file index.js --bundle-output android-bundle.js
|
||||
react-native bundle --max-workers 1 --platform android --dev true --entry-file index.android.js --bundle-output android-bundle.js
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Could not build android bundle"
|
||||
return 1
|
||||
fi
|
||||
|
||||
react-native bundle --max-workers 1 --platform ios --dev true --entry-file index.js --bundle-output ios-bundle.js
|
||||
react-native bundle --max-workers 1 --platform ios --dev true --entry-file index.ios.js --bundle-output ios-bundle.js
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Could not build iOS bundle"
|
||||
return 1
|
||||
|
||||
@@ -29,7 +29,7 @@ def update():
|
||||
# prevent CircleCI from killing the process for inactivity
|
||||
while not done:
|
||||
time.sleep(5)
|
||||
print "Running in background. Waiting for 'adb' command response..."
|
||||
print "Running in background. Waiting for 'adb' command reponse..."
|
||||
|
||||
t = threading.Thread(target=update)
|
||||
t.dameon = True
|
||||
|
||||
@@ -1,43 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule AccessibilityManagerTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {View} = ReactNative;
|
||||
const { View } = ReactNative;
|
||||
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
const {TestModule, AccessibilityManager} = ReactNative.NativeModules;
|
||||
const {
|
||||
TestModule,
|
||||
AccessibilityManager,
|
||||
} = ReactNative.NativeModules;
|
||||
|
||||
class AccessibilityManagerTest extends React.Component<{}> {
|
||||
|
||||
class AccessibilityManagerTest extends React.Component {
|
||||
componentDidMount() {
|
||||
AccessibilityManager.setAccessibilityContentSizeMultipliers({
|
||||
extraSmall: 1.0,
|
||||
small: 2.0,
|
||||
medium: 3.0,
|
||||
large: 4.0,
|
||||
extraLarge: 5.0,
|
||||
extraExtraLarge: 6.0,
|
||||
extraExtraExtraLarge: 7.0,
|
||||
accessibilityMedium: 8.0,
|
||||
accessibilityLarge: 9.0,
|
||||
accessibilityExtraLarge: 10.0,
|
||||
accessibilityExtraExtraLarge: 11.0,
|
||||
accessibilityExtraExtraExtraLarge: 12.0,
|
||||
'extraSmall': 1.0,
|
||||
'small': 2.0,
|
||||
'medium': 3.0,
|
||||
'large': 4.0,
|
||||
'extraLarge': 5.0,
|
||||
'extraExtraLarge': 6.0,
|
||||
'extraExtraExtraLarge': 7.0,
|
||||
'accessibilityMedium': 8.0,
|
||||
'accessibilityLarge': 9.0,
|
||||
'accessibilityExtraLarge': 10.0,
|
||||
'accessibilityExtraExtraLarge': 11.0,
|
||||
'accessibilityExtraExtraExtraLarge': 12.0,
|
||||
});
|
||||
RCTDeviceEventEmitter.addListener('didUpdateDimensions', update => {
|
||||
TestModule.markTestPassed(update.window.fontScale === 4.0);
|
||||
});
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
render(): React.Element<any> {
|
||||
return <View />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @providesModule AppEventsTest
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {NativeAppEventEmitter, StyleSheet, Text, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
NativeAppEventEmitter,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const deepDiffer = require('deepDiffer');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
const TEST_PAYLOAD = {foo: 'bar'};
|
||||
var TEST_PAYLOAD = {foo: 'bar'};
|
||||
|
||||
type AppEvent = {data: Object, ts: number};
|
||||
type AppEvent = { data: Object, ts: number, };
|
||||
type State = {
|
||||
sent: 'none' | AppEvent,
|
||||
received: 'none' | AppEvent,
|
||||
elapsed?: string,
|
||||
};
|
||||
|
||||
class AppEventsTest extends React.Component<{}, State> {
|
||||
class AppEventsTest extends React.Component {
|
||||
state: State = {sent: 'none', received: 'none'};
|
||||
|
||||
componentDidMount() {
|
||||
NativeAppEventEmitter.addListener('testEvent', this.receiveEvent);
|
||||
const event = {data: TEST_PAYLOAD, ts: Date.now()};
|
||||
var event = {data: TEST_PAYLOAD, ts: Date.now()};
|
||||
TestModule.sendAppEvent('testEvent', event);
|
||||
this.setState({sent: event});
|
||||
}
|
||||
@@ -40,7 +46,7 @@ class AppEventsTest extends React.Component<{}, State> {
|
||||
if (deepDiffer(event.data, TEST_PAYLOAD)) {
|
||||
throw new Error('Received wrong event: ' + JSON.stringify(event));
|
||||
}
|
||||
const elapsed = Date.now() - event.ts + 'ms';
|
||||
var elapsed = (Date.now() - event.ts) + 'ms';
|
||||
this.setState({received: event, elapsed}, () => {
|
||||
TestModule.markTestCompleted();
|
||||
});
|
||||
@@ -49,7 +55,9 @@ class AppEventsTest extends React.Component<{}, State> {
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>{JSON.stringify(this.state, null, ' ')}</Text>
|
||||
<Text>
|
||||
{JSON.stringify(this.state, null, ' ')}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -57,7 +65,7 @@ class AppEventsTest extends React.Component<{}, State> {
|
||||
|
||||
AppEventsTest.displayName = 'AppEventsTest';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 40,
|
||||
},
|
||||
|
||||
@@ -1,57 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule AsyncStorageTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {AsyncStorage, Text, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
AsyncStorage,
|
||||
Text,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const deepDiffer = require('deepDiffer');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
const DEBUG = false;
|
||||
var DEBUG = false;
|
||||
|
||||
const KEY_1 = 'key_1';
|
||||
const VAL_1 = 'val_1';
|
||||
const KEY_2 = 'key_2';
|
||||
const VAL_2 = 'val_2';
|
||||
const KEY_MERGE = 'key_merge';
|
||||
const VAL_MERGE_1 = {foo: 1, bar: {hoo: 1, boo: 1}, moo: {a: 3}};
|
||||
const VAL_MERGE_2 = {bar: {hoo: 2}, baz: 2, moo: {a: 3}};
|
||||
const VAL_MERGE_EXPECT = {foo: 1, bar: {hoo: 2, boo: 1}, baz: 2, moo: {a: 3}};
|
||||
var KEY_1 = 'key_1';
|
||||
var VAL_1 = 'val_1';
|
||||
var KEY_2 = 'key_2';
|
||||
var VAL_2 = 'val_2';
|
||||
var KEY_MERGE = 'key_merge';
|
||||
var VAL_MERGE_1 = {'foo': 1, 'bar': {'hoo': 1, 'boo': 1}, 'moo': {'a': 3}};
|
||||
var VAL_MERGE_2 = {'bar': {'hoo': 2}, 'baz': 2, 'moo': {'a': 3}};
|
||||
var VAL_MERGE_EXPECT =
|
||||
{'foo': 1, 'bar': {'hoo': 2, 'boo': 1}, 'baz': 2, 'moo': {'a': 3}};
|
||||
|
||||
// setup in componentDidMount
|
||||
let done = (result: ?boolean) => {};
|
||||
let updateMessage = (message: string) => {};
|
||||
var done = (result : ?boolean) => {};
|
||||
var updateMessage = (message : string ) => {};
|
||||
|
||||
function runTestCase(description: string, fn) {
|
||||
function runTestCase(description : string, fn) {
|
||||
updateMessage(description);
|
||||
fn();
|
||||
}
|
||||
|
||||
function expectTrue(condition: boolean, message: string) {
|
||||
function expectTrue(condition : boolean, message : string) {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
function expectEqual(lhs, rhs, testname: string) {
|
||||
function expectEqual(lhs, rhs, testname : string) {
|
||||
expectTrue(
|
||||
!deepDiffer(lhs, rhs),
|
||||
'Error in test ' +
|
||||
testname +
|
||||
': expected\n' +
|
||||
JSON.stringify(rhs) +
|
||||
'\ngot\n' +
|
||||
JSON.stringify(lhs),
|
||||
'Error in test ' + testname + ': expected\n' + JSON.stringify(rhs) +
|
||||
'\ngot\n' + JSON.stringify(lhs)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,14 +61,11 @@ function expectAsyncNoError(place, err) {
|
||||
if (err instanceof Error) {
|
||||
err = err.message;
|
||||
}
|
||||
expectTrue(
|
||||
err === null,
|
||||
'Unexpected error in ' + place + ': ' + JSON.stringify(err),
|
||||
);
|
||||
expectTrue(err === null, 'Unexpected error in ' + place + ': ' + JSON.stringify(err));
|
||||
}
|
||||
|
||||
function testSetAndGet() {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, err1 => {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, (err1) => {
|
||||
expectAsyncNoError('testSetAndGet/setItem', err1);
|
||||
AsyncStorage.getItem(KEY_1, (err2, result) => {
|
||||
expectAsyncNoError('testSetAndGet/getItem', err2);
|
||||
@@ -87,8 +86,8 @@ function testMissingGet() {
|
||||
}
|
||||
|
||||
function testSetTwice() {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, () => {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, () => {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
|
||||
AsyncStorage.getItem(KEY_1, (err, result) => {
|
||||
expectAsyncNoError('testSetTwice/setItem', err);
|
||||
expectEqual(result, VAL_1, 'testSetTwice');
|
||||
@@ -100,16 +99,16 @@ function testSetTwice() {
|
||||
}
|
||||
|
||||
function testRemoveItem() {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, () => {
|
||||
AsyncStorage.setItem(KEY_2, VAL_2, () => {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
|
||||
AsyncStorage.setItem(KEY_2, VAL_2, ()=>{
|
||||
AsyncStorage.getAllKeys((err, result) => {
|
||||
expectAsyncNoError('testRemoveItem/getAllKeys', err);
|
||||
expectTrue(
|
||||
result.indexOf(KEY_1) >= 0 && result.indexOf(KEY_2) >= 0,
|
||||
'Missing KEY_1 or KEY_2 in ' + '(' + result + ')',
|
||||
'Missing KEY_1 or KEY_2 in ' + '(' + result + ')'
|
||||
);
|
||||
updateMessage('testRemoveItem - add two items');
|
||||
AsyncStorage.removeItem(KEY_1, err2 => {
|
||||
AsyncStorage.removeItem(KEY_1, (err2) => {
|
||||
expectAsyncNoError('testRemoveItem/removeItem', err2);
|
||||
updateMessage('delete successful ');
|
||||
AsyncStorage.getItem(KEY_1, (err3, result2) => {
|
||||
@@ -117,17 +116,17 @@ function testRemoveItem() {
|
||||
expectEqual(
|
||||
result2,
|
||||
null,
|
||||
'testRemoveItem: key_1 present after delete',
|
||||
'testRemoveItem: key_1 present after delete'
|
||||
);
|
||||
updateMessage('key properly removed ');
|
||||
AsyncStorage.getAllKeys((err4, result3) => {
|
||||
expectAsyncNoError('testRemoveItem/getAllKeys', err4);
|
||||
expectTrue(
|
||||
result3.indexOf(KEY_1) === -1,
|
||||
'Unexpected: KEY_1 present in ' + result3,
|
||||
);
|
||||
updateMessage('proper length returned.');
|
||||
runTestCase('should merge values', testMerge);
|
||||
expectAsyncNoError('testRemoveItem/getAllKeys', err4);
|
||||
expectTrue(
|
||||
result3.indexOf(KEY_1) === -1,
|
||||
'Unexpected: KEY_1 present in ' + result3
|
||||
);
|
||||
updateMessage('proper length returned.');
|
||||
runTestCase('should merge values', testMerge);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -137,9 +136,9 @@ function testRemoveItem() {
|
||||
}
|
||||
|
||||
function testMerge() {
|
||||
AsyncStorage.setItem(KEY_MERGE, JSON.stringify(VAL_MERGE_1), err1 => {
|
||||
AsyncStorage.setItem(KEY_MERGE, JSON.stringify(VAL_MERGE_1), (err1) => {
|
||||
expectAsyncNoError('testMerge/setItem', err1);
|
||||
AsyncStorage.mergeItem(KEY_MERGE, JSON.stringify(VAL_MERGE_2), err2 => {
|
||||
AsyncStorage.mergeItem(KEY_MERGE, JSON.stringify(VAL_MERGE_2), (err2) => {
|
||||
expectAsyncNoError('testMerge/mergeItem', err2);
|
||||
AsyncStorage.getItem(KEY_MERGE, (err3, result) => {
|
||||
expectAsyncNoError('testMerge/setItem', err3);
|
||||
@@ -154,35 +153,32 @@ function testMerge() {
|
||||
function testOptimizedMultiGet() {
|
||||
let batch = [[KEY_1, VAL_1], [KEY_2, VAL_2]];
|
||||
let keys = batch.map(([key, value]) => key);
|
||||
AsyncStorage.multiSet(batch, err1 => {
|
||||
AsyncStorage.multiSet(batch, (err1) => {
|
||||
// yes, twice on purpose
|
||||
[1, 2].forEach(i => {
|
||||
;[1, 2].forEach((i) => {
|
||||
expectAsyncNoError(`${i} testOptimizedMultiGet/multiSet`, err1);
|
||||
AsyncStorage.multiGet(keys, (err2, result) => {
|
||||
expectAsyncNoError(`${i} testOptimizedMultiGet/multiGet`, err2);
|
||||
expectEqual(result, batch, `${i} testOptimizedMultiGet multiGet`);
|
||||
updateMessage(
|
||||
'multiGet([key_1, key_2]) correctly returned ' +
|
||||
JSON.stringify(result),
|
||||
);
|
||||
updateMessage('multiGet([key_1, key_2]) correctly returned ' + JSON.stringify(result));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class AsyncStorageTest extends React.Component<{}, $FlowFixMeState> {
|
||||
|
||||
class AsyncStorageTest extends React.Component {
|
||||
state = {
|
||||
messages: 'Initializing...',
|
||||
done: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
done = () =>
|
||||
this.setState({done: true}, () => {
|
||||
TestModule.markTestCompleted();
|
||||
});
|
||||
updateMessage = msg => {
|
||||
done = () => this.setState({done: true}, () => {
|
||||
TestModule.markTestCompleted();
|
||||
});
|
||||
updateMessage = (msg) => {
|
||||
this.setState({messages: this.state.messages.concat('\n' + msg)});
|
||||
DEBUG && console.log(msg);
|
||||
};
|
||||
@@ -193,10 +189,7 @@ class AsyncStorageTest extends React.Component<{}, $FlowFixMeState> {
|
||||
return (
|
||||
<View style={{backgroundColor: 'white', padding: 40}}>
|
||||
<Text>
|
||||
{/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This
|
||||
* comment suppresses an error found when Flow v0.54 was deployed.
|
||||
* To see the error delete this comment and run Flow. */
|
||||
this.constructor.displayName + ': '}
|
||||
{this.constructor.displayName + ': '}
|
||||
{this.state.done ? 'Done' : 'Testing...'}
|
||||
{'\n\n' + this.state.messages}
|
||||
</Text>
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule ImageCachePolicyTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {Image, View, Text, StyleSheet} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
/*
|
||||
* The reload and force-cache tests don't actually verify that the complete functionality.
|
||||
@@ -27,25 +33,22 @@ const {TestModule} = ReactNative.NativeModules;
|
||||
|
||||
const TESTS = ['only-if-cached', 'default', 'reload', 'force-cache'];
|
||||
|
||||
type Props = {};
|
||||
type Props = {}
|
||||
type State = {
|
||||
'only-if-cached'?: boolean,
|
||||
default?: boolean,
|
||||
reload?: boolean,
|
||||
'default'?: boolean,
|
||||
'reload'?: boolean,
|
||||
'force-cache'?: boolean,
|
||||
};
|
||||
}
|
||||
|
||||
class ImageCachePolicyTest extends React.Component<Props, $FlowFixMeState> {
|
||||
state = {};
|
||||
class ImageCachePolicyTest extends React.Component {
|
||||
state = {}
|
||||
|
||||
shouldComponentUpdate(nextProps: Props, nextState: State) {
|
||||
const results: Array<?boolean> = TESTS.map(x => nextState[x]);
|
||||
|
||||
if (!results.includes(undefined)) {
|
||||
const result: boolean = results.reduce(
|
||||
(x, y) => (x === y) === true,
|
||||
true,
|
||||
);
|
||||
const result: boolean = results.reduce((x,y) => x === y === true, true)
|
||||
TestModule.markTestPassed(result);
|
||||
}
|
||||
|
||||
@@ -60,46 +63,38 @@ class ImageCachePolicyTest extends React.Component<Props, $FlowFixMeState> {
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<Text>Hello</Text>
|
||||
<Image
|
||||
source={{
|
||||
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
|
||||
cache: 'only-if-cached'
|
||||
}}
|
||||
onLoad={() => this.testComplete('only-if-cached', false)}
|
||||
onError={() => this.testComplete('only-if-cached', true)}
|
||||
style={styles.base}
|
||||
/>
|
||||
<Image
|
||||
source={{
|
||||
uri:
|
||||
'https://facebook.github.io/react-native/img/favicon.png?cacheBust=notinCache' +
|
||||
Date.now(),
|
||||
cache: 'only-if-cached',
|
||||
}}
|
||||
onLoad={() => this.testComplete('only-if-cached', false)}
|
||||
onError={() => this.testComplete('only-if-cached', true)}
|
||||
style={styles.base}
|
||||
/>
|
||||
<Image
|
||||
source={{
|
||||
uri:
|
||||
'https://facebook.github.io/react-native/img/favicon.png?cacheBust=notinCache' +
|
||||
Date.now(),
|
||||
cache: 'default',
|
||||
}}
|
||||
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
|
||||
cache: 'default'
|
||||
}}
|
||||
onLoad={() => this.testComplete('default', true)}
|
||||
onError={() => this.testComplete('default', false)}
|
||||
style={styles.base}
|
||||
/>
|
||||
<Image
|
||||
source={{
|
||||
uri:
|
||||
'https://facebook.github.io/react-native/img/favicon.png?cacheBust=notinCache' +
|
||||
Date.now(),
|
||||
cache: 'reload',
|
||||
}}
|
||||
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
|
||||
cache: 'reload'
|
||||
}}
|
||||
onLoad={() => this.testComplete('reload', true)}
|
||||
onError={() => this.testComplete('reload', false)}
|
||||
style={styles.base}
|
||||
/>
|
||||
<Image
|
||||
source={{
|
||||
uri:
|
||||
'https://facebook.github.io/react-native/img/favicon.png?cacheBust=notinCache' +
|
||||
Date.now(),
|
||||
cache: 'force-cache',
|
||||
}}
|
||||
uri: 'https://facebook.github.io/react/img/logo_small_2x.png?cacheBust=notinCache' + Date.now(),
|
||||
cache: 'force-cache'
|
||||
}}
|
||||
onLoad={() => this.testComplete('force-cache', true)}
|
||||
onError={() => this.testComplete('force-cache', false)}
|
||||
style={styles.base}
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule ImageSnapshotTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {Image, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
class ImageSnapshotTest extends React.Component<{}> {
|
||||
class ImageSnapshotTest extends React.Component {
|
||||
componentDidMount() {
|
||||
if (!TestModule.verifySnapshot) {
|
||||
throw new Error('TestModule.verifySnapshot not defined.');
|
||||
}
|
||||
}
|
||||
|
||||
done = (success: boolean) => {
|
||||
done = (success : boolean) => {
|
||||
TestModule.markTestPassed(success);
|
||||
};
|
||||
|
||||
@@ -31,8 +35,7 @@ class ImageSnapshotTest extends React.Component<{}> {
|
||||
<Image
|
||||
source={require('./blue_square.png')}
|
||||
defaultSource={require('./red_square.png')}
|
||||
onLoad={() => TestModule.verifySnapshot(this.done)}
|
||||
/>
|
||||
onLoad={() => TestModule.verifySnapshot(this.done)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule IntegrationTestHarnessTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
|
||||
* found when Flow v0.54 was deployed. To see the error delete this comment and
|
||||
* run Flow. */
|
||||
const requestAnimationFrame = require('fbjs/lib/requestAnimationFrame');
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const ReactNative = require('react-native');
|
||||
const {Text, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var requestAnimationFrame = require('fbjs/lib/requestAnimationFrame');
|
||||
var React = require('react');
|
||||
var PropTypes = require('prop-types');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
Text,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
class IntegrationTestHarnessTest extends React.Component<
|
||||
{
|
||||
class IntegrationTestHarnessTest extends React.Component {
|
||||
props: {
|
||||
shouldThrow?: boolean,
|
||||
waitOneFrame?: boolean,
|
||||
},
|
||||
$FlowFixMeState,
|
||||
> {
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
shouldThrow: PropTypes.bool,
|
||||
waitOneFrame: PropTypes.bool,
|
||||
@@ -62,10 +62,7 @@ class IntegrationTestHarnessTest extends React.Component<
|
||||
return (
|
||||
<View style={{backgroundColor: 'white', padding: 40}}>
|
||||
<Text>
|
||||
{/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This
|
||||
* comment suppresses an error found when Flow v0.54 was deployed.
|
||||
* To see the error delete this comment and run Flow. */
|
||||
this.constructor.displayName + ': '}
|
||||
{this.constructor.displayName + ': '}
|
||||
{this.state.done ? 'Done' : 'Testing...'}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule IntegrationTestsApp
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
AppRegistry,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
@@ -22,7 +23,7 @@ const {
|
||||
} = ReactNative;
|
||||
|
||||
// Keep this list in sync with RNTesterIntegrationTests.m
|
||||
const TESTS = [
|
||||
var TESTS = [
|
||||
require('./IntegrationTestHarnessTest'),
|
||||
require('./TimersTest'),
|
||||
require('./AsyncStorageTest'),
|
||||
@@ -32,17 +33,13 @@ const TESTS = [
|
||||
require('./ImageCachePolicyTest'),
|
||||
require('./ImageSnapshotTest'),
|
||||
require('./PromiseTest'),
|
||||
require('./WebViewTest'),
|
||||
require('./SyncMethodTest'),
|
||||
require('./WebSocketTest'),
|
||||
require('./AccessibilityManagerTest'),
|
||||
];
|
||||
|
||||
TESTS.forEach(
|
||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment
|
||||
* suppresses an error found when Flow v0.54 was deployed. To see the error
|
||||
* delete this comment and run Flow. */
|
||||
test => AppRegistry.registerComponent(test.displayName, () => test),
|
||||
(test) => AppRegistry.registerComponent(test.displayName, () => test)
|
||||
);
|
||||
|
||||
// Modules required for integration tests
|
||||
@@ -50,7 +47,7 @@ require('LoggingTestModule');
|
||||
|
||||
type Test = any;
|
||||
|
||||
class IntegrationTestsApp extends React.Component<{}, $FlowFixMeState> {
|
||||
class IntegrationTestsApp extends React.Component {
|
||||
state = {
|
||||
test: (null: ?Test),
|
||||
};
|
||||
@@ -59,9 +56,6 @@ class IntegrationTestsApp extends React.Component<{}, $FlowFixMeState> {
|
||||
if (this.state.test) {
|
||||
return (
|
||||
<ScrollView>
|
||||
{/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
|
||||
* comment suppresses an error when upgrading Flow's support for
|
||||
* React. To see the error delete this comment and run Flow. */}
|
||||
<this.state.test />
|
||||
</ScrollView>
|
||||
);
|
||||
@@ -70,18 +64,20 @@ class IntegrationTestsApp extends React.Component<{}, $FlowFixMeState> {
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.row}>
|
||||
Click on a test to run it in this shell for easier debugging and
|
||||
development. Run all tests in the testing environment with cmd+U in
|
||||
development. Run all tests in the testing environment with cmd+U in
|
||||
Xcode.
|
||||
</Text>
|
||||
<View style={styles.separator} />
|
||||
<ScrollView>
|
||||
{TESTS.map(test => [
|
||||
{TESTS.map((test) => [
|
||||
<TouchableOpacity
|
||||
onPress={() => this.setState({test})}
|
||||
style={styles.row}>
|
||||
<Text style={styles.testName}>{test.displayName}</Text>
|
||||
<Text style={styles.testName}>
|
||||
{test.displayName}
|
||||
</Text>
|
||||
</TouchableOpacity>,
|
||||
<View style={styles.separator} />,
|
||||
<View style={styles.separator} />
|
||||
])}
|
||||
</ScrollView>
|
||||
</View>
|
||||
@@ -89,7 +85,7 @@ class IntegrationTestsApp extends React.Component<{}, $FlowFixMeState> {
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
marginTop: 40,
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @providesModule LayoutEventsTest
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const createReactClass = require('create-react-class');
|
||||
const ReactNative = require('react-native');
|
||||
const {Image, LayoutAnimation, StyleSheet, Text, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var createReactClass = require('create-react-class');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
LayoutAnimation,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const deepDiffer = require('deepDiffer');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
function debug(...args) {
|
||||
// console.log.apply(null, arguments);
|
||||
}
|
||||
|
||||
import type {Layout, LayoutEvent} from 'CoreEventTypes';
|
||||
type Layout = {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
type LayoutEvent = {
|
||||
nativeEvent: {
|
||||
layout: Layout;
|
||||
};
|
||||
};
|
||||
type Style = {
|
||||
margin?: number,
|
||||
padding?: number,
|
||||
@@ -42,7 +59,7 @@ type State = {
|
||||
containerStyle?: Style,
|
||||
};
|
||||
|
||||
const LayoutEventsTest = createReactClass({
|
||||
var LayoutEventsTest = createReactClass({
|
||||
displayName: 'LayoutEventsTest',
|
||||
getInitialState(): State {
|
||||
return {
|
||||
@@ -51,23 +68,27 @@ const LayoutEventsTest = createReactClass({
|
||||
},
|
||||
animateViewLayout: function() {
|
||||
debug('animateViewLayout invoked');
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring, () => {
|
||||
debug('animateViewLayout done');
|
||||
this.checkLayout(this.addWrapText);
|
||||
});
|
||||
LayoutAnimation.configureNext(
|
||||
LayoutAnimation.Presets.spring,
|
||||
() => {
|
||||
debug('animateViewLayout done');
|
||||
this.checkLayout(this.addWrapText);
|
||||
}
|
||||
);
|
||||
this.setState({viewStyle: {margin: 60}});
|
||||
},
|
||||
addWrapText: function() {
|
||||
debug('addWrapText invoked');
|
||||
this.setState(
|
||||
{extraText: ' And a bunch more text to wrap around a few lines.'},
|
||||
() => this.checkLayout(this.changeContainer),
|
||||
() => this.checkLayout(this.changeContainer)
|
||||
);
|
||||
},
|
||||
changeContainer: function() {
|
||||
debug('changeContainer invoked');
|
||||
this.setState({containerStyle: {width: 280}}, () =>
|
||||
this.checkLayout(TestModule.markTestCompleted),
|
||||
this.setState(
|
||||
{containerStyle: {width: 280}},
|
||||
() => this.checkLayout(TestModule.markTestCompleted)
|
||||
);
|
||||
},
|
||||
checkLayout: function(next?: ?Function) {
|
||||
@@ -93,11 +114,10 @@ const LayoutEventsTest = createReactClass({
|
||||
},
|
||||
compare: function(node: string, measured: any, onLayout: any): void {
|
||||
if (deepDiffer(measured, onLayout)) {
|
||||
const data = {measured, onLayout};
|
||||
var data = {measured, onLayout};
|
||||
throw new Error(
|
||||
node +
|
||||
' onLayout mismatch with measure ' +
|
||||
JSON.stringify(data, null, ' '),
|
||||
node + ' onLayout mismatch with measure ' +
|
||||
JSON.stringify(data, null, ' ')
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -114,9 +134,9 @@ const LayoutEventsTest = createReactClass({
|
||||
this.setState({imageLayout: e.nativeEvent.layout}, this.checkLayout);
|
||||
},
|
||||
render: function() {
|
||||
const viewStyle = [styles.view, this.state.viewStyle];
|
||||
const textLayout = this.state.textLayout || {width: '?', height: '?'};
|
||||
const imageLayout = this.state.imageLayout || {x: '?', y: '?'};
|
||||
var viewStyle = [styles.view, this.state.viewStyle];
|
||||
var textLayout = this.state.textLayout || {width: '?', height: '?'};
|
||||
var imageLayout = this.state.imageLayout || {x: '?', y: '?'};
|
||||
debug('viewLayout', this.state.viewLayout);
|
||||
return (
|
||||
<View style={[styles.container, this.state.containerStyle]}>
|
||||
@@ -138,10 +158,10 @@ const LayoutEventsTest = createReactClass({
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 40,
|
||||
},
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @providesModule LoggingTestModule
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const BatchedBridge = require('BatchedBridge');
|
||||
var BatchedBridge = require('BatchedBridge');
|
||||
|
||||
const warning = require('fbjs/lib/warning');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
var warning = require('fbjs/lib/warning');
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
|
||||
const LoggingTestModule = {
|
||||
var LoggingTestModule = {
|
||||
logToConsole: function(str) {
|
||||
console.log(str);
|
||||
},
|
||||
logToConsoleAfterWait: function(str, timeout_ms) {
|
||||
logToConsoleAfterWait: function(str,timeout_ms) {
|
||||
setTimeout(function() {
|
||||
console.log(str);
|
||||
}, timeout_ms);
|
||||
@@ -34,9 +35,12 @@ const LoggingTestModule = {
|
||||
},
|
||||
throwError: function(str) {
|
||||
throw new Error(str);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
BatchedBridge.registerCallableModule('LoggingTestModule', LoggingTestModule);
|
||||
BatchedBridge.registerCallableModule(
|
||||
'LoggingTestModule',
|
||||
LoggingTestModule
|
||||
);
|
||||
|
||||
module.exports = LoggingTestModule;
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule PromiseTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var { View } = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
class PromiseTest extends React.Component<{}> {
|
||||
class PromiseTest extends React.Component {
|
||||
shouldResolve = false;
|
||||
shouldReject = false;
|
||||
shouldSucceedAsync = false;
|
||||
@@ -27,26 +28,24 @@ class PromiseTest extends React.Component<{}> {
|
||||
this.testShouldReject(),
|
||||
this.testShouldSucceedAsync(),
|
||||
this.testShouldThrowAsync(),
|
||||
]).then(() =>
|
||||
TestModule.markTestPassed(
|
||||
this.shouldResolve &&
|
||||
this.shouldReject &&
|
||||
this.shouldSucceedAsync &&
|
||||
this.shouldThrowAsync,
|
||||
),
|
||||
);
|
||||
]).then(() => TestModule.markTestPassed(
|
||||
this.shouldResolve && this.shouldReject &&
|
||||
this.shouldSucceedAsync && this.shouldThrowAsync
|
||||
));
|
||||
}
|
||||
|
||||
testShouldResolve = () => {
|
||||
return TestModule.shouldResolve()
|
||||
.then(() => (this.shouldResolve = true))
|
||||
.catch(() => (this.shouldResolve = false));
|
||||
return TestModule
|
||||
.shouldResolve()
|
||||
.then(() => this.shouldResolve = true)
|
||||
.catch(() => this.shouldResolve = false);
|
||||
};
|
||||
|
||||
testShouldReject = () => {
|
||||
return TestModule.shouldReject()
|
||||
.then(() => (this.shouldReject = false))
|
||||
.catch(() => (this.shouldReject = true));
|
||||
return TestModule
|
||||
.shouldReject()
|
||||
.then(() => this.shouldReject = false)
|
||||
.catch(() => this.shouldReject = true);
|
||||
};
|
||||
|
||||
testShouldSucceedAsync = async (): Promise<any> => {
|
||||
@@ -67,7 +66,7 @@ class PromiseTest extends React.Component<{}> {
|
||||
}
|
||||
};
|
||||
|
||||
render(): React.Node {
|
||||
render(): React.Element<any> {
|
||||
return <View />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* 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.
|
||||
* @providesModule PropertiesUpdateTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {View} = ReactNative;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
View,
|
||||
} = ReactNative;
|
||||
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
class PropertiesUpdateTest extends React.Component {
|
||||
render() {
|
||||
if (this.props.markTestPassed) {
|
||||
TestModule.markTestPassed(true);
|
||||
}
|
||||
return <View />;
|
||||
return (
|
||||
<View/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @providesModule RCTRootViewIntegrationTestApp
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
require('regenerator-runtime/runtime');
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
|
||||
const {
|
||||
var {
|
||||
AppRegistry,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
@@ -24,14 +25,14 @@ const {
|
||||
} = ReactNative;
|
||||
|
||||
/* Keep this list in sync with RCTRootViewIntegrationTests.m */
|
||||
const TESTS = [
|
||||
var TESTS = [
|
||||
require('./PropertiesUpdateTest'),
|
||||
require('./ReactContentSizeUpdateTest'),
|
||||
require('./SizeFlexibilityUpdateTest'),
|
||||
];
|
||||
|
||||
TESTS.forEach(test =>
|
||||
AppRegistry.registerComponent(test.displayName, () => test),
|
||||
TESTS.forEach(
|
||||
(test) => AppRegistry.registerComponent(test.displayName, () => test)
|
||||
);
|
||||
|
||||
class RCTRootViewIntegrationTestApp extends React.Component {
|
||||
@@ -51,18 +52,20 @@ class RCTRootViewIntegrationTestApp extends React.Component {
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.row}>
|
||||
Click on a test to run it in this shell for easier debugging and
|
||||
development. Run all tests in the testing environment with cmd+U in
|
||||
development. Run all tests in the testing environment with cmd+U in
|
||||
Xcode.
|
||||
</Text>
|
||||
<View style={styles.separator} />
|
||||
<ScrollView>
|
||||
{TESTS.map(test => [
|
||||
{TESTS.map((test) => [
|
||||
<TouchableOpacity
|
||||
onPress={() => this.setState({test})}
|
||||
style={styles.row}>
|
||||
<Text style={styles.testName}>{test.displayName}</Text>
|
||||
<Text style={styles.testName}>
|
||||
{test.displayName}
|
||||
</Text>
|
||||
</TouchableOpacity>,
|
||||
<View style={styles.separator} />,
|
||||
<View style={styles.separator} />
|
||||
])}
|
||||
</ScrollView>
|
||||
</View>
|
||||
@@ -70,7 +73,7 @@ class RCTRootViewIntegrationTestApp extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
marginTop: 40,
|
||||
@@ -88,7 +91,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent(
|
||||
'RCTRootViewIntegrationTestApp',
|
||||
() => RCTRootViewIntegrationTestApp,
|
||||
);
|
||||
AppRegistry.registerComponent('RCTRootViewIntegrationTestApp', () => RCTRootViewIntegrationTestApp);
|
||||
|
||||
@@ -1,39 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* 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.
|
||||
* @providesModule ReactContentSizeUpdateTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const createReactClass = require('create-react-class');
|
||||
const ReactNative = require('react-native');
|
||||
const RCTNativeAppEventEmitter = require('RCTNativeAppEventEmitter');
|
||||
const Subscribable = require('Subscribable');
|
||||
const TimerMixin = require('react-timer-mixin');
|
||||
var React = require('react');
|
||||
var createReactClass = require('create-react-class');
|
||||
var ReactNative = require('react-native');
|
||||
var RCTNativeAppEventEmitter = require('RCTNativeAppEventEmitter');
|
||||
var Subscribable = require('Subscribable');
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
|
||||
const {View} = ReactNative;
|
||||
var { View } = ReactNative;
|
||||
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const reactViewWidth = 101;
|
||||
const reactViewHeight = 102;
|
||||
const newReactViewWidth = 201;
|
||||
const newReactViewHeight = 202;
|
||||
var reactViewWidth = 101;
|
||||
var reactViewHeight = 102;
|
||||
var newReactViewWidth = 201;
|
||||
var newReactViewHeight = 202;
|
||||
|
||||
const ReactContentSizeUpdateTest = createReactClass({
|
||||
var ReactContentSizeUpdateTest = createReactClass({
|
||||
displayName: 'ReactContentSizeUpdateTest',
|
||||
mixins: [Subscribable.Mixin, TimerMixin],
|
||||
mixins: [Subscribable.Mixin,
|
||||
TimerMixin],
|
||||
|
||||
UNSAFE_componentWillMount: function() {
|
||||
componentWillMount: function() {
|
||||
this.addListenerOn(
|
||||
RCTNativeAppEventEmitter,
|
||||
'rootViewDidChangeIntrinsicSize',
|
||||
this.rootViewDidChangeIntrinsicSize,
|
||||
this.rootViewDidChangeIntrinsicSize
|
||||
);
|
||||
},
|
||||
|
||||
@@ -52,25 +53,23 @@ const ReactContentSizeUpdateTest = createReactClass({
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.setTimeout(() => {
|
||||
this.updateViewSize();
|
||||
}, 1000);
|
||||
this.setTimeout(
|
||||
() => { this.updateViewSize(); },
|
||||
1000
|
||||
);
|
||||
},
|
||||
|
||||
rootViewDidChangeIntrinsicSize: function(intrinsicSize) {
|
||||
if (
|
||||
intrinsicSize.height === newReactViewHeight &&
|
||||
intrinsicSize.width === newReactViewWidth
|
||||
) {
|
||||
if (intrinsicSize.height === newReactViewHeight && intrinsicSize.width === newReactViewWidth) {
|
||||
TestModule.markTestPassed(true);
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{height: this.state.height, width: this.state.width}} />
|
||||
<View style={{'height':this.state.height, 'width':this.state.width}}/>
|
||||
);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
ReactContentSizeUpdateTest.displayName = 'ReactContentSizeUpdateTest';
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule SimpleSnapshotTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
|
||||
* found when Flow v0.54 was deployed. To see the error delete this comment and
|
||||
* run Flow. */
|
||||
const requestAnimationFrame = require('fbjs/lib/requestAnimationFrame');
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var requestAnimationFrame = require('fbjs/lib/requestAnimationFrame');
|
||||
|
||||
const {StyleSheet, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
class SimpleSnapshotTest extends React.Component<{}> {
|
||||
class SimpleSnapshotTest extends React.Component {
|
||||
componentDidMount() {
|
||||
if (!TestModule.verifySnapshot) {
|
||||
throw new Error('TestModule.verifySnapshot not defined.');
|
||||
@@ -28,7 +29,7 @@ class SimpleSnapshotTest extends React.Component<{}> {
|
||||
requestAnimationFrame(() => TestModule.verifySnapshot(this.done));
|
||||
}
|
||||
|
||||
done = (success: boolean) => {
|
||||
done = (success : boolean) => {
|
||||
TestModule.markTestPassed(success);
|
||||
};
|
||||
|
||||
@@ -42,7 +43,7 @@ class SimpleSnapshotTest extends React.Component<{}> {
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
var styles = StyleSheet.create({
|
||||
box1: {
|
||||
width: 80,
|
||||
height: 50,
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* 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.
|
||||
* @providesModule SizeFlexibilityUpdateTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const createReactClass = require('create-react-class');
|
||||
const ReactNative = require('react-native');
|
||||
const RCTNativeAppEventEmitter = require('RCTNativeAppEventEmitter');
|
||||
const Subscribable = require('Subscribable');
|
||||
const {View} = ReactNative;
|
||||
var React = require('react');
|
||||
var createReactClass = require('create-react-class');
|
||||
var ReactNative = require('react-native');
|
||||
var RCTNativeAppEventEmitter = require('RCTNativeAppEventEmitter');
|
||||
var Subscribable = require('Subscribable');
|
||||
var { View } = ReactNative;
|
||||
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const reactViewWidth = 111;
|
||||
const reactViewHeight = 222;
|
||||
var reactViewWidth = 111;
|
||||
var reactViewHeight = 222;
|
||||
|
||||
let finalState = false;
|
||||
var finalState = false;
|
||||
|
||||
const SizeFlexibilityUpdateTest = createReactClass({
|
||||
var SizeFlexibilityUpdateTest = createReactClass({
|
||||
displayName: 'SizeFlexibilityUpdateTest',
|
||||
mixins: [Subscribable.Mixin],
|
||||
|
||||
UNSAFE_componentWillMount: function() {
|
||||
componentWillMount: function() {
|
||||
this.addListenerOn(
|
||||
RCTNativeAppEventEmitter,
|
||||
'rootViewDidChangeIntrinsicSize',
|
||||
this.rootViewDidChangeIntrinsicSize,
|
||||
this.rootViewDidChangeIntrinsicSize
|
||||
);
|
||||
},
|
||||
|
||||
@@ -41,6 +41,7 @@ const SizeFlexibilityUpdateTest = createReactClass({
|
||||
},
|
||||
|
||||
rootViewDidChangeIntrinsicSize: function(intrinsicSize) {
|
||||
|
||||
if (finalState) {
|
||||
// If a test reaches its final state, it is not expected to do anything more
|
||||
TestModule.markTestPassed(false);
|
||||
@@ -48,37 +49,25 @@ const SizeFlexibilityUpdateTest = createReactClass({
|
||||
}
|
||||
|
||||
if (this.props.both) {
|
||||
if (
|
||||
intrinsicSize.width === reactViewWidth &&
|
||||
intrinsicSize.height === reactViewHeight
|
||||
) {
|
||||
if (intrinsicSize.width === reactViewWidth && intrinsicSize.height === reactViewHeight) {
|
||||
this.markPassed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.props.height) {
|
||||
if (
|
||||
intrinsicSize.width !== reactViewWidth &&
|
||||
intrinsicSize.height === reactViewHeight
|
||||
) {
|
||||
if (intrinsicSize.width !== reactViewWidth && intrinsicSize.height === reactViewHeight) {
|
||||
this.markPassed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.props.width) {
|
||||
if (
|
||||
intrinsicSize.width === reactViewWidth &&
|
||||
intrinsicSize.height !== reactViewHeight
|
||||
) {
|
||||
if (intrinsicSize.width === reactViewWidth && intrinsicSize.height !== reactViewHeight) {
|
||||
this.markPassed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.props.none) {
|
||||
if (
|
||||
intrinsicSize.width !== reactViewWidth &&
|
||||
intrinsicSize.height !== reactViewHeight
|
||||
) {
|
||||
if (intrinsicSize.width !== reactViewWidth && intrinsicSize.height !== reactViewHeight) {
|
||||
this.markPassed();
|
||||
return;
|
||||
}
|
||||
@@ -86,8 +75,10 @@ const SizeFlexibilityUpdateTest = createReactClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
return <View style={{height: reactViewHeight, width: reactViewWidth}} />;
|
||||
},
|
||||
return (
|
||||
<View style={{'height':reactViewHeight, 'width':reactViewWidth}}/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
SizeFlexibilityUpdateTest.displayName = 'SizeFlexibilityUpdateTest';
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule SyncMethodTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {View} = ReactNative;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var { View } = ReactNative;
|
||||
|
||||
const {TestModule, RNTesterTestModule} = ReactNative.NativeModules;
|
||||
const {
|
||||
TestModule,
|
||||
RNTesterTestModule,
|
||||
} = ReactNative.NativeModules;
|
||||
|
||||
class SyncMethodTest extends React.Component<{}> {
|
||||
|
||||
class SyncMethodTest extends React.Component {
|
||||
componentDidMount() {
|
||||
if (
|
||||
RNTesterTestModule.echoString('test string value') !== 'test string value'
|
||||
) {
|
||||
if (RNTesterTestModule.echoString('test string value') !== 'test string value') {
|
||||
throw new Error('Something wrong with sync method export');
|
||||
}
|
||||
if (RNTesterTestModule.methodThatReturnsNil() != null) {
|
||||
@@ -29,7 +32,7 @@ class SyncMethodTest extends React.Component<{}> {
|
||||
TestModule.markTestCompleted();
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
render(): React.Element<any> {
|
||||
return <View />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule TimersTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const createReactClass = require('create-react-class');
|
||||
const ReactNative = require('react-native');
|
||||
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
|
||||
* found when Flow v0.54 was deployed. To see the error delete this comment and
|
||||
* run Flow. */
|
||||
const TimerMixin = require('react-timer-mixin');
|
||||
var React = require('react');
|
||||
var createReactClass = require('create-react-class');
|
||||
var ReactNative = require('react-native');
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
|
||||
const {StyleSheet, Text, View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const TimersTest = createReactClass({
|
||||
var TimersTest = createReactClass({
|
||||
displayName: 'TimersTest',
|
||||
mixins: [TimerMixin],
|
||||
|
||||
@@ -70,29 +72,26 @@ const TimersTest = createReactClass({
|
||||
},
|
||||
|
||||
testClearTimeout0() {
|
||||
const timeout = this.setTimeout(() => this._fail('testClearTimeout0'), 0);
|
||||
var timeout = this.setTimeout(() => this._fail('testClearTimeout0'), 0);
|
||||
this.clearTimeout(timeout);
|
||||
this.testClearTimeout30();
|
||||
},
|
||||
|
||||
testClearTimeout30() {
|
||||
const timeout = this.setTimeout(() => this._fail('testClearTimeout30'), 30);
|
||||
var timeout = this.setTimeout(() => this._fail('testClearTimeout30'), 30);
|
||||
this.clearTimeout(timeout);
|
||||
this.setTimeout(this.testClearMulti, 50);
|
||||
},
|
||||
|
||||
testClearMulti() {
|
||||
const fails = [];
|
||||
var fails = [];
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-1'), 20));
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-2'), 50));
|
||||
const delayClear = this.setTimeout(
|
||||
() => this._fail('testClearMulti-3'),
|
||||
50,
|
||||
);
|
||||
var delayClear = this.setTimeout(() => this._fail('testClearMulti-3'), 50);
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-4'), 0));
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-5'), 10));
|
||||
|
||||
fails.forEach(timeout => this.clearTimeout(timeout));
|
||||
fails.forEach((timeout) => this.clearTimeout(timeout));
|
||||
this.setTimeout(() => this.clearTimeout(delayClear), 20);
|
||||
|
||||
this.setTimeout(this.testOrdering, 50);
|
||||
@@ -100,35 +99,25 @@ const TimersTest = createReactClass({
|
||||
|
||||
testOrdering() {
|
||||
// Clear timers are set first because it's more likely to uncover bugs.
|
||||
let fail0;
|
||||
var fail0;
|
||||
this.setImmediate(() => this.clearTimeout(fail0));
|
||||
fail0 = this.setTimeout(
|
||||
() =>
|
||||
this._fail(
|
||||
'testOrdering-t0, setImmediate should happen before ' +
|
||||
'setTimeout 0',
|
||||
),
|
||||
0,
|
||||
() => this._fail('testOrdering-t0, setImmediate should happen before ' +
|
||||
'setTimeout 0'),
|
||||
0
|
||||
);
|
||||
let failAnim; // This should fail without the t=0 fastpath feature.
|
||||
var failAnim; // This should fail without the t=0 fastpath feature.
|
||||
this.setTimeout(() => this.cancelAnimationFrame(failAnim), 0);
|
||||
failAnim = this.requestAnimationFrame(() =>
|
||||
this._fail(
|
||||
'testOrdering-Anim, setTimeout 0 should happen before ' +
|
||||
'requestAnimationFrame',
|
||||
),
|
||||
failAnim = this.requestAnimationFrame(
|
||||
() => this._fail('testOrdering-Anim, setTimeout 0 should happen before ' +
|
||||
'requestAnimationFrame')
|
||||
);
|
||||
let fail25;
|
||||
this.setTimeout(() => {
|
||||
this.clearTimeout(fail25);
|
||||
}, 20);
|
||||
var fail25;
|
||||
this.setTimeout(() => { this.clearTimeout(fail25); }, 20);
|
||||
fail25 = this.setTimeout(
|
||||
() =>
|
||||
this._fail(
|
||||
'testOrdering-t25, setTimeout 20 should happen before ' +
|
||||
'setTimeout 25',
|
||||
),
|
||||
25,
|
||||
() => this._fail('testOrdering-t25, setTimeout 20 should happen before ' +
|
||||
'setTimeout 25'),
|
||||
25
|
||||
);
|
||||
this.setTimeout(this.done, 50);
|
||||
},
|
||||
@@ -163,12 +152,12 @@ const TimersTest = createReactClass({
|
||||
this.setState({count: this.state.count + 1});
|
||||
},
|
||||
|
||||
_fail(caller: string): void {
|
||||
_fail(caller : string) : void {
|
||||
throw new Error('_fail called by ' + caller);
|
||||
},
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
padding: 40,
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
* @providesModule WebSocketTest
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {View} = ReactNative;
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var { View } = ReactNative;
|
||||
var { TestModule } = ReactNative.NativeModules;
|
||||
|
||||
const DEFAULT_WS_URL = 'ws://localhost:5555/';
|
||||
|
||||
const WS_EVENTS = ['close', 'error', 'message', 'open'];
|
||||
const WS_EVENTS = [
|
||||
'close',
|
||||
'error',
|
||||
'message',
|
||||
'open',
|
||||
];
|
||||
const WS_STATES = [
|
||||
/* 0 */ 'CONNECTING',
|
||||
/* 1 */ 'OPEN',
|
||||
@@ -26,17 +32,17 @@ const WS_STATES = [
|
||||
];
|
||||
|
||||
type State = {
|
||||
url: string,
|
||||
fetchStatus: ?string,
|
||||
socket: ?WebSocket,
|
||||
socketState: ?number,
|
||||
lastSocketEvent: ?string,
|
||||
lastMessage: ?string | ?ArrayBuffer,
|
||||
testMessage: string,
|
||||
testExpectedResponse: string,
|
||||
url: string;
|
||||
fetchStatus: ?string;
|
||||
socket: ?WebSocket;
|
||||
socketState: ?number;
|
||||
lastSocketEvent: ?string;
|
||||
lastMessage: ?string | ?ArrayBuffer;
|
||||
testMessage: string;
|
||||
testExpectedResponse: string;
|
||||
};
|
||||
|
||||
class WebSocketTest extends React.Component<{}, State> {
|
||||
class WebSocketTest extends React.Component {
|
||||
state: State = {
|
||||
url: DEFAULT_WS_URL,
|
||||
fetchStatus: null,
|
||||
@@ -45,13 +51,13 @@ class WebSocketTest extends React.Component<{}, State> {
|
||||
lastSocketEvent: null,
|
||||
lastMessage: null,
|
||||
testMessage: 'testMessage',
|
||||
testExpectedResponse: 'testMessage_response',
|
||||
testExpectedResponse: 'testMessage_response'
|
||||
};
|
||||
|
||||
_waitFor = (condition: any, timeout: any, callback: any) => {
|
||||
let remaining = timeout;
|
||||
let t;
|
||||
const timeoutFunction = function() {
|
||||
var remaining = timeout;
|
||||
var t;
|
||||
var timeoutFunction = function() {
|
||||
if (condition()) {
|
||||
callback(true);
|
||||
return;
|
||||
@@ -60,11 +66,11 @@ class WebSocketTest extends React.Component<{}, State> {
|
||||
if (remaining === 0) {
|
||||
callback(false);
|
||||
} else {
|
||||
t = setTimeout(timeoutFunction, 1000);
|
||||
t = setTimeout(timeoutFunction,1000);
|
||||
}
|
||||
};
|
||||
t = setTimeout(timeoutFunction, 1000);
|
||||
};
|
||||
t = setTimeout(timeoutFunction,1000);
|
||||
}
|
||||
|
||||
_connect = () => {
|
||||
const socket = new WebSocket(this.state.url);
|
||||
@@ -77,11 +83,11 @@ class WebSocketTest extends React.Component<{}, State> {
|
||||
|
||||
_socketIsConnected = () => {
|
||||
return this.state.socketState === 1; //'OPEN'
|
||||
};
|
||||
}
|
||||
|
||||
_socketIsDisconnected = () => {
|
||||
return this.state.socketState === 3; //'CLOSED'
|
||||
};
|
||||
}
|
||||
|
||||
_disconnect = () => {
|
||||
if (!this.state.socket) {
|
||||
@@ -113,7 +119,7 @@ class WebSocketTest extends React.Component<{}, State> {
|
||||
};
|
||||
|
||||
_receivedTestExpectedResponse = () => {
|
||||
return this.state.lastMessage === this.state.testExpectedResponse;
|
||||
return (this.state.lastMessage === this.state.testExpectedResponse);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
@@ -121,44 +127,38 @@ class WebSocketTest extends React.Component<{}, State> {
|
||||
}
|
||||
|
||||
testConnect = () => {
|
||||
const component = this;
|
||||
var component = this;
|
||||
component._connect();
|
||||
component._waitFor(component._socketIsConnected, 5, function(
|
||||
connectSucceeded,
|
||||
) {
|
||||
component._waitFor(component._socketIsConnected, 5, function(connectSucceeded) {
|
||||
if (!connectSucceeded) {
|
||||
TestModule.markTestPassed(false);
|
||||
return;
|
||||
}
|
||||
component.testSendAndReceive();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
testSendAndReceive = () => {
|
||||
const component = this;
|
||||
var component = this;
|
||||
component._sendTestMessage();
|
||||
component._waitFor(component._receivedTestExpectedResponse, 5, function(
|
||||
messageReceived,
|
||||
) {
|
||||
component._waitFor(component._receivedTestExpectedResponse, 5, function(messageReceived) {
|
||||
if (!messageReceived) {
|
||||
TestModule.markTestPassed(false);
|
||||
return;
|
||||
}
|
||||
component.testDisconnect();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
testDisconnect = () => {
|
||||
const component = this;
|
||||
var component = this;
|
||||
component._disconnect();
|
||||
component._waitFor(component._socketIsDisconnected, 5, function(
|
||||
disconnectSucceeded,
|
||||
) {
|
||||
component._waitFor(component._socketIsDisconnected, 5, function(disconnectSucceeded) {
|
||||
TestModule.markTestPassed(disconnectSucceeded);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
render(): React.Element<any> {
|
||||
return <View />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {WebView} = ReactNative;
|
||||
|
||||
const {TestModule} = ReactNative.NativeModules;
|
||||
|
||||
class WebViewTest extends React.Component {
|
||||
render() {
|
||||
let firstMessageReceived = false;
|
||||
let secondMessageReceived = false;
|
||||
function processMessage(e) {
|
||||
const message = e.nativeEvent.data;
|
||||
if (message === 'First') {
|
||||
firstMessageReceived = true;
|
||||
}
|
||||
if (message === 'Second') {
|
||||
secondMessageReceived = true;
|
||||
}
|
||||
|
||||
// got both messages
|
||||
if (firstMessageReceived && secondMessageReceived) {
|
||||
TestModule.markTestPassed(true);
|
||||
}
|
||||
// wait for next message
|
||||
else if (firstMessageReceived && !secondMessageReceived) {
|
||||
return;
|
||||
}
|
||||
// first message got lost
|
||||
else if (!firstMessageReceived && secondMessageReceived) {
|
||||
throw new Error('First message got lost');
|
||||
}
|
||||
}
|
||||
const html =
|
||||
'Hello world' +
|
||||
'<script>' +
|
||||
"window.setTimeout(function(){window.postMessage('First'); window.postMessage('Second')}, 0)" +
|
||||
'</script>';
|
||||
|
||||
// fail if messages didn't get through;
|
||||
window.setTimeout(function() {
|
||||
throw new Error(
|
||||
firstMessageReceived
|
||||
? 'Both messages got lost'
|
||||
: 'Second message got lost',
|
||||
);
|
||||
}, 10000);
|
||||
|
||||
const source = {
|
||||
html: html,
|
||||
};
|
||||
|
||||
return (
|
||||
<WebView
|
||||
source={source}
|
||||
onMessage={processMessage}
|
||||
originWhitelist={['about:blank']}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WebViewTest.displayName = 'WebViewTest';
|
||||
|
||||
module.exports = WebViewTest;
|
||||
@@ -1,9 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2015-present, Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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 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.
|
||||
|
||||
# Set terminal title
|
||||
echo -en "\033]0;Web Socket Test Server\a"
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @providesModule websocket_integration_test_server
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
|
||||
* found when Flow v0.54 was deployed. To see the error delete this comment and
|
||||
* run Flow. */
|
||||
const WebSocket = require('ws');
|
||||
|
||||
console.log(`\
|
||||
@@ -27,8 +26,8 @@ An incoming message of 'exit' will shut down the server.
|
||||
`);
|
||||
|
||||
const server = new WebSocket.Server({port: 5555});
|
||||
server.on('connection', ws => {
|
||||
ws.on('message', message => {
|
||||
server.on('connection', (ws) => {
|
||||
ws.on('message', (message) => {
|
||||
console.log('Received message:', message);
|
||||
if (message === 'exit') {
|
||||
console.log('WebSocket integration test server exit');
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#import "JSContextRef.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void nativeProfilerEnableBytecode(void);
|
||||
void nativeProfilerStart(JSContextRef ctx, const char *title);
|
||||
void nativeProfilerEnd(JSContextRef ctx, const char *title, const char *filename);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
#include "JSCLegacyProfiler.h"
|
||||
|
||||
#include "APICast.h"
|
||||
#include "LegacyProfiler.h"
|
||||
#include "OpaqueJSString.h"
|
||||
#include "JSProfilerPrivate.h"
|
||||
#include "JSStringRef.h"
|
||||
#include "String.h"
|
||||
#include "Options.h"
|
||||
|
||||
enum json_gen_status {
|
||||
json_gen_status_ok = 0,
|
||||
json_gen_status_error = 1,
|
||||
};
|
||||
|
||||
enum json_entry {
|
||||
json_entry_key,
|
||||
json_entry_value,
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct json_state {
|
||||
FILE *fileOut;
|
||||
bool hasFirst;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
typedef json_state *json_gen;
|
||||
|
||||
static void json_escaped_cstring_printf(json_gen gen, const char *str) {
|
||||
const char *cursor = str;
|
||||
fputc('"', gen->fileOut);
|
||||
while (*cursor) {
|
||||
const char *escape = nullptr;
|
||||
switch (*cursor) {
|
||||
case '"':
|
||||
escape = "\\\"";
|
||||
break;
|
||||
case '\b':
|
||||
escape = "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
escape = "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
escape = "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
escape = "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
escape = "\\t";
|
||||
break;
|
||||
case '\\':
|
||||
escape = "\\\\";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (escape != nullptr) {
|
||||
fwrite(escape, 1, strlen(escape), gen->fileOut);
|
||||
} else {
|
||||
fputc(*cursor, gen->fileOut);
|
||||
}
|
||||
cursor++;
|
||||
}
|
||||
fputc('"', gen->fileOut);
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_key_cstring(json_gen gen, const char *buffer) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
json_escaped_cstring_printf(gen, buffer);
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_map_open(json_gen gen, json_entry entryType) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (entryType == json_entry_value) {
|
||||
fprintf(gen->fileOut, ":");
|
||||
} else if (entryType == json_entry_key) {
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
}
|
||||
fprintf(gen->fileOut, "{");
|
||||
gen->hasFirst = false;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_map_close(json_gen gen) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
fprintf(gen->fileOut, "}");
|
||||
gen->hasFirst = true;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_array_open(json_gen gen, json_entry entryType) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (entryType == json_entry_value) {
|
||||
fprintf(gen->fileOut, ":");
|
||||
} else if (entryType == json_entry_key) {
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
}
|
||||
fprintf(gen->fileOut, "[");
|
||||
gen->hasFirst = false;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_array_close(json_gen gen) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
fprintf(gen->fileOut, "]");
|
||||
gen->hasFirst = true;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_keyvalue_cstring(json_gen gen, const char *key, const char *value) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
fprintf(gen->fileOut, "\"%s\" : ", key);
|
||||
json_escaped_cstring_printf(gen, value);
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
|
||||
static json_gen_status json_gen_keyvalue_integer(json_gen gen, const char *key, int value) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
fprintf(gen->fileOut, "\"%s\": %d", key, value);
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_keyvalue_double(json_gen gen, const char *key, double value) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
fprintf(gen->fileOut, "\"%s\": %.20g", key, value);
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen json_gen_alloc(const char *fileName) {
|
||||
json_gen gen = (json_gen)malloc(sizeof(json_state));
|
||||
memset(gen, 0, sizeof(json_state));
|
||||
gen->fileOut = fopen(fileName, "wb");
|
||||
return gen;
|
||||
}
|
||||
|
||||
static void json_gen_free(json_gen gen) {
|
||||
if (gen->fileOut) {
|
||||
fclose(gen->fileOut);
|
||||
}
|
||||
free(gen);
|
||||
}
|
||||
|
||||
#define GEN_AND_CHECK(expr) \
|
||||
do { \
|
||||
json_gen_status GEN_AND_CHECK_status = (expr); \
|
||||
if (GEN_AND_CHECK_status != json_gen_status_ok) { \
|
||||
return GEN_AND_CHECK_status; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
|
||||
static json_gen_status append_children_array_json(json_gen gen, const JSC::ProfileNode *node);
|
||||
static json_gen_status append_node_json(json_gen gen, const JSC::ProfileNode *node);
|
||||
|
||||
static json_gen_status append_root_json(json_gen gen, const JSC::Profile *profile) {
|
||||
GEN_AND_CHECK(json_gen_map_open(gen, json_entry_key));
|
||||
GEN_AND_CHECK(json_gen_key_cstring(gen, "rootNodes"));
|
||||
#if IOS8
|
||||
GEN_AND_CHECK(append_children_array_json(gen, profile->head()));
|
||||
#else
|
||||
GEN_AND_CHECK(append_children_array_json(gen, profile->rootNode()));
|
||||
#endif
|
||||
GEN_AND_CHECK(json_gen_map_close(gen));
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status append_children_array_json(json_gen gen, const JSC::ProfileNode *node) {
|
||||
GEN_AND_CHECK(json_gen_array_open(gen, json_entry_value));
|
||||
for (RefPtr<JSC::ProfileNode> child : node->children()) {
|
||||
GEN_AND_CHECK(append_node_json(gen, child.get()));
|
||||
}
|
||||
GEN_AND_CHECK(json_gen_array_close(gen));
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status append_node_json(json_gen gen, const JSC::ProfileNode *node) {
|
||||
GEN_AND_CHECK(json_gen_map_open(gen, json_entry_key));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_integer(gen, "id", node->id()));
|
||||
|
||||
if (!node->functionName().isEmpty()) {
|
||||
GEN_AND_CHECK(json_gen_keyvalue_cstring(gen, "functionName", node->functionName().utf8().data()));
|
||||
}
|
||||
|
||||
if (!node->url().isEmpty()) {
|
||||
GEN_AND_CHECK(json_gen_keyvalue_cstring(gen, "url", node->url().utf8().data()));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_integer(gen, "lineNumber", node->lineNumber()));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_integer(gen, "columnNumber", node->columnNumber()));
|
||||
}
|
||||
|
||||
GEN_AND_CHECK(json_gen_key_cstring(gen, "calls"));
|
||||
GEN_AND_CHECK(json_gen_array_open(gen, json_entry_value));
|
||||
for (const JSC::ProfileNode::Call &call : node->calls()) {
|
||||
GEN_AND_CHECK(json_gen_map_open(gen, json_entry_key));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_double(gen, "startTime", call.startTime()));
|
||||
#if IOS8
|
||||
GEN_AND_CHECK(json_gen_keyvalue_double(gen, "totalTime", call.totalTime()));
|
||||
#else
|
||||
GEN_AND_CHECK(json_gen_keyvalue_double(gen, "totalTime", call.elapsedTime()));
|
||||
#endif
|
||||
GEN_AND_CHECK(json_gen_map_close(gen));
|
||||
}
|
||||
GEN_AND_CHECK(json_gen_array_close(gen));
|
||||
|
||||
if (!node->children().isEmpty()) {
|
||||
GEN_AND_CHECK(json_gen_key_cstring(gen, "children"));
|
||||
GEN_AND_CHECK(append_children_array_json(gen, node));
|
||||
}
|
||||
|
||||
GEN_AND_CHECK(json_gen_map_close(gen));
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static void convert_to_json(const JSC::Profile *profile, const char *filename) {
|
||||
json_gen_status status;
|
||||
json_gen gen = json_gen_alloc(filename);
|
||||
|
||||
status = append_root_json(gen, profile);
|
||||
if (status != json_gen_status_ok) {
|
||||
FILE *fileOut = fopen(filename, "wb");
|
||||
if (fileOut != nullptr) {
|
||||
fprintf(fileOut, "{\"error\": %d}", (int)status);
|
||||
fclose(fileOut);
|
||||
}
|
||||
}
|
||||
json_gen_free(gen);
|
||||
}
|
||||
|
||||
// Based on JSEndProfiling, with a little extra code to return the profile as JSON.
|
||||
static void JSEndProfilingAndRender(JSContextRef ctx, const char *title, const char *filename)
|
||||
{
|
||||
JSC::ExecState *exec = toJS(ctx);
|
||||
JSC::LegacyProfiler *profiler = JSC::LegacyProfiler::profiler();
|
||||
RefPtr<JSC::Profile> rawProfile = profiler->stopProfiling(exec, WTF::String(title));
|
||||
convert_to_json(rawProfile.get(), filename);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void nativeProfilerEnableBytecode(void)
|
||||
{
|
||||
JSC::Options::setOption("forceProfilerBytecodeGeneration=true");
|
||||
}
|
||||
|
||||
void nativeProfilerStart(JSContextRef ctx, const char *title) {
|
||||
JSStartProfiling(ctx, JSStringCreateWithUTF8CString(title));
|
||||
}
|
||||
|
||||
void nativeProfilerEnd(JSContextRef ctx, const char *title, const char *filename) {
|
||||
JSEndProfilingAndRender(ctx, title, filename);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
ios9:
|
||||
IOS_VERSION=9 \
|
||||
JSC_VERSION=7601.1.46.3 \
|
||||
WEB_CORE_VERSION=7601.1.46.10 \
|
||||
WTF_VERSION=7601.1.46.3 \
|
||||
make -f Makefile.base
|
||||
|
||||
ios8:
|
||||
IOS_VERSION=8 \
|
||||
JSC_VERSION=7600.1.17 \
|
||||
WEB_CORE_VERSION=7600.1.25 \
|
||||
WTF_VERSION=7600.1.24 \
|
||||
make -f Makefile.base
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -rf $(wildcard *.dylib)
|
||||
-rm -rf download
|
||||
@@ -0,0 +1,80 @@
|
||||
HEADER_PATHS := `find download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION) -name '*.h' | xargs -I{} dirname {} | uniq | xargs -I{} echo "-I {}"`
|
||||
|
||||
XCODE_PATH ?= $(shell xcode-select -p)
|
||||
SDK_PATH = $(XCODE_PATH)/Platforms/$1.platform/Developer/SDKs/$1.sdk
|
||||
SDK_VERSION = $(shell plutil -convert json -o - $(call SDK_PATH,iPhoneOS)/SDKSettings.plist | awk -f parseSDKVersion.awk)
|
||||
|
||||
CERT ?= iPhone Developer
|
||||
|
||||
ARCHS = x86_64 arm64 armv7 i386
|
||||
|
||||
PLATFORM = \
|
||||
if [[ "$*" = "x86_64" || "$*" = "i386" ]]; then \
|
||||
PLATFORM=iPhoneSimulator; \
|
||||
else \
|
||||
PLATFORM=iPhoneOS; \
|
||||
fi;
|
||||
|
||||
SYSROOT = -isysroot $(call SDK_PATH,$${PLATFORM})
|
||||
|
||||
IOS_LIBS = \
|
||||
download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION) \
|
||||
download/WebCore/WebCore-$(WEB_CORE_VERSION) \
|
||||
download/WTF/WTF-$(WTF_VERSION) \
|
||||
download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION)/Bytecodes.h
|
||||
|
||||
IOS_EXT=ios$(IOS_VERSION)
|
||||
|
||||
ifneq ($(SDK_VERSION), $(IOS_VERSION))
|
||||
|
||||
all:
|
||||
$(error "Expected to be compiled with iOS SDK version 8, found $(SDK_VERSION)")
|
||||
|
||||
else
|
||||
|
||||
all: RCTJSCProfiler.$(IOS_EXT).dylib /tmp/RCTJSCProfiler
|
||||
cp $^
|
||||
|
||||
endif
|
||||
|
||||
/tmp/RCTJSCProfiler:
|
||||
mkdir -p $@
|
||||
|
||||
RCTJSCProfiler.$(IOS_EXT).dylib: RCTJSCProfiler_unsigned.$(IOS_EXT).dylib
|
||||
cp $< $@
|
||||
codesign -f -s "${CERT}" $@
|
||||
|
||||
.PRECIOUS: RCTJSCProfiler_unsigned.$(IOS_EXT).dylib
|
||||
RCTJSCProfiler_unsigned.$(IOS_EXT).dylib: $(patsubst %,RCTJSCProfiler_%.$(IOS_EXT).dylib,$(ARCHS))
|
||||
lipo -create -output $@ $^
|
||||
|
||||
.PRECIOUS: RCTJSCProfiler_%.$(IOS_EXT).dylib
|
||||
RCTJSCProfiler_%.$(IOS_EXT).dylib: $(IOS_LIBS)
|
||||
$(PLATFORM) \
|
||||
clang -w -dynamiclib -o RCTJSCProfiler_$*.$(IOS_EXT).dylib -std=c++11 \
|
||||
-arch $* \
|
||||
-install_name RCTJSCProfiler.$(IOS_EXT).dylib \
|
||||
-include ./download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION)/config.h \
|
||||
-I download \
|
||||
-I download/WebCore/WebCore-$(WEB_CORE_VERSION)/icu \
|
||||
-I download/WTF/WTF-$(WTF_VERSION) \
|
||||
-DNDEBUG=1 \
|
||||
-DIOS$(IOS_VERSION)=1 \
|
||||
-miphoneos-version-min=8.0 \
|
||||
$(SYSROOT) \
|
||||
$(HEADER_PATHS) \
|
||||
-undefined dynamic_lookup \
|
||||
JSCLegacyProfiler.mm
|
||||
|
||||
.PRECIOUS: %/Bytecodes.h
|
||||
%/Bytecodes.h:
|
||||
python $*/generate-bytecode-files --bytecodes_h $@ $*/bytecode/BytecodeList.json
|
||||
|
||||
.PRECIOUS: download/%
|
||||
download/%: download/%.tar.gz
|
||||
tar -zxvf $< -C `dirname $@` > /dev/null
|
||||
|
||||
.PRECIOUS: %.tar.gz
|
||||
%.tar.gz:
|
||||
mkdir -p `dirname $@`
|
||||
curl -o $@ http://www.opensource.apple.com/tarballs/$(patsubst download/%,%,$@)
|
||||
Executable
+254
@@ -0,0 +1,254 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import smap
|
||||
import trace_data
|
||||
import urllib
|
||||
|
||||
SECONDS_TO_NANOSECONDS = (1000*1000)
|
||||
SAMPLE_DELTA_IN_SECONDS = 0.0001
|
||||
|
||||
class Marker(object):
|
||||
def __init__(self, _name, _timestamp, _depth, _is_end, _ident, url, line, col):
|
||||
self.name = _name
|
||||
self.timestamp = _timestamp
|
||||
self.depth = _depth
|
||||
self.is_end = _is_end
|
||||
self.ident = _ident
|
||||
self.url = url
|
||||
self.line = line
|
||||
self.col = col
|
||||
|
||||
# sort markers making sure they are ordered by timestamp then depth of function call
|
||||
# and finally that markers of the same ident are sorted in the order begin then end
|
||||
def __cmp__(self, other):
|
||||
if self.timestamp < other.timestamp:
|
||||
return -1
|
||||
if self.timestamp > other.timestamp:
|
||||
return 1
|
||||
if self.depth < other.depth:
|
||||
return -1
|
||||
if self.depth > other.depth:
|
||||
return 1
|
||||
if self.ident == other.ident:
|
||||
if self.is_end:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# calculate marker name based on combination of function name and location
|
||||
def _calcname(entry):
|
||||
funcname = ""
|
||||
if "functionName" in entry:
|
||||
funcname = funcname + entry["functionName"]
|
||||
return funcname
|
||||
|
||||
def _calcurl(mapcache, entry, map_file):
|
||||
if entry.url not in mapcache:
|
||||
map_url = entry.url.replace('.bundle', '.map')
|
||||
|
||||
if map_url != entry.url:
|
||||
if map_file:
|
||||
print('Loading sourcemap from:' + map_file)
|
||||
map_url = map_file
|
||||
|
||||
try:
|
||||
url_file = urllib.urlopen(map_url)
|
||||
if url_file != None:
|
||||
entries = smap.parse(url_file)
|
||||
mapcache[entry.url] = entries
|
||||
except Exception, e:
|
||||
mapcache[entry.url] = []
|
||||
|
||||
if entry.url in mapcache:
|
||||
source_entry = smap.find(mapcache[entry.url], entry.line, entry.col)
|
||||
if source_entry:
|
||||
entry.url = 'file://' + source_entry.src
|
||||
entry.line = source_entry.src_line
|
||||
entry.col = source_entry.src_col
|
||||
|
||||
def _compute_markers(markers, call_point, depth):
|
||||
name = _calcname(call_point)
|
||||
ident = len(markers)
|
||||
url = ""
|
||||
lineNumber = -1
|
||||
columnNumber = -1
|
||||
if "url" in call_point:
|
||||
url = call_point["url"]
|
||||
if "lineNumber" in call_point:
|
||||
lineNumber = call_point["lineNumber"]
|
||||
if "columnNumber" in call_point:
|
||||
columnNumber = call_point["columnNumber"]
|
||||
|
||||
for call in call_point["calls"]:
|
||||
markers.append(Marker(name, call["startTime"], depth, 0, ident, url, lineNumber, columnNumber))
|
||||
markers.append(Marker(name, call["startTime"] + call["totalTime"], depth, 1, ident, url, lineNumber, columnNumber))
|
||||
ident = ident + 2
|
||||
if "children" in call_point:
|
||||
for child in call_point["children"]:
|
||||
_compute_markers(markers, child, depth+1);
|
||||
|
||||
def _find_child(children, name):
|
||||
for child in children:
|
||||
if child['functionName'] == name:
|
||||
return child
|
||||
return None
|
||||
|
||||
def _add_entry_cpuprofiler_program(newtime, cpuprofiler):
|
||||
curnode = _find_child(cpuprofiler['head']['children'], '(program)')
|
||||
if cpuprofiler['lastTime'] != None:
|
||||
lastTime = cpuprofiler['lastTime']
|
||||
while lastTime < newtime:
|
||||
curnode['hitCount'] += 1
|
||||
cpuprofiler['samples'].append(curnode['callUID'])
|
||||
cpuprofiler['timestamps'].append(int(lastTime*SECONDS_TO_NANOSECONDS))
|
||||
lastTime += SAMPLE_DELTA_IN_SECONDS
|
||||
cpuprofiler['lastTime'] = lastTime
|
||||
else:
|
||||
cpuprofiler['lastTime'] = newtime
|
||||
|
||||
|
||||
def _add_entry_cpuprofiler(stack, newtime, cpuprofiler):
|
||||
index = len(stack) - 1
|
||||
marker = stack[index]
|
||||
|
||||
if marker.name not in cpuprofiler['markers']:
|
||||
cpuprofiler['markers'][marker.name] = cpuprofiler['id']
|
||||
cpuprofiler['callUID'] += 1
|
||||
callUID = cpuprofiler['markers'][marker.name]
|
||||
|
||||
curnode = cpuprofiler['head']
|
||||
index = 0
|
||||
while index < len(stack):
|
||||
newnode = _find_child(curnode['children'], stack[index].name)
|
||||
if newnode == None:
|
||||
newnode = {}
|
||||
newnode['callUID'] = callUID
|
||||
newnode['url'] = marker.url
|
||||
newnode['functionName'] = stack[index].name
|
||||
newnode['hitCount'] = 0
|
||||
newnode['lineNumber'] = marker.line
|
||||
newnode['columnNumber'] = marker.col
|
||||
newnode['scriptId'] = callUID
|
||||
newnode['positionTicks'] = []
|
||||
newnode['id'] = cpuprofiler['id']
|
||||
cpuprofiler['id'] += 1
|
||||
newnode['children'] = []
|
||||
curnode['children'].append(newnode)
|
||||
curnode['deoptReason'] = ''
|
||||
curnode = newnode
|
||||
index += 1
|
||||
|
||||
if cpuprofiler['lastTime'] == None:
|
||||
cpuprofiler['lastTime'] = newtime
|
||||
|
||||
if cpuprofiler['lastTime'] != None:
|
||||
lastTime = cpuprofiler['lastTime']
|
||||
while lastTime < newtime:
|
||||
curnode['hitCount'] += 1
|
||||
if len(curnode['positionTicks']) == 0:
|
||||
ticks = {}
|
||||
ticks['line'] = curnode['callUID']
|
||||
ticks['ticks'] = 0
|
||||
curnode['positionTicks'].append(ticks)
|
||||
curnode['positionTicks'][0]['ticks'] += 1
|
||||
cpuprofiler['samples'].append(curnode['callUID'])
|
||||
cpuprofiler['timestamps'].append(int(lastTime*1000*1000))
|
||||
lastTime += 0.0001
|
||||
cpuprofiler['lastTime'] = lastTime
|
||||
|
||||
def _create_default_cpuprofiler_node(name, _id, _uid):
|
||||
return {'functionName': name,
|
||||
'scriptId':'0',
|
||||
'url':'',
|
||||
'lineNumber':0,
|
||||
'columnNumber':0,
|
||||
'positionTicks':[],
|
||||
'id':_id,
|
||||
'callUID':_uid,
|
||||
'children': [],
|
||||
'hitCount': 0,
|
||||
'deoptReason':''}
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Converts JSON profile format to fbsystrace text output")
|
||||
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
dest = "output_file",
|
||||
default = None,
|
||||
help = "Output file for trace data")
|
||||
parser.add_argument(
|
||||
"-cpuprofiler",
|
||||
dest = "output_cpuprofiler",
|
||||
default = None,
|
||||
help = "Output file for cpuprofiler data")
|
||||
parser.add_argument(
|
||||
"-map",
|
||||
dest = "map_file",
|
||||
default = None,
|
||||
help = "Map file for symbolicating")
|
||||
parser.add_argument( "file", help = "JSON trace input_file")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
markers = []
|
||||
with open(args.file, "r") as trace_file:
|
||||
trace = json.load(trace_file)
|
||||
for root_entry in trace["rootNodes"]:
|
||||
_compute_markers(markers, root_entry, 0)
|
||||
|
||||
mapcache = {}
|
||||
for m in markers:
|
||||
_calcurl(mapcache, m, args.map_file)
|
||||
|
||||
sorted_markers = list(sorted(markers));
|
||||
|
||||
if args.output_cpuprofiler != None:
|
||||
cpuprofiler = {}
|
||||
cpuprofiler['startTime'] = None
|
||||
cpuprofiler['endTime'] = None
|
||||
cpuprofiler['lastTime'] = None
|
||||
cpuprofiler['id'] = 4
|
||||
cpuprofiler['callUID'] = 4
|
||||
cpuprofiler['samples'] = []
|
||||
cpuprofiler['timestamps'] = []
|
||||
cpuprofiler['markers'] = {}
|
||||
cpuprofiler['head'] = _create_default_cpuprofiler_node('(root)', 1, 1)
|
||||
cpuprofiler['head']['children'].append(_create_default_cpuprofiler_node('(root)', 2, 2))
|
||||
cpuprofiler['head']['children'].append(_create_default_cpuprofiler_node('(program)', 3, 3))
|
||||
marker_stack = []
|
||||
with open(args.output_cpuprofiler, 'w') as file_out:
|
||||
for marker in sorted_markers:
|
||||
if len(marker_stack):
|
||||
_add_entry_cpuprofiler(marker_stack, marker.timestamp, cpuprofiler)
|
||||
else:
|
||||
_add_entry_cpuprofiler_program(marker.timestamp, cpuprofiler)
|
||||
if marker.is_end:
|
||||
marker_stack.pop()
|
||||
else:
|
||||
marker_stack.append(marker)
|
||||
cpuprofiler['startTime'] = cpuprofiler['timestamps'][0] / 1000000.0
|
||||
cpuprofiler['endTime'] = cpuprofiler['timestamps'][len(cpuprofiler['timestamps']) - 1] / 1000000.0
|
||||
json.dump(cpuprofiler, file_out, sort_keys=False, indent=4, separators=(',', ': '))
|
||||
|
||||
|
||||
if args.output_file != None:
|
||||
with open(args.output_file,"w") as trace_file:
|
||||
for marker in sorted_markers:
|
||||
start_or_end = None
|
||||
if marker.is_end:
|
||||
start_or_end = "E"
|
||||
else:
|
||||
start_or_end = "B"
|
||||
#output with timestamp at high level of precision
|
||||
trace_file.write("json-0 [000] .... {0:.12f}: tracing_mark_write: {1}|0|{2}\n".format(
|
||||
marker.timestamp,
|
||||
start_or_end,
|
||||
marker.name))
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,10 @@
|
||||
BEGIN {
|
||||
FS = ":"
|
||||
RS = ","
|
||||
}
|
||||
|
||||
/"Version"/ {
|
||||
version = substr($2, 2, length($2) - 2)
|
||||
print int(version)
|
||||
exit 0
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
"""
|
||||
adapted from https://github.com/martine/python-sourcemap into a reuasable module
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2010
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
"""A module for parsing source maps, as output by the Closure and
|
||||
CoffeeScript compilers and consumed by browsers. See
|
||||
http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
|
||||
"""
|
||||
|
||||
import collections
|
||||
import json
|
||||
import sys
|
||||
import bisect
|
||||
|
||||
class entry(object):
|
||||
def __init__(self, dst_line, dst_col, src, src_line, src_col):
|
||||
self.dst_line = dst_line
|
||||
self.dst_col = dst_col
|
||||
self.src = src
|
||||
self.src_line = src_line
|
||||
self.src_col = src_col
|
||||
|
||||
def __cmp__(self, other):
|
||||
#print(self)
|
||||
#print(other)
|
||||
if self.dst_line < other.dst_line:
|
||||
return -1
|
||||
if self.dst_line > other.dst_line:
|
||||
return 1
|
||||
if self.dst_col < other.dst_col:
|
||||
return -1
|
||||
if self.dst_col > other.dst_col:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
SmapState = collections.namedtuple(
|
||||
'SmapState', ['dst_line', 'dst_col',
|
||||
'src', 'src_line', 'src_col',
|
||||
'name'])
|
||||
|
||||
# Mapping of base64 letter -> integer value.
|
||||
B64 = dict((c, i) for i, c in
|
||||
enumerate('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||
'0123456789+/'))
|
||||
|
||||
|
||||
def _parse_vlq(segment):
|
||||
"""Parse a string of VLQ-encoded data.
|
||||
|
||||
Returns:
|
||||
a list of integers.
|
||||
"""
|
||||
|
||||
values = []
|
||||
|
||||
cur, shift = 0, 0
|
||||
for c in segment:
|
||||
val = B64[c]
|
||||
# Each character is 6 bits:
|
||||
# 5 of value and the high bit is the continuation.
|
||||
val, cont = val & 0b11111, val >> 5
|
||||
cur += val << shift
|
||||
shift += 5
|
||||
|
||||
if not cont:
|
||||
# The low bit of the unpacked value is the sign.
|
||||
cur, sign = cur >> 1, cur & 1
|
||||
if sign:
|
||||
cur = -cur
|
||||
values.append(cur)
|
||||
cur, shift = 0, 0
|
||||
|
||||
if cur or shift:
|
||||
raise Exception('leftover cur/shift in vlq decode')
|
||||
|
||||
return values
|
||||
|
||||
|
||||
def _parse_smap(file):
|
||||
"""Given a file-like object, yield SmapState()s as they are read from it."""
|
||||
|
||||
smap = json.load(file)
|
||||
sources = smap['sources']
|
||||
names = smap['names']
|
||||
mappings = smap['mappings']
|
||||
lines = mappings.split(';')
|
||||
|
||||
dst_col, src_id, src_line, src_col, name_id = 0, 0, 0, 0, 0
|
||||
for dst_line, line in enumerate(lines):
|
||||
segments = line.split(',')
|
||||
dst_col = 0
|
||||
for segment in segments:
|
||||
if not segment:
|
||||
continue
|
||||
parsed = _parse_vlq(segment)
|
||||
dst_col += parsed[0]
|
||||
|
||||
src = None
|
||||
name = None
|
||||
if len(parsed) > 1:
|
||||
src_id += parsed[1]
|
||||
src = sources[src_id]
|
||||
src_line += parsed[2]
|
||||
src_col += parsed[3]
|
||||
|
||||
if len(parsed) > 4:
|
||||
name_id += parsed[4]
|
||||
name = names[name_id]
|
||||
|
||||
assert dst_line >= 0
|
||||
assert dst_col >= 0
|
||||
assert src_line >= 0
|
||||
assert src_col >= 0
|
||||
|
||||
yield SmapState(dst_line, dst_col, src, src_line, src_col, name)
|
||||
|
||||
def find(entries, line, col):
|
||||
test = entry(line, col, '', 0, 0)
|
||||
index = bisect.bisect_right(entries, test)
|
||||
if index == 0:
|
||||
return None
|
||||
return entries[index - 1]
|
||||
|
||||
def parse(file):
|
||||
# Simple demo that shows files that most contribute to total size.
|
||||
lookup = []
|
||||
for state in _parse_smap(file):
|
||||
lookup.append(entry(state.dst_line, state.dst_col, state.src, state.src_line, state.src_col))
|
||||
|
||||
sorted_lookup = list(sorted(lookup))
|
||||
return sorted_lookup
|
||||
@@ -0,0 +1,244 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import re
|
||||
import unittest
|
||||
|
||||
"""
|
||||
# _-----=> irqs-off
|
||||
# / _----=> need-resched
|
||||
# | / _---=> hardirq/softirq
|
||||
# || / _--=> preempt-depth
|
||||
# ||| / delay
|
||||
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
|
||||
# | | | |||| | |
|
||||
<idle>-0 [001] ...2 3269.291072: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120
|
||||
"""
|
||||
TRACE_LINE_PATTERN = re.compile(
|
||||
r'^\s*(?P<task>.+)-(?P<pid>\d+)\s+(?:\((?P<tgid>.+)\)\s+)?\[(?P<cpu>\d+)\]\s+(?:(?P<flags>\S{4})\s+)?(?P<timestamp>[0-9.]+):\s+(?P<function>.+)$')
|
||||
|
||||
"""
|
||||
Example lines from custom app traces:
|
||||
0: B|27295|providerRemove
|
||||
0: E
|
||||
tracing_mark_write: S|27311|NNFColdStart<D-7744962>|1112249168
|
||||
"""
|
||||
APP_TRACE_LINE_PATTERN = re.compile(
|
||||
r'^(?P<type>.+?): (?P<args>.+)$')
|
||||
|
||||
"""
|
||||
Example section names:
|
||||
NNFColdStart
|
||||
NNFColdStart<0><T7744962>
|
||||
NNFColdStart<X>
|
||||
NNFColdStart<T7744962>
|
||||
"""
|
||||
DECORATED_SECTION_NAME_PATTERN = re.compile(r'^(?P<section_name>.*?)(?:<0>)?(?:<(?P<command>.)(?P<argument>.*?)>)?$')
|
||||
|
||||
SYSTRACE_LINE_TYPES = set(['0', 'tracing_mark_write'])
|
||||
|
||||
class TraceLine(object):
|
||||
def __init__(self, task, pid, tgid, cpu, flags, timestamp, function):
|
||||
self.task = task
|
||||
self.pid = pid
|
||||
self.tgid = tgid
|
||||
self.cpu = cpu
|
||||
self.flags = flags
|
||||
self.timestamp = timestamp
|
||||
self.function = function
|
||||
self.canceled = False
|
||||
|
||||
@property
|
||||
def is_app_trace_line(self):
|
||||
return isinstance(self.function, AppTraceFunction)
|
||||
|
||||
def cancel(self):
|
||||
self.canceled = True
|
||||
|
||||
def __str__(self):
|
||||
if self.canceled:
|
||||
return ""
|
||||
elif self.tgid:
|
||||
return "{task:>16s}-{pid:<5d} ({tgid:5s}) [{cpu:03d}] {flags:4s} {timestamp:12f}: {function}\n".format(**vars(self))
|
||||
elif self.flags:
|
||||
return "{task:>16s}-{pid:<5d} [{cpu:03d}] {flags:4s} {timestamp:12f}: {function}\n".format(**vars(self))
|
||||
else:
|
||||
return "{task:>16s}-{pid:<5d} [{cpu:03d}] {timestamp:12.6f}: {function}\n".format(**vars(self))
|
||||
|
||||
|
||||
class AppTraceFunction(object):
|
||||
def __init__(self, type, args):
|
||||
self.type = type
|
||||
self.args = args
|
||||
self.operation = args[0]
|
||||
|
||||
if len(args) >= 2 and args[1]:
|
||||
self.pid = int(args[1])
|
||||
if len(args) >= 3:
|
||||
self._section_name, self.command, self.argument = _parse_section_name(args[2])
|
||||
args[2] = self._section_name
|
||||
else:
|
||||
self._section_name = None
|
||||
self.command = None
|
||||
self.argument = None
|
||||
self.cookie = None
|
||||
|
||||
@property
|
||||
def section_name(self):
|
||||
return self._section_name
|
||||
|
||||
@section_name.setter
|
||||
def section_name(self, value):
|
||||
self._section_name = value
|
||||
self.args[2] = value
|
||||
|
||||
def __str__(self):
|
||||
return "{type}: {args}".format(type=self.type, args='|'.join(self.args))
|
||||
|
||||
|
||||
class AsyncTraceFunction(AppTraceFunction):
|
||||
def __init__(self, type, args):
|
||||
super(AsyncTraceFunction, self).__init__(type, args)
|
||||
|
||||
self.cookie = int(args[3])
|
||||
|
||||
|
||||
TRACE_TYPE_MAP = {
|
||||
'S': AsyncTraceFunction,
|
||||
'T': AsyncTraceFunction,
|
||||
'F': AsyncTraceFunction,
|
||||
}
|
||||
|
||||
def parse_line(line):
|
||||
match = TRACE_LINE_PATTERN.match(line.strip())
|
||||
if not match:
|
||||
return None
|
||||
|
||||
task = match.group("task")
|
||||
pid = int(match.group("pid"))
|
||||
tgid = match.group("tgid")
|
||||
cpu = int(match.group("cpu"))
|
||||
flags = match.group("flags")
|
||||
timestamp = float(match.group("timestamp"))
|
||||
function = match.group("function")
|
||||
|
||||
app_trace = _parse_function(function)
|
||||
if app_trace:
|
||||
function = app_trace
|
||||
|
||||
return TraceLine(task, pid, tgid, cpu, flags, timestamp, function)
|
||||
|
||||
def parse_dextr_line(line):
|
||||
task = line["name"]
|
||||
pid = line["pid"]
|
||||
tgid = line["tid"]
|
||||
cpu = None
|
||||
flags = None
|
||||
timestamp = line["ts"]
|
||||
function = AppTraceFunction("DextrTrace", [line["ph"], line["pid"], line["name"]])
|
||||
|
||||
return TraceLine(task, pid, tgid, cpu, flags, timestamp, function)
|
||||
|
||||
|
||||
def _parse_function(function):
|
||||
line_match = APP_TRACE_LINE_PATTERN.match(function)
|
||||
if not line_match:
|
||||
return None
|
||||
|
||||
type = line_match.group("type")
|
||||
if not type in SYSTRACE_LINE_TYPES:
|
||||
return None
|
||||
|
||||
args = line_match.group("args").split('|')
|
||||
if len(args) == 1 and len(args[0]) == 0:
|
||||
args = None
|
||||
|
||||
constructor = TRACE_TYPE_MAP.get(args[0], AppTraceFunction)
|
||||
return constructor(type, args)
|
||||
|
||||
|
||||
def _parse_section_name(section_name):
|
||||
if section_name is None:
|
||||
return section_name, None, None
|
||||
|
||||
section_name_match = DECORATED_SECTION_NAME_PATTERN.match(section_name)
|
||||
section_name = section_name_match.group("section_name")
|
||||
command = section_name_match.group("command")
|
||||
argument = section_name_match.group("argument")
|
||||
return section_name, command, argument
|
||||
|
||||
|
||||
def _format_section_name(section_name, command, argument):
|
||||
if not command:
|
||||
return section_name
|
||||
|
||||
return "{section_name}<{command}{argument}>".format(**vars())
|
||||
|
||||
|
||||
class RoundTripFormattingTests(unittest.TestCase):
|
||||
def testPlainSectionName(self):
|
||||
section_name = "SectionName12345-5562342fas"
|
||||
|
||||
self.assertEqual(section_name, _format_section_name(*_parse_section_name(section_name)))
|
||||
|
||||
def testDecoratedSectionName(self):
|
||||
section_name = "SectionName12345-5562342fas<D-123456>"
|
||||
|
||||
self.assertEqual(section_name, _format_section_name(*_parse_section_name(section_name)))
|
||||
|
||||
def testSimpleFunction(self):
|
||||
function = "0: E"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithoutCookie(self):
|
||||
function = "0: B|27295|providerRemove"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithCookie(self):
|
||||
function = "0: S|27311|NNFColdStart|1112249168"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithCookieAndArgs(self):
|
||||
function = "0: T|27311|NNFColdStart|1122|Start"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithArgsButNoPid(self):
|
||||
function = "0: E|||foo=bar"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testKitKatFunction(self):
|
||||
function = "tracing_mark_write: B|14127|Looper.dispatchMessage|arg=>>>>> Dispatching to Handler (android.os.Handler) {422ae980} null: 0|Java"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testNonSysTraceFunctionIgnored(self):
|
||||
function = "sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120"
|
||||
|
||||
self.assertEqual(None, _parse_function(function))
|
||||
|
||||
def testLineWithFlagsAndTGID(self):
|
||||
line = " <idle>-0 ( 550) [000] d..2 7953.258473: cpu_idle: state=1 cpu_id=0\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
|
||||
def testLineWithFlagsAndNoTGID(self):
|
||||
line = " <idle>-0 (-----) [000] d..2 7953.258473: cpu_idle: state=1 cpu_id=0\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
|
||||
def testLineWithFlags(self):
|
||||
line = " <idle>-0 [001] ...2 3269.291072: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
|
||||
def testLineWithoutFlags(self):
|
||||
line = " <idle>-0 [001] 3269.291072: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
@@ -1,21 +1,30 @@
|
||||
MIT License
|
||||
BSD License
|
||||
|
||||
Copyright (c) 2015-present, Facebook, Inc.
|
||||
For React Native software
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name Facebook nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
__tests__
|
||||
@@ -152,10 +152,7 @@
|
||||
0CF68AF71AF0549300FF9E5C /* RCTConvert+ART.m */,
|
||||
0CF68AC21AF0540F00FF9E5C /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
0CF68AC21AF0540F00FF9E5C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
@@ -361,7 +358,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -396,7 +393,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
// A little helper to make sure we have the right memory allocation ready for use.
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTGroup.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTNode.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTRenderable.h"
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @providesModule ARTSerializablePath
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// TODO: Move this into an ART mode called "serialized" or something
|
||||
|
||||
const Class = require('art/core/class.js');
|
||||
const Path = require('art/core/path.js');
|
||||
var Class = require('art/core/class.js');
|
||||
var Path = require('art/core/path.js');
|
||||
|
||||
const MOVE_TO = 0;
|
||||
const CLOSE = 1;
|
||||
const LINE_TO = 2;
|
||||
const CURVE_TO = 3;
|
||||
const ARC = 4;
|
||||
var MOVE_TO = 0;
|
||||
var CLOSE = 1;
|
||||
var LINE_TO = 2;
|
||||
var CURVE_TO = 3;
|
||||
var ARC = 4;
|
||||
|
||||
var SerializablePath = Class(Path, {
|
||||
|
||||
const SerializablePath = Class(Path, {
|
||||
initialize: function(path) {
|
||||
this.reset();
|
||||
if (path instanceof SerializablePath) {
|
||||
@@ -55,18 +57,7 @@ const SerializablePath = Class(Path, {
|
||||
onArc: function(sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation) {
|
||||
if (rx !== ry || rotation) {
|
||||
return this._arcToBezier(
|
||||
sx,
|
||||
sy,
|
||||
ex,
|
||||
ey,
|
||||
cx,
|
||||
cy,
|
||||
rx,
|
||||
ry,
|
||||
sa,
|
||||
ea,
|
||||
ccw,
|
||||
rotation,
|
||||
sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation
|
||||
);
|
||||
}
|
||||
this.path.push(ARC, cx, cy, rx, sa, ea, ccw ? 0 : 1);
|
||||
@@ -78,7 +69,8 @@ const SerializablePath = Class(Path, {
|
||||
|
||||
toJSON: function() {
|
||||
return this.path;
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = SerializablePath;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTShape.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTSurfaceView.h"
|
||||
@@ -13,15 +15,6 @@
|
||||
|
||||
@implementation ARTSurfaceView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.opaque = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
||||
{
|
||||
[super insertReactSubview:subview atIndex:atIndex];
|
||||
@@ -53,4 +46,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reactSetInheritedBackgroundColor:(UIColor *)inheritedBackgroundColor
|
||||
{
|
||||
self.backgroundColor = inheritedBackgroundColor;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTText.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTBrush.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTBrush.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTLinearGradient.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTBrush.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTPattern.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTBrush.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTRadialGradient.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTBrush.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTSolidColor.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "RCTConvert+ART.h"
|
||||
@@ -49,7 +51,7 @@
|
||||
CGPathAddArc(path, NULL, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE == 0);
|
||||
break;
|
||||
default:
|
||||
RCTLogError(@"Invalid CGPath type %llu at element %llu of %@", (unsigned long long)type, (unsigned long long)i, arr);
|
||||
RCTLogError(@"Invalid CGPath type %zd at element %zd of %@", type, i, arr);
|
||||
CGPathRelease(path);
|
||||
return NULL;
|
||||
}
|
||||
@@ -156,7 +158,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
case 3: // pattern
|
||||
return [[ARTPattern alloc] initWithArray:arr];
|
||||
default:
|
||||
RCTLogError(@"Unknown brush type: %llu", (unsigned long long)type);
|
||||
RCTLogError(@"Unknown brush type: %zd", type);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
@@ -165,7 +167,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
{
|
||||
NSArray *arr = [self NSArray:json];
|
||||
if (arr.count < offset + 2) {
|
||||
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(2 + offset), arr);
|
||||
RCTLogError(@"Too few elements in array (expected at least %zd): %@", 2 + offset, arr);
|
||||
return CGPointZero;
|
||||
}
|
||||
return (CGPoint){
|
||||
@@ -178,7 +180,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
{
|
||||
NSArray *arr = [self NSArray:json];
|
||||
if (arr.count < offset + 4) {
|
||||
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(4 + offset), arr);
|
||||
RCTLogError(@"Too few elements in array (expected at least %zd): %@", 4 + offset, arr);
|
||||
return CGRectZero;
|
||||
}
|
||||
return (CGRect){
|
||||
@@ -191,7 +193,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
{
|
||||
NSArray *arr = [self NSArray:json];
|
||||
if (arr.count < offset + 4) {
|
||||
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(4 + offset), arr);
|
||||
RCTLogError(@"Too few elements in array (expected at least %zd): %@", 4 + offset, arr);
|
||||
return NULL;
|
||||
}
|
||||
return [self CGColor:[arr subarrayWithRange:(NSRange){offset, 4}]];
|
||||
@@ -201,7 +203,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
{
|
||||
NSArray *arr = [self NSArray:json];
|
||||
if (arr.count < offset) {
|
||||
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)offset, arr);
|
||||
RCTLogError(@"Too few elements in array (expected at least %zd): %@", offset, arr);
|
||||
return NULL;
|
||||
}
|
||||
arr = [arr subarrayWithRange:(NSRange){offset, arr.count - offset}];
|
||||
|
||||
+122
-136
@@ -1,25 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @format
|
||||
* @providesModule ReactNativeART
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Color = require('art/core/color');
|
||||
const Path = require('ARTSerializablePath');
|
||||
const Transform = require('art/core/transform');
|
||||
var Color = require('art/core/color');
|
||||
var Path = require('ARTSerializablePath');
|
||||
var Transform = require('art/core/transform');
|
||||
|
||||
const React = require('React');
|
||||
const PropTypes = require('prop-types');
|
||||
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var React = require('React');
|
||||
var PropTypes = require('prop-types');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
|
||||
const createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
const merge = require('merge');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var merge = require('merge');
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
|
||||
// Diff Helpers
|
||||
|
||||
@@ -30,7 +31,7 @@ function arrayDiffer(a, b) {
|
||||
if (a.length !== b.length) {
|
||||
return true;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return true;
|
||||
}
|
||||
@@ -64,64 +65,61 @@ function fontAndLinesDiffer(a, b) {
|
||||
|
||||
// Native Attributes
|
||||
|
||||
const SurfaceViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
var SurfaceViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
// This should contain pixel information such as width, height and
|
||||
// resolution to know what kind of buffer needs to be allocated.
|
||||
// Currently we rely on UIViews and style to figure that out.
|
||||
});
|
||||
|
||||
const NodeAttributes = {
|
||||
transform: {diff: arrayDiffer},
|
||||
var NodeAttributes = {
|
||||
transform: { diff: arrayDiffer },
|
||||
opacity: true,
|
||||
};
|
||||
|
||||
const GroupAttributes = merge(NodeAttributes, {
|
||||
clipping: {diff: arrayDiffer},
|
||||
var GroupAttributes = merge(NodeAttributes, {
|
||||
clipping: { diff: arrayDiffer }
|
||||
});
|
||||
|
||||
const RenderableAttributes = merge(NodeAttributes, {
|
||||
fill: {diff: arrayDiffer},
|
||||
stroke: {diff: arrayDiffer},
|
||||
var RenderableAttributes = merge(NodeAttributes, {
|
||||
fill: { diff: arrayDiffer },
|
||||
stroke: { diff: arrayDiffer },
|
||||
strokeWidth: true,
|
||||
strokeCap: true,
|
||||
strokeJoin: true,
|
||||
strokeDash: {diff: arrayDiffer},
|
||||
strokeDash: { diff: arrayDiffer },
|
||||
});
|
||||
|
||||
const ShapeAttributes = merge(RenderableAttributes, {
|
||||
d: {diff: arrayDiffer},
|
||||
var ShapeAttributes = merge(RenderableAttributes, {
|
||||
d: { diff: arrayDiffer },
|
||||
});
|
||||
|
||||
const TextAttributes = merge(RenderableAttributes, {
|
||||
var TextAttributes = merge(RenderableAttributes, {
|
||||
alignment: true,
|
||||
frame: {diff: fontAndLinesDiffer},
|
||||
path: {diff: arrayDiffer},
|
||||
frame: { diff: fontAndLinesDiffer },
|
||||
path: { diff: arrayDiffer }
|
||||
});
|
||||
|
||||
// Native Components
|
||||
|
||||
const NativeSurfaceView = createReactNativeComponentClass(
|
||||
'ARTSurfaceView',
|
||||
() => ({
|
||||
validAttributes: SurfaceViewAttributes,
|
||||
uiViewClassName: 'ARTSurfaceView',
|
||||
}),
|
||||
);
|
||||
var NativeSurfaceView = createReactNativeComponentClass({
|
||||
validAttributes: SurfaceViewAttributes,
|
||||
uiViewClassName: 'ARTSurfaceView',
|
||||
});
|
||||
|
||||
const NativeGroup = createReactNativeComponentClass('ARTGroup', () => ({
|
||||
var NativeGroup = createReactNativeComponentClass({
|
||||
validAttributes: GroupAttributes,
|
||||
uiViewClassName: 'ARTGroup',
|
||||
}));
|
||||
});
|
||||
|
||||
const NativeShape = createReactNativeComponentClass('ARTShape', () => ({
|
||||
var NativeShape = createReactNativeComponentClass({
|
||||
validAttributes: ShapeAttributes,
|
||||
uiViewClassName: 'ARTShape',
|
||||
}));
|
||||
});
|
||||
|
||||
const NativeText = createReactNativeComponentClass('ARTText', () => ({
|
||||
var NativeText = createReactNativeComponentClass({
|
||||
validAttributes: TextAttributes,
|
||||
uiViewClassName: 'ARTText',
|
||||
}));
|
||||
});
|
||||
|
||||
// Utilities
|
||||
|
||||
@@ -146,15 +144,15 @@ class Surface extends React.Component {
|
||||
};
|
||||
|
||||
getChildContext() {
|
||||
return {isInSurface: true};
|
||||
return { isInSurface: true };
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const w = extractNumber(props.width, 0);
|
||||
const h = extractNumber(props.height, 0);
|
||||
var props = this.props;
|
||||
var w = extractNumber(props.width, 0);
|
||||
var h = extractNumber(props.height, 0);
|
||||
return (
|
||||
<NativeSurfaceView style={[props.style, {width: w, height: h}]}>
|
||||
<NativeSurfaceView style={[props.style, { width: w, height: h }]}>
|
||||
{this.props.children}
|
||||
</NativeSurfaceView>
|
||||
);
|
||||
@@ -173,13 +171,13 @@ function extractNumber(value, defaultValue) {
|
||||
return +value;
|
||||
}
|
||||
|
||||
const pooledTransform = new Transform();
|
||||
var pooledTransform = new Transform();
|
||||
|
||||
function extractTransform(props) {
|
||||
const scaleX =
|
||||
props.scaleX != null ? props.scaleX : props.scale != null ? props.scale : 1;
|
||||
const scaleY =
|
||||
props.scaleY != null ? props.scaleY : props.scale != null ? props.scale : 1;
|
||||
var scaleX = props.scaleX != null ? props.scaleX :
|
||||
props.scale != null ? props.scale : 1;
|
||||
var scaleY = props.scaleY != null ? props.scaleY :
|
||||
props.scale != null ? props.scale : 1;
|
||||
|
||||
pooledTransform
|
||||
.transformTo(1, 0, 0, 1, 0, 0)
|
||||
@@ -192,12 +190,9 @@ function extractTransform(props) {
|
||||
}
|
||||
|
||||
return [
|
||||
pooledTransform.xx,
|
||||
pooledTransform.yx,
|
||||
pooledTransform.xy,
|
||||
pooledTransform.yy,
|
||||
pooledTransform.x,
|
||||
pooledTransform.y,
|
||||
pooledTransform.xx, pooledTransform.yx,
|
||||
pooledTransform.xy, pooledTransform.yy,
|
||||
pooledTransform.x, pooledTransform.y,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -223,10 +218,10 @@ class Group extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
var props = this.props;
|
||||
invariant(
|
||||
this.context.isInSurface,
|
||||
'ART: <Group /> must be a child of a <Surface />',
|
||||
'ART: <Group /> must be a child of a <Surface />'
|
||||
);
|
||||
return (
|
||||
<NativeGroup
|
||||
@@ -240,14 +235,14 @@ class Group extends React.Component {
|
||||
|
||||
class ClippingRectangle extends React.Component {
|
||||
render() {
|
||||
const props = this.props;
|
||||
const x = extractNumber(props.x, 0);
|
||||
const y = extractNumber(props.y, 0);
|
||||
const w = extractNumber(props.width, 0);
|
||||
const h = extractNumber(props.height, 0);
|
||||
const clipping = [x, y, w, h];
|
||||
var props = this.props;
|
||||
var x = extractNumber(props.x, 0);
|
||||
var y = extractNumber(props.y, 0);
|
||||
var w = extractNumber(props.width, 0);
|
||||
var h = extractNumber(props.height, 0);
|
||||
var clipping = [x, y, w, h];
|
||||
// The current clipping API requires x and y to be ignored in the transform
|
||||
const propsExcludingXAndY = merge(props);
|
||||
var propsExcludingXAndY = merge(props);
|
||||
delete propsExcludingXAndY.x;
|
||||
delete propsExcludingXAndY.y;
|
||||
return (
|
||||
@@ -263,13 +258,13 @@ class ClippingRectangle extends React.Component {
|
||||
|
||||
// Renderables
|
||||
|
||||
const SOLID_COLOR = 0;
|
||||
const LINEAR_GRADIENT = 1;
|
||||
const RADIAL_GRADIENT = 2;
|
||||
const PATTERN = 3;
|
||||
var SOLID_COLOR = 0;
|
||||
var LINEAR_GRADIENT = 1;
|
||||
var RADIAL_GRADIENT = 2;
|
||||
var PATTERN = 3;
|
||||
|
||||
function insertColorIntoArray(color, targetArray, atIndex) {
|
||||
const c = new Color(color);
|
||||
var c = new Color(color);
|
||||
targetArray[atIndex + 0] = c.red / 255;
|
||||
targetArray[atIndex + 1] = c.green / 255;
|
||||
targetArray[atIndex + 2] = c.blue / 255;
|
||||
@@ -277,14 +272,14 @@ function insertColorIntoArray(color, targetArray, atIndex) {
|
||||
}
|
||||
|
||||
function insertColorsIntoArray(stops, targetArray, atIndex) {
|
||||
let i = 0;
|
||||
var i = 0;
|
||||
if ('length' in stops) {
|
||||
while (i < stops.length) {
|
||||
insertColorIntoArray(stops[i], targetArray, atIndex + i * 4);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
for (const offset in stops) {
|
||||
for (var offset in stops) {
|
||||
insertColorIntoArray(stops[offset], targetArray, atIndex + i * 4);
|
||||
i++;
|
||||
}
|
||||
@@ -293,17 +288,17 @@ function insertColorsIntoArray(stops, targetArray, atIndex) {
|
||||
}
|
||||
|
||||
function insertOffsetsIntoArray(stops, targetArray, atIndex, multi, reverse) {
|
||||
let offsetNumber;
|
||||
let i = 0;
|
||||
var offsetNumber;
|
||||
var i = 0;
|
||||
if ('length' in stops) {
|
||||
while (i < stops.length) {
|
||||
offsetNumber = (i / (stops.length - 1)) * multi;
|
||||
offsetNumber = i / (stops.length - 1) * multi;
|
||||
targetArray[atIndex + i] = reverse ? 1 - offsetNumber : offsetNumber;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
for (const offsetString in stops) {
|
||||
offsetNumber = +offsetString * multi;
|
||||
for (var offsetString in stops) {
|
||||
offsetNumber = (+offsetString) * multi;
|
||||
targetArray[atIndex + i] = reverse ? 1 - offsetNumber : offsetNumber;
|
||||
i++;
|
||||
}
|
||||
@@ -312,21 +307,21 @@ function insertOffsetsIntoArray(stops, targetArray, atIndex, multi, reverse) {
|
||||
}
|
||||
|
||||
function insertColorStopsIntoArray(stops, targetArray, atIndex) {
|
||||
const lastIndex = insertColorsIntoArray(stops, targetArray, atIndex);
|
||||
var lastIndex = insertColorsIntoArray(stops, targetArray, atIndex);
|
||||
insertOffsetsIntoArray(stops, targetArray, lastIndex, 1, false);
|
||||
}
|
||||
|
||||
function insertDoubleColorStopsIntoArray(stops, targetArray, atIndex) {
|
||||
let lastIndex = insertColorsIntoArray(stops, targetArray, atIndex);
|
||||
var lastIndex = insertColorsIntoArray(stops, targetArray, atIndex);
|
||||
lastIndex = insertColorsIntoArray(stops, targetArray, lastIndex);
|
||||
lastIndex = insertOffsetsIntoArray(stops, targetArray, lastIndex, 0.5, false);
|
||||
insertOffsetsIntoArray(stops, targetArray, lastIndex, 0.5, true);
|
||||
}
|
||||
|
||||
function applyBoundingBoxToBrushData(brushData, props) {
|
||||
const type = brushData[0];
|
||||
const width = +props.width;
|
||||
const height = +props.height;
|
||||
var type = brushData[0];
|
||||
var width = +props.width;
|
||||
var height = +props.height;
|
||||
if (type === LINEAR_GRADIENT) {
|
||||
brushData[1] *= width;
|
||||
brushData[2] *= height;
|
||||
@@ -360,7 +355,7 @@ function extractBrush(colorOrBrush, props) {
|
||||
}
|
||||
return colorOrBrush._brush;
|
||||
}
|
||||
const c = new Color(colorOrBrush);
|
||||
var c = new Color(colorOrBrush);
|
||||
return [SOLID_COLOR, c.red / 255, c.green / 255, c.blue / 255, c.alpha];
|
||||
}
|
||||
|
||||
@@ -368,29 +363,23 @@ function extractColor(color) {
|
||||
if (color == null) {
|
||||
return null;
|
||||
}
|
||||
const c = new Color(color);
|
||||
var c = new Color(color);
|
||||
return [c.red / 255, c.green / 255, c.blue / 255, c.alpha];
|
||||
}
|
||||
|
||||
function extractStrokeCap(strokeCap) {
|
||||
switch (strokeCap) {
|
||||
case 'butt':
|
||||
return 0;
|
||||
case 'square':
|
||||
return 2;
|
||||
default:
|
||||
return 1; // round
|
||||
case 'butt': return 0;
|
||||
case 'square': return 2;
|
||||
default: return 1; // round
|
||||
}
|
||||
}
|
||||
|
||||
function extractStrokeJoin(strokeJoin) {
|
||||
switch (strokeJoin) {
|
||||
case 'miter':
|
||||
return 0;
|
||||
case 'bevel':
|
||||
return 2;
|
||||
default:
|
||||
return 1; // round
|
||||
case 'miter': return 0;
|
||||
case 'bevel': return 2;
|
||||
default: return 1; // round
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,9 +390,9 @@ function extractStrokeJoin(strokeJoin) {
|
||||
|
||||
class Shape extends React.Component {
|
||||
render() {
|
||||
const props = this.props;
|
||||
const path = props.d || childrenAsString(props.children);
|
||||
const d = (path instanceof Path ? path : new Path(path)).toJSON();
|
||||
var props = this.props;
|
||||
var path = props.d || childrenAsString(props.children);
|
||||
var d = (path instanceof Path ? path : new Path(path)).toJSON();
|
||||
return (
|
||||
<NativeShape
|
||||
fill={extractBrush(props.fill, props)}
|
||||
@@ -414,6 +403,7 @@ class Shape extends React.Component {
|
||||
strokeJoin={extractStrokeJoin(props.strokeJoin)}
|
||||
strokeWidth={extractNumber(props.strokeWidth, 1)}
|
||||
transform={extractTransform(props)}
|
||||
|
||||
d={d}
|
||||
/>
|
||||
);
|
||||
@@ -422,34 +412,33 @@ class Shape extends React.Component {
|
||||
|
||||
// Text
|
||||
|
||||
const cachedFontObjectsFromString = {};
|
||||
var cachedFontObjectsFromString = {};
|
||||
|
||||
const fontFamilyPrefix = /^[\s"']*/;
|
||||
const fontFamilySuffix = /[\s"']*$/;
|
||||
var fontFamilyPrefix = /^[\s"']*/;
|
||||
var fontFamilySuffix = /[\s"']*$/;
|
||||
|
||||
function extractSingleFontFamily(fontFamilyString) {
|
||||
// ART on the web allows for multiple font-families to be specified.
|
||||
// For compatibility, we extract the first font-family, hoping
|
||||
// we'll get a match.
|
||||
return fontFamilyString
|
||||
.split(',')[0]
|
||||
.replace(fontFamilyPrefix, '')
|
||||
.replace(fontFamilySuffix, '');
|
||||
return fontFamilyString.split(',')[0]
|
||||
.replace(fontFamilyPrefix, '')
|
||||
.replace(fontFamilySuffix, '');
|
||||
}
|
||||
|
||||
function parseFontString(font) {
|
||||
if (cachedFontObjectsFromString.hasOwnProperty(font)) {
|
||||
return cachedFontObjectsFromString[font];
|
||||
}
|
||||
const regexp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?)[ptexm\%]*(?:\s*\/.*?)?\s+)?\s*\"?([^\"]*)/i;
|
||||
const match = regexp.exec(font);
|
||||
var regexp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?)[ptexm\%]*(?:\s*\/.*?)?\s+)?\s*\"?([^\"]*)/i;
|
||||
var match = regexp.exec(font);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const fontFamily = extractSingleFontFamily(match[3]);
|
||||
const fontSize = +match[2] || 12;
|
||||
const isBold = /bold/.exec(match[1]);
|
||||
const isItalic = /italic/.exec(match[1]);
|
||||
var fontFamily = extractSingleFontFamily(match[3]);
|
||||
var fontSize = +match[2] || 12;
|
||||
var isBold = /bold/.exec(match[1]);
|
||||
var isItalic = /italic/.exec(match[1]);
|
||||
cachedFontObjectsFromString[font] = {
|
||||
fontFamily: fontFamily,
|
||||
fontSize: fontSize,
|
||||
@@ -466,10 +455,9 @@ function extractFont(font) {
|
||||
if (typeof font === 'string') {
|
||||
return parseFontString(font);
|
||||
}
|
||||
const fontFamily = extractSingleFontFamily(font.fontFamily);
|
||||
const fontSize = +font.fontSize || 12;
|
||||
const fontWeight =
|
||||
font.fontWeight != null ? font.fontWeight.toString() : '400';
|
||||
var fontFamily = extractSingleFontFamily(font.fontFamily);
|
||||
var fontSize = +font.fontSize || 12;
|
||||
var fontWeight = font.fontWeight != null ? font.fontWeight.toString() : '400';
|
||||
return {
|
||||
// Normalize
|
||||
fontFamily: fontFamily,
|
||||
@@ -479,9 +467,9 @@ function extractFont(font) {
|
||||
};
|
||||
}
|
||||
|
||||
const newLine = /\n/g;
|
||||
var newLine = /\n/g;
|
||||
function extractFontAndLines(font, text) {
|
||||
return {font: extractFont(font), lines: text.split(newLine)};
|
||||
return { font: extractFont(font), lines: text.split(newLine) };
|
||||
}
|
||||
|
||||
function extractAlignment(alignment) {
|
||||
@@ -497,14 +485,12 @@ function extractAlignment(alignment) {
|
||||
|
||||
class Text extends React.Component {
|
||||
render() {
|
||||
const props = this.props;
|
||||
const path = props.path;
|
||||
const textPath = path
|
||||
? (path instanceof Path ? path : new Path(path)).toJSON()
|
||||
: null;
|
||||
const textFrame = extractFontAndLines(
|
||||
var props = this.props;
|
||||
var path = props.path;
|
||||
var textPath = path ? (path instanceof Path ? path : new Path(path)).toJSON() : null;
|
||||
var textFrame = extractFontAndLines(
|
||||
props.font,
|
||||
childrenAsString(props.children),
|
||||
childrenAsString(props.children)
|
||||
);
|
||||
return (
|
||||
<NativeText
|
||||
@@ -516,6 +502,7 @@ class Text extends React.Component {
|
||||
strokeJoin={extractStrokeJoin(props.strokeJoin)}
|
||||
strokeWidth={extractNumber(props.strokeWidth, 1)}
|
||||
transform={extractTransform(props)}
|
||||
|
||||
alignment={extractAlignment(props.alignment)}
|
||||
frame={textFrame}
|
||||
path={textPath}
|
||||
@@ -527,17 +514,16 @@ class Text extends React.Component {
|
||||
// Declarative fill type objects - API design not finalized
|
||||
|
||||
function LinearGradient(stops, x1, y1, x2, y2) {
|
||||
const type = LINEAR_GRADIENT;
|
||||
var type = LINEAR_GRADIENT;
|
||||
|
||||
if (arguments.length < 5) {
|
||||
const angle = ((x1 == null ? 270 : x1) * Math.PI) / 180;
|
||||
var angle = ((x1 == null) ? 270 : x1) * Math.PI / 180;
|
||||
|
||||
let x = Math.cos(angle);
|
||||
let y = -Math.sin(angle);
|
||||
const l = (Math.abs(x) + Math.abs(y)) / 2;
|
||||
var x = Math.cos(angle);
|
||||
var y = -Math.sin(angle);
|
||||
var l = (Math.abs(x) + Math.abs(y)) / 2;
|
||||
|
||||
x *= l;
|
||||
y *= l;
|
||||
x *= l; y *= l;
|
||||
|
||||
x1 = 0.5 - x;
|
||||
x2 = 0.5 + x;
|
||||
@@ -548,7 +534,7 @@ function LinearGradient(stops, x1, y1, x2, y2) {
|
||||
this._bb = false;
|
||||
}
|
||||
|
||||
const brushData = [type, +x1, +y1, +x2, +y2];
|
||||
var brushData = [type, +x1, +y1, +x2, +y2];
|
||||
insertColorStopsIntoArray(stops, brushData, 5);
|
||||
this._brush = brushData;
|
||||
}
|
||||
@@ -575,7 +561,7 @@ function RadialGradient(stops, fx, fy, rx, ry, cx, cy) {
|
||||
// To simulate this we render the gradient twice as large and add double
|
||||
// color stops. Ideally this API would become more restrictive so that this
|
||||
// extra work isn't needed.
|
||||
const brushData = [RADIAL_GRADIENT, +fx, +fy, +rx * 2, +ry * 2, +cx, +cy];
|
||||
var brushData = [RADIAL_GRADIENT, +fx, +fy, +rx * 2, +ry * 2, +cx, +cy];
|
||||
insertDoubleColorStopsIntoArray(stops, brushData, 7);
|
||||
this._brush = brushData;
|
||||
}
|
||||
@@ -584,7 +570,7 @@ function Pattern(url, width, height, left, top) {
|
||||
this._brush = [PATTERN, url, +left || 0, +top || 0, +width, +height];
|
||||
}
|
||||
|
||||
const ReactART = {
|
||||
var ReactART = {
|
||||
LinearGradient: LinearGradient,
|
||||
RadialGradient: RadialGradient,
|
||||
Pattern: Pattern,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTNodeManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTGroupManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <React/RCTViewManager.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTNodeManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTNodeManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTRenderableManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTRenderableManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTShapeManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import <React/RCTViewManager.h>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTSurfaceViewManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTRenderableManager.h"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#import "ARTTextManager.h"
|
||||
|
||||
@@ -1,62 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* @providesModule ActionSheetIOS
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const RCTActionSheetManager = require('NativeModules').ActionSheetManager;
|
||||
var RCTActionSheetManager = require('NativeModules').ActionSheetManager;
|
||||
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const processColor = require('processColor');
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
var processColor = require('processColor');
|
||||
|
||||
/**
|
||||
* Display action sheets and share sheets on iOS.
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/actionsheetios.html
|
||||
*/
|
||||
const ActionSheetIOS = {
|
||||
var ActionSheetIOS = {
|
||||
/**
|
||||
* Display an iOS action sheet.
|
||||
*
|
||||
* The `options` object must contain one or more of:
|
||||
* Display an iOS action sheet. The `options` object must contain one or more
|
||||
* of:
|
||||
*
|
||||
* - `options` (array of strings) - a list of button titles (required)
|
||||
* - `cancelButtonIndex` (int) - index of cancel button in `options`
|
||||
* - `destructiveButtonIndex` (int) - index of destructive button in `options`
|
||||
* - `title` (string) - a title to show above the action sheet
|
||||
* - `message` (string) - a message to show below the title
|
||||
*
|
||||
* The 'callback' function takes one parameter, the zero-based index
|
||||
* of the selected item.
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/actionsheetios.html#showactionsheetwithoptions
|
||||
*/
|
||||
showActionSheetWithOptions(
|
||||
options: {|
|
||||
+title?: ?string,
|
||||
+message?: ?string,
|
||||
+options: Array<string>,
|
||||
+destructiveButtonIndex?: ?number,
|
||||
+cancelButtonIndex?: ?number,
|
||||
+anchor?: ?number,
|
||||
+tintColor?: number | string,
|
||||
|},
|
||||
callback: (buttonIndex: number) => void,
|
||||
) {
|
||||
showActionSheetWithOptions(options: Object, callback: Function) {
|
||||
invariant(
|
||||
typeof options === 'object' && options !== null,
|
||||
'Options must be a valid object',
|
||||
'Options must be a valid object'
|
||||
);
|
||||
invariant(
|
||||
typeof callback === 'function',
|
||||
'Must provide a valid callback'
|
||||
);
|
||||
invariant(typeof callback === 'function', 'Must provide a valid callback');
|
||||
|
||||
RCTActionSheetManager.showActionSheetWithOptions(
|
||||
{...options, tintColor: processColor(options.tintColor)},
|
||||
callback,
|
||||
callback
|
||||
);
|
||||
},
|
||||
|
||||
@@ -68,44 +50,35 @@ const ActionSheetIOS = {
|
||||
* - `url` (string) - a URL to share
|
||||
* - `message` (string) - a message to share
|
||||
* - `subject` (string) - a subject for the message
|
||||
* - `excludedActivityTypes` (array) - the activities to exclude from
|
||||
* the ActionSheet
|
||||
* - `tintColor` (color) - tint color of the buttons
|
||||
* - `excludedActivityTypes` (array) - the activities to exclude from the ActionSheet
|
||||
*
|
||||
* The 'failureCallback' function takes one parameter, an error object.
|
||||
* The only property defined on this object is an optional `stack` property
|
||||
* of type `string`.
|
||||
*
|
||||
* The 'successCallback' function takes two parameters:
|
||||
*
|
||||
* - a boolean value signifying success or failure
|
||||
* - a string that, in the case of success, indicates the method of sharing
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/actionsheetios.html#showshareactionsheetwithoptions
|
||||
* NOTE: if `url` points to a local file, or is a base64-encoded
|
||||
* uri, the file it points to will be loaded and shared directly.
|
||||
* In this way, you can share images, videos, PDF files, etc.
|
||||
*/
|
||||
showShareActionSheetWithOptions(
|
||||
options: Object,
|
||||
failureCallback: Function,
|
||||
successCallback: Function,
|
||||
successCallback: Function
|
||||
) {
|
||||
invariant(
|
||||
typeof options === 'object' && options !== null,
|
||||
'Options must be a valid object',
|
||||
'Options must be a valid object'
|
||||
);
|
||||
invariant(
|
||||
typeof failureCallback === 'function',
|
||||
'Must provide a valid failureCallback',
|
||||
'Must provide a valid failureCallback'
|
||||
);
|
||||
invariant(
|
||||
typeof successCallback === 'function',
|
||||
'Must provide a valid successCallback',
|
||||
'Must provide a valid successCallback'
|
||||
);
|
||||
RCTActionSheetManager.showShareActionSheetWithOptions(
|
||||
{...options, tintColor: processColor(options.tintColor)},
|
||||
failureCallback,
|
||||
successCallback,
|
||||
successCallback
|
||||
);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ActionSheetIOS;
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
@@ -133,7 +132,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -174,7 +173,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user